Commit 291090a0761934fe295d0923ea577f6878460bf3

Russell Belfer 2013-01-17T13:19:09

Add skipping of unknown commit headers This moves the check for the "encoding" header into a loop which is just scanning for non-required headers at the end of a commit header. That loop will skip unrecognized lines (including header continuation lines) until a terminating completely blank line is found, and only then does it move to reading the commit message.

diff --git a/src/commit.c b/src/commit.c
index 79f287e..9449224 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -135,7 +135,6 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
 {
 	const char *buffer = data;
 	const char *buffer_end = (const char *)data + len;
-
 	git_oid parent_id;
 
 	git_vector_init(&commit->parent_ids, 4, NULL);
@@ -148,9 +147,7 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
 	 */
 
 	while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
-		git_oid *new_id;
-
-		new_id = git__malloc(sizeof(git_oid));
+		git_oid *new_id = git__malloc(sizeof(git_oid));
 		GITERR_CHECK_ALLOC(new_id);
 
 		git_oid_cpy(new_id, &parent_id);
@@ -172,24 +169,29 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
 	if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
 		return -1;
 
-	if (git__prefixcmp(buffer, "encoding ") == 0) {
-		const char *encoding_end;
-		buffer += strlen("encoding ");
+	/* Parse add'l header entries until blank line found */
+	while (buffer < buffer_end && *buffer != '\n') {
+		const char *eoln = buffer;
+		while (eoln < buffer_end && *eoln != '\n')
+			++eoln;
+		if (eoln < buffer_end && *eoln == '\n')
+			++eoln;
 
-		encoding_end = buffer;
-		while (encoding_end < buffer_end && *encoding_end != '\n')
-			encoding_end++;
+		if (git__prefixcmp(buffer, "encoding ") == 0) {
+			buffer += strlen("encoding ");
 
-		commit->message_encoding = git__strndup(buffer, encoding_end - buffer);
-		GITERR_CHECK_ALLOC(commit->message_encoding);
+			commit->message_encoding = git__strndup(buffer, eoln - buffer);
+			GITERR_CHECK_ALLOC(commit->message_encoding);
+		}
 
-		buffer = encoding_end;
+		buffer = eoln;
 	}
 
-	/* parse commit message */
+	/* skip blank lines */
 	while (buffer < buffer_end - 1 && *buffer == '\n')
 		buffer++;
 
+	/* parse commit message */
 	if (buffer <= buffer_end) {
 		commit->message = git__strndup(buffer, buffer_end - buffer);
 		GITERR_CHECK_ALLOC(commit->message);
diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c
index 8075f26..908d9fb 100644
--- a/tests-clar/commit/parse.c
+++ b/tests-clar/commit/parse.c
@@ -236,6 +236,30 @@ author Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
 committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
 \n\
 a simple commit which works\n",
+/* simple commit with GPG signature */
+"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
+parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
+author Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
+committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
+gpgsig -----BEGIN PGP SIGNATURE-----\n\
+ Version: GnuPG v1.4.12 (Darwin)\n\
+ \n\
+ iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
+ o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
+ JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
+ AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
+ SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
+ who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
+ 6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
+ cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
+ c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
+ ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
+ 7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
+ cpxtDQQMGYFpXK/71stq\n\
+ =ozeK\n\
+ -----END PGP SIGNATURE-----\n\
+\n\
+a simple commit which works\n",
 };
 
 void test_commit_parse__entire_commit(void)
@@ -251,10 +275,8 @@ void test_commit_parse__entire_commit(void)
 		commit->object.repo = g_repo;
 
 		cl_git_fail(git_commit__parse_buffer(
-                     commit,
-                     failing_commit_cases[i],
-                     strlen(failing_commit_cases[i]))
-         );
+			commit, failing_commit_cases[i], strlen(failing_commit_cases[i]))
+		);
 
 		git_commit__free(commit);
 	}
@@ -272,17 +294,11 @@ void test_commit_parse__entire_commit(void)
                      strlen(passing_commit_cases[i]))
          );
 
-		git_commit__free(commit);
-
-		commit = (git_commit*)git__malloc(sizeof(git_commit));
-		memset(commit, 0x0, sizeof(git_commit));
-		commit->object.repo = g_repo;
-
-		cl_git_pass(git_commit__parse_buffer(
-                     commit,
-                     passing_commit_cases[i],
-                     strlen(passing_commit_cases[i]))
-         );
+		if (!i)
+			cl_assert_equal_s("\n", git_commit_message(commit));
+		else
+			cl_assert(git__prefixcmp(
+				git_commit_message(commit), "a simple commit which works") == 0);
 
 		git_commit__free(commit);
 	}