summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org.(none)>2005-04-19 18:16:12 (GMT)
committerLinus Torvalds <torvalds@ppc970.osdl.org.(none)>2005-04-19 18:16:12 (GMT)
commitca016f0e4e7e508407fe17e121fcd520fbb7c865 (patch)
treec5404b84a8df1badc32da2ba364f0485f4258e61
parent4aaef1064a1091ec38ab6adc823f26b82cf4998d (diff)
downloadgit-ca016f0e4e7e508407fe17e121fcd520fbb7c865.zip
git-ca016f0e4e7e508407fe17e121fcd520fbb7c865.tar.gz
git-ca016f0e4e7e508407fe17e121fcd520fbb7c865.tar.bz2
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.
-rw-r--r--read-tree.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/read-tree.c b/read-tree.c
index f507f16..abb5225 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");