aboutsummaryrefslogtreecommitdiff
path: root/read-tree.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2005-06-07 11:36:30 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-07 11:41:51 -0700
commitc859600954df4c292ec7c81d7f2f9d0a62b5975b (patch)
tree4c2f1d9fae4deff6e82d0f32f11cc14cd67093c3 /read-tree.c
parent63aff4fed94355889be98ad44371e29942ff70e4 (diff)
downloadgit-c859600954df4c292ec7c81d7f2f9d0a62b5975b.tar.gz
git-c859600954df4c292ec7c81d7f2f9d0a62b5975b.tar.xz
[PATCH] read-tree: save more user hassles during fast-forward.
This implements the "never lose the current cache information or the work tree state, but favor a successful merge over merge failure" principle in the fast-forward two-tree merge operation. It comes with a set of tests to cover all the cases described in the case matrix found in the new documentation. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'read-tree.c')
-rw-r--r--read-tree.c49
1 files changed, 36 insertions, 13 deletions
diff --git a/read-tree.c b/read-tree.c
index 2fb27e974..8eb243212 100644
--- a/read-tree.c
+++ b/read-tree.c
@@ -155,28 +155,51 @@ static int threeway_merge(struct cache_entry *stages[4], struct cache_entry **ds
/*
* Two-way merge.
*
- * The rule is:
- * - every current entry has to match the old tree
- * - if the current entry matches the new tree, we leave it
- * as-is. Otherwise we require that it be up-to-date.
+ * The rule is to "carry forward" what is in the index without losing
+ * information across a "fast forward", favoring a successful merge
+ * over a merge failure when it makes sense. For details of the
+ * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
+ *
*/
static int twoway_merge(struct cache_entry **src, struct cache_entry **dst)
{
- struct cache_entry *old = src[0];
- struct cache_entry *a = src[1], *b = src[2];
+ struct cache_entry *current = src[0];
+ struct cache_entry *oldtree = src[1], *newtree = src[2];
if (src[3])
return -1;
- if (old) {
- if (!a || !same(old, a))
+ if (current) {
+ if ((!oldtree && !newtree) || /* 4 and 5 */
+ (!oldtree && newtree &&
+ same(current, newtree)) || /* 6 and 7 */
+ (oldtree && newtree &&
+ same(oldtree, newtree)) || /* 14 and 15 */
+ (oldtree && newtree &&
+ !same(oldtree, newtree) && /* 18 and 19*/
+ same(current, newtree))) {
+ *dst++ = current;
+ return 1;
+ }
+ else if (oldtree && !newtree && same(current, oldtree)) {
+ /* 10 or 11 */
+ verify_uptodate(current);
+ return 0;
+ }
+ else if (oldtree && newtree &&
+ same(current, oldtree) && !same(current, newtree)) {
+ /* 20 or 21 */
+ verify_uptodate(current);
+ return merged_entry(newtree, NULL, dst);
+ }
+ else
+ /* all other failures */
return -1;
}
- if (b)
- return merged_entry(b, old, dst);
- if (old)
- verify_uptodate(old);
- return 0;
+ else if (newtree)
+ return merged_entry(newtree, NULL, dst);
+ else
+ return 0;
}
/*