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 $
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
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