Commit 6bb9fea13ee2da6475ac799acd5f8296bc1a8537

Erik van Zijst 2012-11-02T10:28:17

tags: Fixed the tag parser to correctly treat the message field as optional. This fix makes libgit2 capable of parsing annotated tag objects that lack the optional message/description field. Previously, libgit2 treated this field as mandatory and raised a tag_error on such tags. However, the message field is optional. An example of such a tag is refs/tags/v2.6.16.31-rc1 in Linux: $ git cat-file tag refs/tags/v2.6.16.31-rc1 object afaa018cefb6af63befef1df7d8febaae904434f type commit tag v2.6.16.31-rc1 tagger Adrian Bunk <bunk@stusta.de> 1162716505 +0100 $

diff --git a/src/tag.c b/src/tag.c
index 56f84a8..4c3d811 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -139,16 +139,19 @@ int git_tag__parse_buffer(git_tag *tag, const char *buffer, size_t length)
 			return -1;
 	}
 
-	if( *buffer != '\n' )
-		return tag_error("No new line before message");
+	tag->message = NULL;
+	if (buffer < buffer_end) {
+		if( *buffer != '\n' )
+			return tag_error("No new line before message");
 
-	text_len = buffer_end - ++buffer;
+		text_len = buffer_end - ++buffer;
 
-	tag->message = git__malloc(text_len + 1);
-	GITERR_CHECK_ALLOC(tag->message);
+		tag->message = git__malloc(text_len + 1);
+		GITERR_CHECK_ALLOC(tag->message);
 
-	memcpy(tag->message, buffer, text_len);
-	tag->message[text_len] = '\0';
+		memcpy(tag->message, buffer, text_len);
+		tag->message[text_len] = '\0';
+	}
 
 	return 0;
 }
diff --git a/tests-clar/object/tag/read.c b/tests-clar/object/tag/read.c
index 4dd5cc2..62dd4ca 100644
--- a/tests-clar/object/tag/read.c
+++ b/tests-clar/object/tag/read.c
@@ -7,6 +7,8 @@ static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980";
 static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
 static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755";
 static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d";
+static const char *short_tag_id = "5da7760512a953e3c7c4e47e4392c7a4338fb729";
+static const char *short_tagged_commit = "4a5ed60bafcf4638b7c8356bd4ce1916bfede93c";
 
 static git_repository *g_repo;
 
@@ -83,3 +85,34 @@ void test_object_tag_read__parse_without_tagger(void)
    git_commit_free(commit);
    git_repository_free(bad_tag_repo);
 }
+
+void test_object_tag_read__parse_without_message(void)
+{
+   // read and parse a tag without a message field
+   git_repository *short_tag_repo;
+   git_tag *short_tag;
+   git_commit *commit;
+   git_oid id, id_commit;
+
+   // TODO: This is a little messy
+   cl_git_pass(git_repository_open(&short_tag_repo, cl_fixture("short_tag.git")));
+
+   git_oid_fromstr(&id, short_tag_id);
+   git_oid_fromstr(&id_commit, short_tagged_commit);
+
+   cl_git_pass(git_tag_lookup(&short_tag, short_tag_repo, &id));
+   cl_assert(short_tag != NULL);
+
+   cl_assert_equal_s(git_tag_name(short_tag), "no_description");
+   cl_assert(git_oid_cmp(&id, git_tag_id(short_tag)) == 0);
+   cl_assert(short_tag->message == NULL);
+
+   cl_git_pass(git_tag_target((git_object **)&commit, short_tag));
+   cl_assert(commit != NULL);
+
+   cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
+
+   git_tag_free(short_tag);
+   git_commit_free(commit);
+   git_repository_free(short_tag_repo);
+}
diff --git a/tests-clar/resources/short_tag.git/HEAD b/tests-clar/resources/short_tag.git/HEAD
new file mode 100644
index 0000000..cb089cd
--- /dev/null
+++ b/tests-clar/resources/short_tag.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests-clar/resources/short_tag.git/config b/tests-clar/resources/short_tag.git/config
new file mode 100644
index 0000000..a4ef456
--- /dev/null
+++ b/tests-clar/resources/short_tag.git/config
@@ -0,0 +1,5 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = true
+	logallrefupdates = true
diff --git a/tests-clar/resources/short_tag.git/index b/tests-clar/resources/short_tag.git/index
new file mode 100644
index 0000000..87fef78
Binary files /dev/null and b/tests-clar/resources/short_tag.git/index differ
diff --git a/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c b/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c
new file mode 100644
index 0000000..aeb4e4b
Binary files /dev/null and b/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c differ
diff --git a/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c b/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c
new file mode 100644
index 0000000..806ce71
Binary files /dev/null and b/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c differ
diff --git a/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 b/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729
new file mode 100644
index 0000000..1192707
--- /dev/null
+++ b/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729
@@ -0,0 +1 @@
+xM0@aלb. i%1ƍpc@--6&B
E+pVСSƆd/m(RJ%
R^vʩ,Giǖ<Ӵ3\ncinRSg	u1
\ No newline at end of file
diff --git a/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
new file mode 100644
index 0000000..7112238
Binary files /dev/null and b/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ
diff --git a/tests-clar/resources/short_tag.git/packed-refs b/tests-clar/resources/short_tag.git/packed-refs
new file mode 100644
index 0000000..ca5197e
--- /dev/null
+++ b/tests-clar/resources/short_tag.git/packed-refs
@@ -0,0 +1 @@
+5da7760512a953e3c7c4e47e4392c7a4338fb729 refs/tags/no_description
diff --git a/tests-clar/resources/short_tag.git/refs/heads/master b/tests-clar/resources/short_tag.git/refs/heads/master
new file mode 100644
index 0000000..fcefd1e
--- /dev/null
+++ b/tests-clar/resources/short_tag.git/refs/heads/master
@@ -0,0 +1 @@
+4a5ed60bafcf4638b7c8356bd4ce1916bfede93c