Commit 00197c34 by Vicent Martí

Merge pull request #1664 from arrbee/checkout-deleted-with-fix

Checkout should not recreate deleted files - with fix
parents f2d110f1 36fd9e30
...@@ -183,6 +183,8 @@ typedef enum { ...@@ -183,6 +183,8 @@ typedef enum {
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2), GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3), GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4), GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu
} git_checkout_notify_t; } git_checkout_notify_t;
/** Checkout notification callback function */ /** Checkout notification callback function */
......
...@@ -220,9 +220,11 @@ static int checkout_action_no_wd( ...@@ -220,9 +220,11 @@ static int checkout_action_no_wd(
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE); action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE);
break; break;
case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */ 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); action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
break; 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)*/ case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/
if (delta->new_file.mode == GIT_FILEMODE_TREE) if (delta->new_file.mode == GIT_FILEMODE_TREE)
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
......
...@@ -91,3 +91,98 @@ void check_file_contents_nocr_at_line( ...@@ -91,3 +91,98 @@ void check_file_contents_nocr_at_line(
{ {
check_file_contents_internal(path, expected, true, file, line, msg); 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( ...@@ -19,3 +19,20 @@ extern void check_file_contents_nocr_at_line(
#define check_file_contents_nocr(PATH,EXP) \ #define check_file_contents_nocr(PATH,EXP) \
check_file_contents_nocr_at_line(PATH,EXP,__FILE__,__LINE__,"String mismatch: " #EXP " != " #PATH) 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 ...@@ -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"); 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) void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
{ {
git_index *index = NULL; git_index *index = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment