[PATCH 24/32] merge: refuse to merge if narrow bases are different

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



commit_narrow_tree() works with a single narrow base. Unfortunately a
merge may have more than one parent. If all parents have the same
trees outside $GIT_DIR/narrow tree, then it's actually "a single
narrow base".

Other than that, refuse to merge. A merge in such case will need
server support because narrow repos do not have enough trees to
perform merge locally.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx>
---
 builtin/merge.c |   18 ++++++++++++++++++
 narrow-tree.c   |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 narrow-tree.h   |    1 +
 3 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 37ce4f5..c70d39d 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -25,6 +25,7 @@
 #include "help.h"
 #include "merge-recursive.h"
 #include "resolve-undo.h"
+#include "narrow-tree.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
@@ -1048,6 +1049,23 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			allow_trivial = 0;
 	}
 
+	if (get_narrow_prefix()) {
+		struct commit_list *item = remoteheads;
+		struct commit *head_commit = lookup_commit(head);
+
+		parse_commit(head_commit);
+		while (item) {
+			parse_commit(item->item);
+			if (!same_narrow_base(head_commit->tree->object.sha1,
+					      item->item->tree->object.sha1,
+					      get_narrow_prefix()))
+				break;
+			item = item->next;
+		}
+		if (item)
+			die("Different narrow base, couldn't do merge (yet)");
+	}
+
 	if (!remoteheads->next)
 		common = get_merge_bases(lookup_commit(head),
 				remoteheads->item, 1);
diff --git a/narrow-tree.c b/narrow-tree.c
index 73d4f22..4a16647 100644
--- a/narrow-tree.c
+++ b/narrow-tree.c
@@ -95,3 +95,58 @@ int join_narrow_tree(const unsigned char *base,
 	strbuf_release(&buffer);
 	return 0;
 }
+
+int same_narrow_base(const unsigned char *t1, const unsigned char *t2, const char *prefix)
+{
+	struct tree_desc desc1, desc2;
+	struct name_entry entry1, entry2;
+	char *buf1, *buf2;
+	enum object_type type;
+	unsigned long size;
+	const char *slash;
+	int prefix_len;
+
+	slash = strchr(prefix, '/');
+	prefix_len = slash ? slash - prefix : strlen(prefix);
+
+	buf1 = read_sha1_file(t1, &type, &size);
+	if (type != OBJ_TREE)
+		die("Bad tree %s", sha1_to_hex(t1));
+	init_tree_desc(&desc1, buf1, size);
+
+	buf2 = read_sha1_file(t2, &type, &size);
+	if (type != OBJ_TREE)
+		die("Bad tree %s", sha1_to_hex(t2));
+	init_tree_desc(&desc2, buf2, size);
+
+	while (tree_entry(&desc1, &entry1) && tree_entry(&desc2, &entry2)) {
+		if (strcmp(entry1.path, entry2.path) ||
+		    entry1.mode != entry2.mode) {
+			free(buf1);
+			free(buf2);
+			return 0;
+		}
+
+		if (!hashcmp(entry1.sha1, entry2.sha1))
+			continue;
+
+		if (S_ISDIR(entry1.mode) &&
+		    !strncmp(entry1.path, prefix, prefix_len) &&
+		    entry1.path[prefix_len] == '\0') {
+
+			/* This is subtree, SHA-1 does not matter */
+			if (!slash)
+				continue;
+
+			if (same_narrow_base(entry1.sha1, entry2.sha1, slash+1))
+				continue;
+		}
+
+		free(buf1);
+		free(buf2);
+		return 0;
+	}
+	free(buf1);
+	free(buf2);
+	return !desc1.size && !desc2.size;
+}
diff --git a/narrow-tree.h b/narrow-tree.h
index ecb3ded..8756094 100644
--- a/narrow-tree.h
+++ b/narrow-tree.h
@@ -1,3 +1,4 @@
 extern int check_narrow_prefix();
 extern int join_narrow_tree(const unsigned char *base, unsigned char *newsha1,
 			    const unsigned char *subtree_sha1, const char *prefix);
+int same_narrow_base(const unsigned char *t1, const unsigned char *t2, const char *prefix);
-- 
1.7.1.rc1.69.g24c2f7

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]