Code

Don't smash stack when $GIT_ALTERNATE_OBJECT_DIRECTORIES is too long
[git.git] / unpack-trees.c
index 675a9998dcbab528faf2cf34ab1a66f884a36300..cac2411b9de7b4889abe6b0b84df25d24a38c7e5 100644 (file)
@@ -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)
@@ -408,10 +414,6 @@ static void verify_uptodate(struct cache_entry *ce,
                        return;
                errno = 0;
        }
-       if (o->reset) {
-               ce->ce_flags |= htons(CE_UPDATE);
-               return;
-       }
        if (errno == ENOENT)
                return;
        die("Entry '%s' not uptodate. Cannot merge.", ce->name);