]> git.ipfire.org Git - thirdparty/git.git/blobdiff - unpack-trees.c
unpack-trees: fix path search bug in verify_absent
[thirdparty/git.git] / unpack-trees.c
index 0de5a31c0b68f87491e540fdc1978809fee00240..48e538ab7eb7b5f31813780d381a25cabbef02cc 100644 (file)
@@ -358,8 +358,13 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
        return -1;
 }
 
+/*
+ * N-way merge "len" trees.  Returns 0 on success, -1 on failure to manipulate the
+ * resulting index, -2 on failure to reflect the changes to the work tree.
+ */
 int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)
 {
+       int ret;
        static struct cache_entry *dfc;
 
        if (len > MAX_UNPACK_TREES)
@@ -404,11 +409,10 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                return unpack_failed(o, "Merge requires file-level merging");
 
        o->src_index = NULL;
-       if (check_updates(o))
-               return -1;
+       ret = check_updates(o) ? (-2) : 0;
        if (o->dst_index)
                *o->dst_index = o->result;
-       return 0;
+       return ret;
 }
 
 /* Here come the merge functions */
@@ -512,22 +516,22 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
        namelen = strlen(ce->name);
        pos = index_name_pos(o->src_index, ce->name, namelen);
        if (0 <= pos)
-               return cnt; /* we have it as nondirectory */
+               return 0; /* we have it as nondirectory */
        pos = -pos - 1;
        for (i = pos; i < o->src_index->cache_nr; i++) {
-               struct cache_entry *ce = o->src_index->cache[i];
-               int len = ce_namelen(ce);
+               struct cache_entry *ce2 = o->src_index->cache[i];
+               int len = ce_namelen(ce2);
                if (len < namelen ||
-                   strncmp(ce->name, ce->name, namelen) ||
-                   ce->name[namelen] != '/')
+                   strncmp(ce->name, ce2->name, namelen) ||
+                   ce2->name[namelen] != '/')
                        break;
                /*
-                * ce->name is an entry in the subdirectory.
+                * ce2->name is an entry in the subdirectory.
                 */
-               if (!ce_stage(ce)) {
-                       if (verify_uptodate(ce, o))
+               if (!ce_stage(ce2)) {
+                       if (verify_uptodate(ce2, o))
                                return -1;
-                       add_entry(o, ce, CE_REMOVE, 0);
+                       add_entry(o, ce2, CE_REMOVE, 0);
                }
                cnt++;
        }
@@ -583,7 +587,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
                return 0;
 
        if (!lstat(ce->name, &st)) {
-               int cnt;
+               int ret;
                int dtype = ce_to_dtype(ce);
                struct cache_entry *result;
 
@@ -611,13 +615,15 @@ static int verify_absent(struct cache_entry *ce, const char *action,
                         * files that are in "foo/" we would lose
                         * it.
                         */
-                       cnt = verify_clean_subdirectory(ce, action, o);
+                       ret = verify_clean_subdirectory(ce, action, o);
+                       if (ret < 0)
+                               return ret;
 
                        /*
                         * If this removed entries from the index,
                         * what that means is:
                         *
-                        * (1) the caller unpack_trees_rec() saw path/foo
+                        * (1) the caller unpack_callback() saw path/foo
                         * in the index, and it has not removed it because
                         * it thinks it is handling 'path' as blob with
                         * D/F conflict;
@@ -630,7 +636,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
                         * We need to increment it by the number of
                         * deleted entries here.
                         */
-                       o->pos += cnt;
+                       o->pos += ret;
                        return 0;
                }