diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2015-12-10 12:14:09 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2015-12-10 12:14:09 +0100 |
commit | 6aa06b65cfcce164d7ad3ef184f40acb68406078 (patch) | |
tree | 3ebbc7f24979c83f34905602627bfee9f4ef5a13 | |
parent | dc49eb585f012ea8df309d90396873f91b2d3ae5 (diff) | |
parent | 254e0a33ee66c65948e15efbe93a810c4077e324 (diff) | |
download | libgit2-6aa06b65cfcce164d7ad3ef184f40acb68406078.tar.gz |
Merge pull request #3522 from pks-t/email-format-commit-message
diff: include commit message when formatting patch
-rw-r--r-- | include/git2/commit.h | 13 | ||||
-rw-r--r-- | include/git2/diff.h | 5 | ||||
-rw-r--r-- | src/commit.c | 28 | ||||
-rw-r--r-- | src/commit.h | 1 | ||||
-rw-r--r-- | src/diff.c | 11 | ||||
-rw-r--r-- | tests/commit/commit.c | 39 | ||||
-rw-r--r-- | tests/diff/format_email.c | 41 | ||||
-rw-r--r-- | tests/resources/diff_format_email/.gitted/index | bin | 256 -> 289 bytes | |||
-rw-r--r-- | tests/resources/diff_format_email/.gitted/objects/62/7e7e12d87e07a83fad5b6bfa25e86ead4a5270 | 1 | ||||
-rw-r--r-- | tests/resources/diff_format_email/.gitted/objects/73/09653445ecf038d3e3dd9ed55edb6cb541a4ba | bin | 0 -> 28 bytes | |||
-rw-r--r-- | tests/resources/diff_format_email/.gitted/objects/d5/ff67764c82f729b13c26a09576570d884d9687 | bin | 0 -> 121 bytes | |||
-rw-r--r-- | tests/resources/diff_format_email/.gitted/refs/heads/master | 2 | ||||
-rw-r--r-- | tests/resources/diff_format_email/file3.txt | 1 |
13 files changed, 139 insertions, 3 deletions
diff --git a/include/git2/commit.h b/include/git2/commit.h index 04711c1fa..34d29ed81 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -128,6 +128,19 @@ GIT_EXTERN(const char *) git_commit_message_raw(const git_commit *commit); GIT_EXTERN(const char *) git_commit_summary(git_commit *commit); /** + * Get the long "body" of the git commit message. + * + * The returned message is the body of the commit, comprising + * everything but the first paragraph of the message. Leading and + * trailing whitespaces are trimmed. + * + * @param commit a previously loaded commit. + * @return the body of a commit or NULL when no the message only + * consists of a summary + */ +GIT_EXTERN(const char *) git_commit_body(git_commit *commit); + +/** * Get the commit time (i.e. committer time) of a commit. * * @param commit a previously loaded commit. diff --git a/include/git2/diff.h b/include/git2/diff.h index cbffdb49a..3eb265652 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -1286,12 +1286,15 @@ typedef struct { /** Summary of the change */ const char *summary; + /** Commit message's body */ + const char *body; + /** Author of the change */ const git_signature *author; } git_diff_format_email_options; #define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1 -#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL} +#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL, NULL} /** * Create an e-mail ready patch from a diff. diff --git a/src/commit.c b/src/commit.c index b42f9de28..81aae489f 100644 --- a/src/commit.c +++ b/src/commit.c @@ -31,6 +31,7 @@ void git_commit__free(void *_commit) git__free(commit->raw_message); git__free(commit->message_encoding); git__free(commit->summary); + git__free(commit->body); git__free(commit); } @@ -472,6 +473,33 @@ const char *git_commit_summary(git_commit *commit) return commit->summary; } +const char *git_commit_body(git_commit *commit) +{ + const char *msg, *end; + + assert(commit); + + if (!commit->body) { + /* search for end of summary */ + for (msg = git_commit_message(commit); *msg; ++msg) + if (msg[0] == '\n' && (!msg[1] || msg[1] == '\n')) + break; + + /* trim leading and trailing whitespace */ + for (; *msg; ++msg) + if (!git__isspace(*msg)) + break; + for (end = msg + strlen(msg) - 1; msg <= end; --end) + if (!git__isspace(*end)) + break; + + if (*msg) + commit->body = git__strndup(msg, end - msg + 1); + } + + return commit->body; +} + int git_commit_tree(git_tree **tree_out, const git_commit *commit) { assert(commit); diff --git a/src/commit.h b/src/commit.h index efb080b50..d01ac2b2f 100644 --- a/src/commit.h +++ b/src/commit.h @@ -28,6 +28,7 @@ struct git_commit { char *raw_header; char *summary; + char *body; }; void git_commit__free(void *commit); diff --git a/src/diff.c b/src/diff.c index 9402b6e61..67fab0763 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1659,6 +1659,7 @@ int git_diff_format_email__append_header_tobuf( const git_oid *id, const git_signature *author, const char *summary, + const char *body, size_t patch_no, size_t total_patches, bool exclude_patchno_marker) @@ -1698,6 +1699,13 @@ int git_diff_format_email__append_header_tobuf( error = git_buf_printf(out, "%s\n\n", summary); + if (body) { + git_buf_puts(out, body); + + if (out->ptr[out->size - 1] != '\n') + git_buf_putc(out, '\n'); + } + return error; } @@ -1775,7 +1783,7 @@ int git_diff_format_email( error = git_diff_format_email__append_header_tobuf(out, opts->id, opts->author, summary == NULL ? opts->summary : summary, - opts->patch_no, opts->total_patches, ignore_marker); + opts->body, opts->patch_no, opts->total_patches, ignore_marker); if (error < 0) goto on_error; @@ -1818,6 +1826,7 @@ int git_diff_commit_as_email( opts.total_patches = total_patches; opts.id = git_commit_id(commit); opts.summary = git_commit_summary(commit); + opts.body = git_commit_body(commit); opts.author = git_commit_author(commit); if ((error = git_diff__commit(&diff, repo, commit, diff_opts)) < 0) diff --git a/tests/commit/commit.c b/tests/commit/commit.c index 81aaf80d3..c82971f4b 100644 --- a/tests/commit/commit.c +++ b/tests/commit/commit.c @@ -63,6 +63,18 @@ void assert_commit_summary(const char *expected, const char *given) git_commit__free(dummy); } +void assert_commit_body(const char *expected, const char *given) +{ + git_commit *dummy; + + cl_assert(dummy = git__calloc(1, sizeof(struct git_commit))); + + dummy->raw_message = git__strdup(given); + cl_assert_equal_s(expected, git_commit_body(dummy)); + + git_commit_free(dummy); +} + void test_commit_commit__summary(void) { assert_commit_summary("One-liner with no trailing newline", "One-liner with no trailing newline"); @@ -80,8 +92,35 @@ void test_commit_commit__summary(void) assert_commit_summary(" Spaces after newlines are collapsed", "\n Spaces after newlines\n are\n collapsed\n "); /* newlines at the very beginning are ignored and not collapsed */ assert_commit_summary(" Spaces before newlines are collapsed", " \nSpaces before newlines \nare \ncollapsed \n"); assert_commit_summary(" Spaces around newlines are collapsed", " \n Spaces around newlines \n are \n collapsed \n "); + assert_commit_summary(" Trailing newlines are" , " \n Trailing newlines \n are \n\n collapsed \n "); + assert_commit_summary(" Trailing spaces are stripped", " \n Trailing spaces \n are stripped \n\n \n \t "); assert_commit_summary("", ""); assert_commit_summary("", " "); assert_commit_summary("", "\n"); assert_commit_summary("", "\n \n"); } + +void test_commit_commit__body(void) +{ + assert_commit_body(NULL, "One-liner with no trailing newline"); + assert_commit_body(NULL, "One-liner with trailing newline\n"); + assert_commit_body(NULL, "\n\nTrimmed leading&trailing newlines\n\n"); + assert_commit_body("(There are more!)", "\nFirst paragraph only\n\n(There are more!)"); + assert_commit_body("(Yes, unwrapped!)", "\nFirst paragraph\nwith unwrapped\ntrailing\tlines\n\n(Yes, unwrapped!)"); + assert_commit_body("are preserved", "\tLeading\n\ttabs\n\nare preserved"); /* tabs around newlines are collapsed down to a single space */ + assert_commit_body("are preserved", " Leading\n Spaces\n\nare preserved"); /* spaces around newlines are collapsed down to a single space */ + assert_commit_body(NULL, "Trailing tabs\tare removed\t\t"); + assert_commit_body(NULL, "Trailing spaces are removed "); + assert_commit_body("are removed", "Trailing tabs\t\n\nare removed"); + assert_commit_body("are removed", "Trailing spaces \n\nare removed"); + assert_commit_body(NULL,"Newlines\nare\nreplaced by spaces\n"); + assert_commit_body(NULL , "\n Spaces after newlines\n are\n collapsed\n "); /* newlines at the very beginning are ignored and not collapsed */ + assert_commit_body(NULL , " \nSpaces before newlines \nare \ncollapsed \n"); + assert_commit_body(NULL , " \n Spaces around newlines \n are \n collapsed \n "); + assert_commit_body("collapsed" , " \n Trailing newlines \n are \n\n collapsed \n "); + assert_commit_body(NULL, " \n Trailing spaces \n are stripped \n\n \n \t "); + assert_commit_body(NULL , ""); + assert_commit_body(NULL , " "); + assert_commit_body(NULL , "\n"); + assert_commit_body(NULL , "\n \n"); +} diff --git a/tests/diff/format_email.c b/tests/diff/format_email.c index 18ad99bd5..8a0128898 100644 --- a/tests/diff/format_email.c +++ b/tests/diff/format_email.c @@ -97,6 +97,47 @@ void test_diff_format_email__simple(void) email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts); } +void test_diff_format_email__with_message(void) +{ + git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; + const char *email = "From 627e7e12d87e07a83fad5b6bfa25e86ead4a5270 Mon Sep 17 00:00:00 2001\n" \ + "From: Patrick Steinhardt <ps@pks.im>\n" \ + "Date: Tue, 24 Nov 2015 13:34:39 +0100\n" \ + "Subject: [PATCH] Modify content with message\n" \ + "\n" \ + "Modify content of file3.txt by appending a new line. Make this\n" \ + "commit message somewhat longer to test behavior with newlines\n" \ + "embedded in the message body.\n" \ + "\n" \ + "Also test if new paragraphs are included correctly.\n" \ + "---\n" \ + " file3.txt | 1 +\n" \ + " 1 file changed, 1 insertion(+), 0 deletions(-)\n" \ + "\n" \ + "diff --git a/file3.txt b/file3.txt\n" \ + "index 9a2d780..7309653 100644\n" \ + "--- a/file3.txt\n" \ + "+++ b/file3.txt\n" \ + "@@ -3,3 +3,4 @@ file3!\n" \ + " file3\n" \ + " file3\n" \ + " file3\n" \ + "+file3\n" \ + "--\n" \ + "libgit2 0.23.0\n" \ + "\n"; + + opts.body = "Modify content of file3.txt by appending a new line. Make this\n" \ + "commit message somewhat longer to test behavior with newlines\n" \ + "embedded in the message body.\n" \ + "\n" \ + "Also test if new paragraphs are included correctly."; + + assert_email_match( + email, "627e7e12d87e07a83fad5b6bfa25e86ead4a5270", &opts); +} + + void test_diff_format_email__multiple(void) { git_oid oid; diff --git a/tests/resources/diff_format_email/.gitted/index b/tests/resources/diff_format_email/.gitted/index Binary files differindex f73027e56..d94f87de8 100644 --- a/tests/resources/diff_format_email/.gitted/index +++ b/tests/resources/diff_format_email/.gitted/index diff --git a/tests/resources/diff_format_email/.gitted/objects/62/7e7e12d87e07a83fad5b6bfa25e86ead4a5270 b/tests/resources/diff_format_email/.gitted/objects/62/7e7e12d87e07a83fad5b6bfa25e86ead4a5270 new file mode 100644 index 000000000..269a5bcf4 --- /dev/null +++ b/tests/resources/diff_format_email/.gitted/objects/62/7e7e12d87e07a83fad5b6bfa25e86ead4a5270 @@ -0,0 +1 @@ +xMN0YGر] !8@%$Nqb5#{Jq+`ޛE!*RR8=5(MT b)⺗AQގE3` W3- cZLO{}O3Bh.Px쇾gޏ$;f\Ntkzc⊼O{|L3Hx5&hN]G5oxYܺRL7SnG15jl~1f.f_*
wt6T;
\ No newline at end of file diff --git a/tests/resources/diff_format_email/.gitted/objects/73/09653445ecf038d3e3dd9ed55edb6cb541a4ba b/tests/resources/diff_format_email/.gitted/objects/73/09653445ecf038d3e3dd9ed55edb6cb541a4ba Binary files differnew file mode 100644 index 000000000..ba9c5fa57 --- /dev/null +++ b/tests/resources/diff_format_email/.gitted/objects/73/09653445ecf038d3e3dd9ed55edb6cb541a4ba diff --git a/tests/resources/diff_format_email/.gitted/objects/d5/ff67764c82f729b13c26a09576570d884d9687 b/tests/resources/diff_format_email/.gitted/objects/d5/ff67764c82f729b13c26a09576570d884d9687 Binary files differnew file mode 100644 index 000000000..e838eeb25 --- /dev/null +++ b/tests/resources/diff_format_email/.gitted/objects/d5/ff67764c82f729b13c26a09576570d884d9687 diff --git a/tests/resources/diff_format_email/.gitted/refs/heads/master b/tests/resources/diff_format_email/.gitted/refs/heads/master index f0f3f932a..3bc734d47 100644 --- a/tests/resources/diff_format_email/.gitted/refs/heads/master +++ b/tests/resources/diff_format_email/.gitted/refs/heads/master @@ -1 +1 @@ -873806f6f27e631eb0b23e4b56bea2bfac14a373 +627e7e12d87e07a83fad5b6bfa25e86ead4a5270 diff --git a/tests/resources/diff_format_email/file3.txt b/tests/resources/diff_format_email/file3.txt index 9a2d780ac..730965344 100644 --- a/tests/resources/diff_format_email/file3.txt +++ b/tests/resources/diff_format_email/file3.txt @@ -3,3 +3,4 @@ file3! file3 file3 file3 +file3 |