From ca016f0e4e7e508407fe17e121fcd520fbb7c865 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 19 Apr 2005 11:16:12 -0700 Subject: [PATCH] Make "read-tree" take the 'stat' information for a merge result from the old index state if the result matches. This leaves the stat information in the result tree for any trivial merges, which is just the way we like it. --- read-tree.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/read-tree.c b/read-tree.c index f507f1633c..abb522550f 100644 --- a/read-tree.c +++ b/read-tree.c @@ -73,6 +73,13 @@ static void remove_lock_file(void) unlink(".git/index.lock"); } +static int path_matches(struct cache_entry *a, struct cache_entry *b) +{ + int len = ce_namelen(a); + return ce_namelen(b) == len && + !memcmp(a->name, b->name, len); +} + static int same(struct cache_entry *a, struct cache_entry *b) { return a->ce_mode == b->ce_mode && @@ -132,13 +139,30 @@ static struct cache_entry *merge_entries(struct cache_entry *a, static void trivially_merge_cache(struct cache_entry **src, int nr) { + static struct cache_entry null_entry; struct cache_entry **dst = src; + struct cache_entry *old = &null_entry; while (nr) { struct cache_entry *ce, *result; ce = src[0]; + + /* We throw away original cache entries except for the stat information */ + if (!ce_stage(ce)) { + old = ce; + src++; + nr--; + active_nr--; + continue; + } if (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) { + /* + * See if we can re-use the old CE directly? + * That way we get the uptodate stat info. + */ + if (path_matches(result, old) && same(result, old)) + *result = *old; ce = result; ce->ce_flags &= ~htons(CE_STAGEMASK); src += 2; @@ -154,7 +178,7 @@ static void trivially_merge_cache(struct cache_entry **src, int nr) int main(int argc, char **argv) { - int i, newfd; + int i, newfd, merge; unsigned char sha1[20]; newfd = open(".git/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600); @@ -163,12 +187,22 @@ int main(int argc, char **argv) atexit(remove_lock_file); remove_lock = 1; + merge = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; /* "-m" stands for "merge", meaning we start in stage 1 */ if (!strcmp(arg, "-m")) { + int i; + if (stage) + usage("-m needs to come first"); + read_cache(); + for (i = 0; i < active_nr; i++) { + if (ce_stage(active_cache[i])) + usage("you need to resolve your current index first"); + } stage = 1; + merge = 1; continue; } if (get_sha1_hex(arg, sha1) < 0) @@ -179,8 +213,11 @@ int main(int argc, char **argv) die("failed to unpack tree object %s", arg); stage++; } - if (stage == 4) + if (merge) { + if (stage != 4) + usage("I need three trees to merge: original, branch1 and branch2"); trivially_merge_cache(active_cache, active_nr); + } if (write_cache(newfd, active_cache, active_nr) || rename(".git/index.lock", ".git/index")) die("unable to write new index file");