Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 00197c3

Browse files
author
Vicent Martí
committed
Merge pull request libgit2#1664 from arrbee/checkout-deleted-with-fix
Checkout should not recreate deleted files - with fix
2 parents f2d110f + 36fd9e3 commit 00197c3

File tree

5 files changed

+158
-1
lines changed

5 files changed

+158
-1
lines changed

include/git2/checkout.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ typedef enum {
183183
GIT_CHECKOUT_NOTIFY_UPDATED = (1u << 2),
184184
GIT_CHECKOUT_NOTIFY_UNTRACKED = (1u << 3),
185185
GIT_CHECKOUT_NOTIFY_IGNORED = (1u << 4),
186+
187+
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFFu
186188
} git_checkout_notify_t;
187189

188190
/** Checkout notification callback function */

src/checkout.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,11 @@ static int checkout_action_no_wd(
220220
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE);
221221
break;
222222
case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */
223-
case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
224223
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
225224
break;
225+
case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
226+
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT);
227+
break;
226228
case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/
227229
if (delta->new_file.mode == GIT_FILEMODE_TREE)
228230
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);

tests-clar/checkout/checkout_helpers.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,98 @@ void check_file_contents_nocr_at_line(
9191
{
9292
check_file_contents_internal(path, expected, true, file, line, msg);
9393
}
94+
95+
int checkout_count_callback(
96+
git_checkout_notify_t why,
97+
const char *path,
98+
const git_diff_file *baseline,
99+
const git_diff_file *target,
100+
const git_diff_file *workdir,
101+
void *payload)
102+
{
103+
checkout_counts *ct = payload;
104+
105+
GIT_UNUSED(baseline); GIT_UNUSED(target); GIT_UNUSED(workdir);
106+
107+
if (why & GIT_CHECKOUT_NOTIFY_CONFLICT) {
108+
ct->n_conflicts++;
109+
110+
if (ct->debug) {
111+
if (workdir) {
112+
if (baseline) {
113+
if (target)
114+
fprintf(stderr, "M %s (conflicts with M %s)\n",
115+
workdir->path, target->path);
116+
else
117+
fprintf(stderr, "M %s (conflicts with D %s)\n",
118+
workdir->path, baseline->path);
119+
} else {
120+
if (target)
121+
fprintf(stderr, "Existing %s (conflicts with A %s)\n",
122+
workdir->path, target->path);
123+
else
124+
fprintf(stderr, "How can an untracked file be a conflict (%s)\n", workdir->path);
125+
}
126+
} else {
127+
if (baseline) {
128+
if (target)
129+
fprintf(stderr, "D %s (conflicts with M %s)\n",
130+
target->path, baseline->path);
131+
else
132+
fprintf(stderr, "D %s (conflicts with D %s)\n",
133+
baseline->path, baseline->path);
134+
} else {
135+
if (target)
136+
fprintf(stderr, "How can an added file with no workdir be a conflict (%s)\n", target->path);
137+
else
138+
fprintf(stderr, "How can a nonexistent file be a conflict (%s)\n", path);
139+
}
140+
}
141+
}
142+
}
143+
144+
if (why & GIT_CHECKOUT_NOTIFY_DIRTY) {
145+
ct->n_dirty++;
146+
147+
if (ct->debug) {
148+
if (workdir)
149+
fprintf(stderr, "M %s\n", workdir->path);
150+
else
151+
fprintf(stderr, "D %s\n", baseline->path);
152+
}
153+
}
154+
155+
if (why & GIT_CHECKOUT_NOTIFY_UPDATED) {
156+
ct->n_updates++;
157+
158+
if (ct->debug) {
159+
if (baseline) {
160+
if (target)
161+
fprintf(stderr, "update: M %s\n", path);
162+
else
163+
fprintf(stderr, "update: D %s\n", path);
164+
} else {
165+
if (target)
166+
fprintf(stderr, "update: A %s\n", path);
167+
else
168+
fprintf(stderr, "update: this makes no sense %s\n", path);
169+
}
170+
}
171+
}
172+
173+
if (why & GIT_CHECKOUT_NOTIFY_UNTRACKED) {
174+
ct->n_untracked++;
175+
176+
if (ct->debug)
177+
fprintf(stderr, "? %s\n", path);
178+
}
179+
180+
if (why & GIT_CHECKOUT_NOTIFY_IGNORED) {
181+
ct->n_ignored++;
182+
183+
if (ct->debug)
184+
fprintf(stderr, "I %s\n", path);
185+
}
186+
187+
return 0;
188+
}

tests-clar/checkout/checkout_helpers.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,20 @@ extern void check_file_contents_nocr_at_line(
1919

2020
#define check_file_contents_nocr(PATH,EXP) \
2121
check_file_contents_nocr_at_line(PATH,EXP,__FILE__,__LINE__,"String mismatch: " #EXP " != " #PATH)
22+
23+
typedef struct {
24+
int n_conflicts;
25+
int n_dirty;
26+
int n_updates;
27+
int n_untracked;
28+
int n_ignored;
29+
int debug;
30+
} checkout_counts;
31+
32+
extern int checkout_count_callback(
33+
git_checkout_notify_t why,
34+
const char *path,
35+
const git_diff_file *baseline,
36+
const git_diff_file *target,
37+
const git_diff_file *workdir,
38+
void *payload);

tests-clar/checkout/tree.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,47 @@ void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERG
442442
assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c");
443443
}
444444

445+
void test_checkout_tree__donot_update_deleted_file_by_default(void)
446+
{
447+
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
448+
git_oid old_id, new_id;
449+
git_commit *old_commit = NULL, *new_commit = NULL;
450+
git_index *index = NULL;
451+
checkout_counts ct;
452+
453+
opts.checkout_strategy = GIT_CHECKOUT_SAFE;
454+
455+
memset(&ct, 0, sizeof(ct));
456+
opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL;
457+
opts.notify_cb = checkout_count_callback;
458+
opts.notify_payload = &ct;
459+
460+
cl_git_pass(git_repository_index(&index, g_repo));
461+
462+
cl_git_pass(git_oid_fromstr(&old_id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"));
463+
cl_git_pass(git_commit_lookup(&old_commit, g_repo, &old_id));
464+
cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD));
465+
466+
cl_git_pass(p_unlink("testrepo/branch_file.txt"));
467+
cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt"));
468+
cl_git_pass(git_index_write(index));
469+
470+
cl_assert(!git_path_exists("testrepo/branch_file.txt"));
471+
472+
cl_git_pass(git_oid_fromstr(&new_id, "099fabac3a9ea935598528c27f866e34089c2eff"));
473+
cl_git_pass(git_commit_lookup(&new_commit, g_repo, &new_id));
474+
475+
476+
cl_git_fail(git_checkout_tree(g_repo, (git_object *)new_commit, &opts));
477+
478+
cl_assert_equal_i(1, ct.n_conflicts);
479+
cl_assert_equal_i(1, ct.n_updates);
480+
481+
git_commit_free(old_commit);
482+
git_commit_free(new_commit);
483+
git_index_free(index);
484+
}
485+
445486
void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
446487
{
447488
git_index *index = NULL;

0 commit comments

Comments
 (0)