push: fix segfault for odd config
[gitweb.git] / unpack-trees.c
index 556813eca824b2c88db07df5db96e3c95ac95a56..e547282ed5c0027b35cbbd8e4f07bf968c6f2171 100644 (file)
@@ -61,7 +61,7 @@ static void unlink_entry(struct cache_entry *ce)
        char *cp, *prev;
        char *name = ce->name;
 
-       if (has_symlink_leading_path(ce_namelen(ce), ce->name))
+       if (has_symlink_or_noent_leading_path(ce_namelen(ce), ce->name))
                return;
        if (unlink(name))
                return;
@@ -240,8 +240,11 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
        return ce;
 }
 
-static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmask, struct cache_entry *src[5],
-       const struct name_entry *names, const struct traverse_info *info)
+static int unpack_nondirectories(int n, unsigned long mask,
+                                unsigned long dirmask,
+                                struct cache_entry **src,
+                                const struct name_entry *names,
+                                const struct traverse_info *info)
 {
        int i;
        struct unpack_trees_options *o = info->data;
@@ -291,7 +294,7 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
 
 static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
 {
-       struct cache_entry *src[5] = { NULL, };
+       struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
        struct unpack_trees_options *o = info->data;
        const struct name_entry *p = names;
 
@@ -352,7 +355,7 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
        discard_index(&o->result);
        if (!o->gently) {
                if (message)
-                       return error(message);
+                       return error("%s", message);
                return -1;
        }
        return -1;
@@ -376,12 +379,13 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        state.refresh_cache = 1;
 
        memset(&o->result, 0, sizeof(o->result));
+       o->result.initialized = 1;
        if (o->src_index)
                o->result.timestamp = o->src_index->timestamp;
        o->merge_size = len;
 
        if (!dfc)
-               dfc = xcalloc(1, sizeof(struct cache_entry) + 1);
+               dfc = xcalloc(1, cache_entry_size(0));
        o->df_conflict_entry = dfc;
 
        if (len) {
@@ -579,7 +583,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
        if (o->index_only || o->reset || !o->update)
                return 0;
 
-       if (has_symlink_leading_path(ce_namelen(ce), ce->name))
+       if (has_symlink_or_noent_leading_path(ce_namelen(ce), ce->name))
                return 0;
 
        if (!lstat(ce->name, &st)) {
@@ -938,8 +942,17 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
                        return -1;
                }
        }
-       else if (newtree)
+       else if (newtree) {
+               if (oldtree && !o->initial_checkout) {
+                       /*
+                        * deletion of the path was staged;
+                        */
+                       if (same(oldtree, newtree))
+                               return 1;
+                       return reject_merge(oldtree, o);
+               }
                return merged_entry(newtree, current, o);
+       }
        return deleted_entry(oldtree, current, o);
 }