mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
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 <junkio@cox.net>
This commit is contained in:
parent
64cab59159
commit
16a4c6176a
|
@ -34,7 +34,6 @@ test_expect_success setup '
|
|||
test_expect_success apply '
|
||||
|
||||
git checkout test &&
|
||||
git reset --hard && #### checkout seems to be buggy
|
||||
git diff --exit-code test &&
|
||||
git diff --exit-code --cached test &&
|
||||
git apply --index test.patch
|
||||
|
|
|
@ -264,10 +264,12 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
|
|||
* directories, in case this unlink is the removal of the
|
||||
* last entry in the directory -- empty directories are removed.
|
||||
*/
|
||||
static void unlink_entry(char *name)
|
||||
static void unlink_entry(char *name, char *last_symlink)
|
||||
{
|
||||
char *cp, *prev;
|
||||
|
||||
if (has_symlink_leading_path(name, last_symlink))
|
||||
return;
|
||||
if (unlink(name))
|
||||
return;
|
||||
prev = NULL;
|
||||
|
@ -291,11 +293,12 @@ static void unlink_entry(char *name)
|
|||
|
||||
static struct checkout state;
|
||||
static void check_updates(struct cache_entry **src, int nr,
|
||||
struct unpack_trees_options *o)
|
||||
struct unpack_trees_options *o)
|
||||
{
|
||||
unsigned short mask = htons(CE_UPDATE);
|
||||
unsigned cnt = 0, total = 0;
|
||||
struct progress progress;
|
||||
char last_symlink[PATH_MAX];
|
||||
|
||||
if (o->update && o->verbose_update) {
|
||||
for (total = cnt = 0; cnt < nr; cnt++) {
|
||||
|
@ -309,6 +312,7 @@ static void check_updates(struct cache_entry **src, int nr,
|
|||
cnt = 0;
|
||||
}
|
||||
|
||||
*last_symlink = '\0';
|
||||
while (nr--) {
|
||||
struct cache_entry *ce = *src++;
|
||||
|
||||
|
@ -317,13 +321,15 @@ static void check_updates(struct cache_entry **src, int nr,
|
|||
display_progress(&progress, ++cnt);
|
||||
if (!ce->ce_mode) {
|
||||
if (o->update)
|
||||
unlink_entry(ce->name);
|
||||
unlink_entry(ce->name, last_symlink);
|
||||
continue;
|
||||
}
|
||||
if (ce->ce_flags & mask) {
|
||||
ce->ce_flags &= ~mask;
|
||||
if (o->update)
|
||||
if (o->update) {
|
||||
checkout_entry(ce, &state, NULL);
|
||||
*last_symlink = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (total)
|
||||
|
|
Loading…
Reference in a new issue