]> asedeno.scripts.mit.edu Git - git.git/blobdiff - unpack-trees.c
Make ls-remote http://... list HEAD, like for git://...
[git.git] / unpack-trees.c
index 0cdf19817d65ef8b054b8399981be164c8ee7542..a59f47557a2b3760c27b93fa678697c35211f952 100644 (file)
@@ -54,13 +54,14 @@ static void unlink_entry(char *name, char *last_symlink)
 }
 
 static struct checkout state;
-static void check_updates(struct unpack_trees_options *o)
+static int check_updates(struct unpack_trees_options *o)
 {
        unsigned cnt = 0, total = 0;
        struct progress *progress = NULL;
        char last_symlink[PATH_MAX];
        struct index_state *index = &o->result;
        int i;
+       int errs = 0;
 
        if (o->update && o->verbose_update) {
                for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
@@ -90,12 +91,13 @@ static void check_updates(struct unpack_trees_options *o)
                if (ce->ce_flags & CE_UPDATE) {
                        ce->ce_flags &= ~CE_UPDATE;
                        if (o->update) {
-                               checkout_entry(ce, &state, NULL);
+                               errs |= checkout_entry(ce, &state, NULL);
                                *last_symlink = '\0';
                        }
                }
        }
        stop_progress(&progress);
+       return errs != 0;
 }
 
 static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
@@ -116,7 +118,6 @@ static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_option
                        add_entry(o, ce, 0, 0);
                        return 0;
                }
-               return 0;
        }
        return call_unpack_fn(src, o);
 }
@@ -124,7 +125,7 @@ static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_option
 int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long df_conflicts, struct name_entry *names, struct traverse_info *info)
 {
        int i;
-       struct tree_desc t[3];
+       struct tree_desc t[MAX_UNPACK_TREES];
        struct traverse_info newinfo;
        struct name_entry *p;
 
@@ -144,8 +145,7 @@ int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long df_conf
                        sha1 = names[i].sha1;
                fill_tree_descriptor(t+i, sha1);
        }
-       traverse_trees(n, t, &newinfo);
-       return 0;
+       return traverse_trees(n, t, &newinfo);
 }
 
 /*
@@ -287,7 +287,6 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
                                                add_entry(o, ce, 0, 0);
                                                return mask;
                                        }
-                                       continue;
                                }
                                src[0] = ce;
                        }
@@ -306,7 +305,9 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
                        if (src[0])
                                conflicts |= 1;
                }
-               traverse_trees_recursive(n, dirmask, conflicts, names, info);
+               if (traverse_trees_recursive(n, dirmask, conflicts,
+                                            names, info) < 0)
+                       return -1;
                return mask;
        }
 
@@ -315,6 +316,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
 
 static int unpack_failed(struct unpack_trees_options *o, const char *message)
 {
+       discard_index(&o->result);
        if (!o->gently) {
                if (message)
                        return error(message);
@@ -327,8 +329,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 {
        static struct cache_entry *dfc;
 
-       if (len > 4)
-               die("unpack_trees takes at most four trees");
+       if (len > MAX_UNPACK_TREES)
+               die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES);
        memset(&state, 0, sizeof(state));
        state.base_dir = "";
        state.force = 1;
@@ -336,6 +338,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        state.refresh_cache = 1;
 
        memset(&o->result, 0, sizeof(o->result));
+       if (o->src_index)
+               o->result.timestamp = o->src_index->timestamp;
        o->merge_size = len;
 
        if (!dfc)
@@ -367,7 +371,8 @@ 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;
-       check_updates(o);
+       if (check_updates(o))
+               return -1;
        if (o->dst_index)
                *o->dst_index = o->result;
        return 0;
@@ -593,16 +598,19 @@ static int verify_absent(struct cache_entry *ce, const char *action,
 static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
                struct unpack_trees_options *o)
 {
+       int update = CE_UPDATE;
+
        if (old) {
                /*
                 * See if we can re-use the old CE directly?
                 * That way we get the uptodate stat info.
                 *
-                * This also removes the UPDATE flag on
-                * a match.
+                * This also removes the UPDATE flag on a match; otherwise
+                * we will end up overwriting local changes in the work tree.
                 */
                if (same(old, merge)) {
                        copy_cache_entry(merge, old);
+                       update = 0;
                } else {
                        if (verify_uptodate(old, o))
                                return -1;
@@ -615,7 +623,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
                invalidate_ce_path(merge, o);
        }
 
-       add_entry(o, merge, CE_UPDATE, CE_STAGEMASK);
+       add_entry(o, merge, update, CE_STAGEMASK);
        return 1;
 }