From 7f8fe1d45e086adc9e7f3f0c33b624eeb3774033 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 1 Dec 2015 10:03:56 +0100 Subject: commit: introduce `git_commit_body` It is already possible to get a commit's summary with the `git_commit_summary` function. It is not possible to get the remaining part of the commit message, that is the commit message's body. Fix this by introducing a new function `git_commit_body`. --- include/git2/commit.h | 13 +++++++++++++ src/commit.c | 28 ++++++++++++++++++++++++++++ src/commit.h | 1 + tests/commit/commit.c | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) 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 @@ -127,6 +127,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. * 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/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"); +} -- cgit v1.2.1