summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2007-05-11 06:44:53 (GMT)
committerJunio C Hamano <junkio@cox.net>2007-05-12 05:33:31 (GMT)
commit16a4c6176ad096881d0021f1a922fbcc2835f799 (patch)
tree14719b93b49e50f6566a3f60a8e6299a05017901 /unpack-trees.c
parent64cab59159d1308365d56e218a10bfc0d3cd0fd0 (diff)
downloadgit-16a4c6176ad096881d0021f1a922fbcc2835f799.zip
git-16a4c6176ad096881d0021f1a922fbcc2835f799.tar.gz
git-16a4c6176ad096881d0021f1a922fbcc2835f799.tar.bz2
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>
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index 675a999..906ce69 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -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)