From: Linus Torvalds Date: Tue, 19 Apr 2005 18:16:12 +0000 (-0700) Subject: Make "read-tree" take the 'stat' information for a merge result from the X-Git-Tag: v0.99~812 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ca016f0e4e7e508407fe17e121fcd520fbb7c865;p=git.git 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. --- diff --git a/read-tree.c b/read-tree.c index f507f1633..abb522550 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");