]> git.proxmox.com Git - libgit2.git/commitdiff
commit: allow retrieving an arbitrary header field
authorCarlos Martín Nieto <cmn@dwim.me>
Mon, 22 Jun 2015 13:32:29 +0000 (15:32 +0200)
committerCarlos Martín Nieto <cmn@dwim.me>
Mon, 22 Jun 2015 13:56:31 +0000 (15:56 +0200)
This allows the user to look up fields which we don't parse in libgit2,
and allows them to access gpgsig or mergetag fields if they wish to
check the signature.

CHANGELOG.md
include/git2/commit.h
src/commit.c
tests/commit/parse.c

index a8e3e18ac072b4f970f27a0e9d8bed837b756160..eb7ae842b6248c74d17aed93d78141bde49798f1 100644 (file)
@@ -140,6 +140,9 @@ support for HTTPS connections insead of OpenSSL.
 * `git_filter_list_contains` will indicate whether a particular
   filter will be run in the given filter list.
 
+* `git_commit_header_field()` has been added, which allows retrieving
+  the contents of an arbitrary header field.
+
 ### API removals
 
 * `git_remote_save()` and `git_remote_clear_refspecs()` have been
index fb53a701bbf6045242548c52e64a2f27e15c4f33..04711c1fa5ef928dec772f6d1c7b949c46ffcba6 100644 (file)
@@ -239,6 +239,17 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
        const git_commit *commit,
        unsigned int n);
 
+/**
+ * Get an arbitrary header field
+ *
+ * @param out the buffer to fill
+ * @param commit the commit to look in
+ * @param field the header field to return
+ * @return 0 on succeess, GIT_ENOTFOUND if the field does not exist,
+ * or an error code
+ */
+GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit, const char *field);
+
 /**
  * Create new commit in the repository from a list of `git_object` pointers
  *
index ce13bdb851ecbb25088d3950b99b15d7a517c4ba..616f947dbb20ac4b65ce9fe2a5c3ebdcce8b94cf 100644 (file)
@@ -518,3 +518,58 @@ int git_commit_nth_gen_ancestor(
        *ancestor = parent;
        return 0;
 }
+
+int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field)
+{
+       const char *buf = commit->raw_header;
+       const char *h, *eol;
+
+       git_buf_sanitize(out);
+       while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
+               h++;
+               if (git__prefixcmp(h, field)) {
+                       buf = h;
+                       continue;
+               }
+
+               h += strlen(field);
+               eol = strchr(h, '\n');
+               if (h[0] != ' ') {
+                       buf = h;
+                       continue;
+               }
+               if (!eol)
+                       goto malformed;
+
+               h++; /* skip the SP */
+
+               git_buf_put(out, h, eol - h);
+               if (git_buf_oom(out))
+                       goto oom;
+
+               /* If the next line starts with SP, it's multi-line, we must continue */
+               while (eol[1] == ' ') {
+                       git_buf_putc(out, '\n');
+                       h = eol + 2;
+                       eol = strchr(h, '\n');
+                       if (!eol)
+                               goto malformed;
+
+                       git_buf_put(out, h, eol - h);
+               }
+
+               if (git_buf_oom(out))
+                       goto oom;
+
+               return 0;
+       }
+
+       return GIT_ENOTFOUND;
+
+malformed:
+       giterr_set(GITERR_OBJECT, "malformed header");
+       return -1;
+oom:
+       giterr_set_oom();
+       return -1;
+}
index fa079f47099eb582bc4f4a97d09708d14069c98d..388da078a79583af4a299de7b91a945fda06ca8c 100644 (file)
@@ -418,3 +418,41 @@ committer Vicent Marti <tanoku@gmail.com> 1273848544 +0200\n\
        cl_assert_equal_s(raw_message, git_commit_message_raw(commit));
        git_commit__free(commit);
 }
+
+void test_commit_parse__arbitrary_field(void)
+{
+       git_commit *commit;
+       git_buf buf = GIT_BUF_INIT;
+       const char *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-----";
+
+       cl_git_pass(parse_commit(&commit, passing_commit_cases[4]));
+
+       cl_git_pass(git_commit_header_field(&buf, commit, "parent"));
+       cl_assert_equal_s("34734e478d6cf50c27c9d69026d93974d052c454", buf.ptr);
+       git_buf_clear(&buf);
+
+       cl_git_pass(git_commit_header_field(&buf, commit, "gpgsig"));
+       cl_assert_equal_s(gpgsig, buf.ptr);
+
+       cl_git_fail_with(GIT_ENOTFOUND, git_commit_header_field(&buf, commit, "awesomeness"));
+       cl_git_fail_with(GIT_ENOTFOUND, git_commit_header_field(&buf, commit, "par"));
+
+       git_buf_free(&buf);
+       git_commit__free(commit);
+}