Skip to content

Commit 16a4c61

Browse files
author
Junio C Hamano
committed
read-tree -m -u: avoid getting confused by intermediate symlinks.
When switching from a branch with both x86_64/boot/Makefile and i386/boot/Makefile to another branch that has x86_64/boot as a symlink pointing at ../i386/boot, the code incorrectly removed i386/boot/Makefile. This was because we first removed everything under x86_64/boot to make room to create a symbolic link x86_64/boot, then removed x86_64/boot/Makefile which no longer exists but now is pointing at i386/boot/Makefile, thanks to the symlink we just created. This fixes it by using the has_symlink_leading_path() function introduced previously for git-apply in the checkout codepath. Earlier, "git checkout" was broken in t4122 test due to this bug, and the test had an extra "git reset --hard" as a workaround, which is removed because it is not needed anymore. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 64cab59 commit 16a4c61

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

t/t4122-apply-symlink-inside.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ test_expect_success setup '
3434
test_expect_success apply '
3535
3636
git checkout test &&
37-
git reset --hard && #### checkout seems to be buggy
3837
git diff --exit-code test &&
3938
git diff --exit-code --cached test &&
4039
git apply --index test.patch

unpack-trees.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,12 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
264264
* directories, in case this unlink is the removal of the
265265
* last entry in the directory -- empty directories are removed.
266266
*/
267-
static void unlink_entry(char *name)
267+
static void unlink_entry(char *name, char *last_symlink)
268268
{
269269
char *cp, *prev;
270270

271+
if (has_symlink_leading_path(name, last_symlink))
272+
return;
271273
if (unlink(name))
272274
return;
273275
prev = NULL;
@@ -291,11 +293,12 @@ static void unlink_entry(char *name)
291293

292294
static struct checkout state;
293295
static void check_updates(struct cache_entry **src, int nr,
294-
struct unpack_trees_options *o)
296+
struct unpack_trees_options *o)
295297
{
296298
unsigned short mask = htons(CE_UPDATE);
297299
unsigned cnt = 0, total = 0;
298300
struct progress progress;
301+
char last_symlink[PATH_MAX];
299302

300303
if (o->update && o->verbose_update) {
301304
for (total = cnt = 0; cnt < nr; cnt++) {
@@ -309,6 +312,7 @@ static void check_updates(struct cache_entry **src, int nr,
309312
cnt = 0;
310313
}
311314

315+
*last_symlink = '\0';
312316
while (nr--) {
313317
struct cache_entry *ce = *src++;
314318

@@ -317,13 +321,15 @@ static void check_updates(struct cache_entry **src, int nr,
317321
display_progress(&progress, ++cnt);
318322
if (!ce->ce_mode) {
319323
if (o->update)
320-
unlink_entry(ce->name);
324+
unlink_entry(ce->name, last_symlink);
321325
continue;
322326
}
323327
if (ce->ce_flags & mask) {
324328
ce->ce_flags &= ~mask;
325-
if (o->update)
329+
if (o->update) {
326330
checkout_entry(ce, &state, NULL);
331+
*last_symlink = '\0';
332+
}
327333
}
328334
}
329335
if (total)

0 commit comments

Comments
 (0)