X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unpack-trees.c;h=a59f47557a2b3760c27b93fa678697c35211f952;hb=4afbcab9898ce63ad641dd0de6e9b69deda44330;hp=0cdf19817d65ef8b054b8399981be164c8ee7542;hpb=34110cd4e394e3f92c01a4709689b384c34645d8;p=git.git diff --git a/unpack-trees.c b/unpack-trees.c index 0cdf19817..a59f47557 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -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; }