From 6bb9fea13ee2da6475ac799acd5f8296bc1a8537 Mon Sep 17 00:00:00 2001 From: Erik van Zijst Date: Fri, 2 Nov 2012 10:28:17 -0700 Subject: [PATCH] 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 1162716505 +0100 $ --- src/tag.c | 17 +++++---- tests-clar/object/tag/read.c | 33 ++++++++++++++++++ tests-clar/resources/short_tag.git/HEAD | 1 + tests-clar/resources/short_tag.git/config | 5 +++ tests-clar/resources/short_tag.git/index | Bin 0 -> 104 bytes .../4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c | Bin 0 -> 169 bytes .../4d/5fcadc293a348e88f777dc0920f11e7d71441c | Bin 0 -> 48 bytes .../5d/a7760512a953e3c7c4e47e4392c7a4338fb729 | 1 + .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../resources/short_tag.git/packed-refs | 1 + .../resources/short_tag.git/refs/heads/master | 1 + 11 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 tests-clar/resources/short_tag.git/HEAD create mode 100644 tests-clar/resources/short_tag.git/config create mode 100644 tests-clar/resources/short_tag.git/index create mode 100644 tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c create mode 100644 tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c create mode 100644 tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 create mode 100644 tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests-clar/resources/short_tag.git/packed-refs create mode 100644 tests-clar/resources/short_tag.git/refs/heads/master diff --git a/src/tag.c b/src/tag.c index 56f84a85f..4c3d811eb 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 4dd5cc253..62dd4ca39 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 000000000..cb089cd89 --- /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 000000000..a4ef456cb --- /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 0000000000000000000000000000000000000000..87fef784703ae391c5d301968bb187364d20ccd0 GIT binary patch literal 104 zcmZ?q402{*U|<4b#(+s*?HL|&CIV?|aj)CE zZ@PHR*}GeFU3t`vLr;2wCo(Xn<>vzp0fAXhtb8A;+I(!OIK;A$z1&=FV+soZLw_OB literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..aeb4e4b0b8c9bf515e183528e050859122bed9d4 GIT binary patch literal 169 zcmV;a09OBa0iBI84#F@DMVWgFUw|rUQzb|Uv2X!KHp_8~p-rmBbl~(9j==W*8~&p_ zO`^~^yVHdkTw!jaea z7tW|7mLiyH%F_vK+u2}3+cmH^-k55$TUYu2hw9362FgiMlB59;6bH~dDvU_avLQpB XRdT`+A{ScZx1bjuV_kg!HtJD