mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-19 17:03:58 +00:00
Merge pull request #1664 from arrbee/checkout-deleted-with-fix
Checkout should not recreate deleted files - with fix
This commit is contained in:
commit
00197c34d6
@ -183,6 +183,8 @@ typedef enum {
|
||||
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
|
||||
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
|
||||
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
|
||||
|
||||
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu
|
||||
} git_checkout_notify_t;
|
||||
|
||||
/** Checkout notification callback function */
|
||||
|
@ -220,9 +220,11 @@ static int checkout_action_no_wd(
|
||||
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */
|
||||
case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
|
||||
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/
|
||||
if (delta->new_file.mode == GIT_FILEMODE_TREE)
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
|
@ -91,3 +91,98 @@ void check_file_contents_nocr_at_line(
|
||||
{
|
||||
check_file_contents_internal(path, expected, true, file, line, msg);
|
||||
}
|
||||
|
||||
int checkout_count_callback(
|
||||
git_checkout_notify_t why,
|
||||
const char *path,
|
||||
const git_diff_file *baseline,
|
||||
const git_diff_file *target,
|
||||
const git_diff_file *workdir,
|
||||
void *payload)
|
||||
{
|
||||
checkout_counts *ct = payload;
|
||||
|
||||
GIT_UNUSED(baseline); GIT_UNUSED(target); GIT_UNUSED(workdir);
|
||||
|
||||
if (why & GIT_CHECKOUT_NOTIFY_CONFLICT) {
|
||||
ct->n_conflicts++;
|
||||
|
||||
if (ct->debug) {
|
||||
if (workdir) {
|
||||
if (baseline) {
|
||||
if (target)
|
||||
fprintf(stderr, "M %s (conflicts with M %s)\n",
|
||||
workdir->path, target->path);
|
||||
else
|
||||
fprintf(stderr, "M %s (conflicts with D %s)\n",
|
||||
workdir->path, baseline->path);
|
||||
} else {
|
||||
if (target)
|
||||
fprintf(stderr, "Existing %s (conflicts with A %s)\n",
|
||||
workdir->path, target->path);
|
||||
else
|
||||
fprintf(stderr, "How can an untracked file be a conflict (%s)\n", workdir->path);
|
||||
}
|
||||
} else {
|
||||
if (baseline) {
|
||||
if (target)
|
||||
fprintf(stderr, "D %s (conflicts with M %s)\n",
|
||||
target->path, baseline->path);
|
||||
else
|
||||
fprintf(stderr, "D %s (conflicts with D %s)\n",
|
||||
baseline->path, baseline->path);
|
||||
} else {
|
||||
if (target)
|
||||
fprintf(stderr, "How can an added file with no workdir be a conflict (%s)\n", target->path);
|
||||
else
|
||||
fprintf(stderr, "How can a nonexistent file be a conflict (%s)\n", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (why & GIT_CHECKOUT_NOTIFY_DIRTY) {
|
||||
ct->n_dirty++;
|
||||
|
||||
if (ct->debug) {
|
||||
if (workdir)
|
||||
fprintf(stderr, "M %s\n", workdir->path);
|
||||
else
|
||||
fprintf(stderr, "D %s\n", baseline->path);
|
||||
}
|
||||
}
|
||||
|
||||
if (why & GIT_CHECKOUT_NOTIFY_UPDATED) {
|
||||
ct->n_updates++;
|
||||
|
||||
if (ct->debug) {
|
||||
if (baseline) {
|
||||
if (target)
|
||||
fprintf(stderr, "update: M %s\n", path);
|
||||
else
|
||||
fprintf(stderr, "update: D %s\n", path);
|
||||
} else {
|
||||
if (target)
|
||||
fprintf(stderr, "update: A %s\n", path);
|
||||
else
|
||||
fprintf(stderr, "update: this makes no sense %s\n", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (why & GIT_CHECKOUT_NOTIFY_UNTRACKED) {
|
||||
ct->n_untracked++;
|
||||
|
||||
if (ct->debug)
|
||||
fprintf(stderr, "? %s\n", path);
|
||||
}
|
||||
|
||||
if (why & GIT_CHECKOUT_NOTIFY_IGNORED) {
|
||||
ct->n_ignored++;
|
||||
|
||||
if (ct->debug)
|
||||
fprintf(stderr, "I %s\n", path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,3 +19,20 @@ extern void check_file_contents_nocr_at_line(
|
||||
|
||||
#define check_file_contents_nocr(PATH,EXP) \
|
||||
check_file_contents_nocr_at_line(PATH,EXP,__FILE__,__LINE__,"String mismatch: " #EXP " != " #PATH)
|
||||
|
||||
typedef struct {
|
||||
int n_conflicts;
|
||||
int n_dirty;
|
||||
int n_updates;
|
||||
int n_untracked;
|
||||
int n_ignored;
|
||||
int debug;
|
||||
} checkout_counts;
|
||||
|
||||
extern int checkout_count_callback(
|
||||
git_checkout_notify_t why,
|
||||
const char *path,
|
||||
const git_diff_file *baseline,
|
||||
const git_diff_file *target,
|
||||
const git_diff_file *workdir,
|
||||
void *payload);
|
||||
|
@ -442,6 +442,47 @@ void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERG
|
||||
assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c");
|
||||
}
|
||||
|
||||
void test_checkout_tree__donot_update_deleted_file_by_default(void)
|
||||
{
|
||||
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||
git_oid old_id, new_id;
|
||||
git_commit *old_commit = NULL, *new_commit = NULL;
|
||||
git_index *index = NULL;
|
||||
checkout_counts ct;
|
||||
|
||||
opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
||||
|
||||
memset(&ct, 0, sizeof(ct));
|
||||
opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
|
||||
opts.notify_cb = checkout_count_callback;
|
||||
opts.notify_payload = &ct;
|
||||
|
||||
cl_git_pass(git_repository_index(&index, g_repo));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&old_id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
|
||||
cl_git_pass(git_commit_lookup(&old_commit, g_repo, &old_id));
|
||||
cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD));
|
||||
|
||||
cl_git_pass(p_unlink("testrepo/branch_file.txt"));
|
||||
cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt"));
|
||||
cl_git_pass(git_index_write(index));
|
||||
|
||||
cl_assert(!git_path_exists("testrepo/branch_file.txt"));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&new_id, "099fabac3a9ea935598528c27f866e34089c2eff"));
|
||||
cl_git_pass(git_commit_lookup(&new_commit, g_repo, &new_id));
|
||||
|
||||
|
||||
cl_git_fail(git_checkout_tree(g_repo, (git_object *)new_commit, &opts));
|
||||
|
||||
cl_assert_equal_i(1, ct.n_conflicts);
|
||||
cl_assert_equal_i(1, ct.n_updates);
|
||||
|
||||
git_commit_free(old_commit);
|
||||
git_commit_free(new_commit);
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
|
||||
{
|
||||
git_index *index = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user