Subject: [PATCH v2 5/8] commit.c: refuse to write commits referring to external objects

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Tue, 30 Apr 2013 10:42:49 +0700

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 cache.h     | 1 +
 commit.c    | 9 +++++++++
 sha1_file.c | 7 +++++++
 3 files changed, 17 insertions(+)

diff --git a/cache.h b/cache.h
index bc3ccd8..57b6d30 100644
--- a/cache.h
+++ b/cache.h
@@ -804,6 +804,7 @@ extern int move_temp_to_file(const char *tmpfile, const char *filename);
 
 extern int has_sha1_pack(const unsigned char *sha1);
 extern int has_sha1_file(const unsigned char *sha1);
+extern int has_sha1_file_proper(const unsigned char *sha1);
 extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
 extern int has_pack_index(const unsigned char *sha1);
diff --git a/commit.c b/commit.c
index 888e02a..3edbe22 100644
--- a/commit.c
+++ b/commit.c
@@ -1343,6 +1343,10 @@ int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
 	/* Not having i18n.commitencoding is the same as having utf-8 */
 	encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
 
+	if (object_database_contaminated && !has_sha1_file_proper(tree))
+		return error(_("cannot create a commit with external tree %s"),
+			     sha1_to_hex(tree));
+
 	strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */
 	strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree));
 
@@ -1355,6 +1359,11 @@ int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
 		struct commit_list *next = parents->next;
 		struct commit *parent = parents->item;
 
+		if (object_database_contaminated &&
+		    !has_sha1_file_proper(parent->object.sha1))
+			return error(_("cannot create a commit with external commit %s"),
+				     sha1_to_hex(parent->object.sha1));
+
 		strbuf_addf(&buffer, "parent %s\n",
 			    sha1_to_hex(parent->object.sha1));
 		free(parents);
diff --git a/sha1_file.c b/sha1_file.c
index 53f93ab..b8f2afe 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2935,6 +2935,13 @@ int has_sha1_file(const unsigned char *sha1)
 	return has_sha1_file_extended(sha1, odb_default);
 }
 
+int has_sha1_file_proper(const unsigned char *sha1)
+{
+	if (find_cached_object(sha1, ODB_CACHED))
+		return 1;
+	return has_sha1_file_extended(sha1, ODB_LOCAL | ODB_ALT);
+}
+
 static void check_tree(const void *buf, size_t size)
 {
 	struct tree_desc desc;
-- 
1.8.2.83.gc99314b