Repository: libgit2/libgit2 (C)

Issue:
`git_commit_summary` creates too long output for some commits
### Description
`git_commit_summary` produces too long paragraphs for some commits, like for this one in the Linux repository - https://github.com/torvalds/linux/commit/3218357c94af92478ef39163163a81e654385320. It creates 925 characters long text (almost the whole commit message) instead of 46 characters long (just the first line).

### Reproduction steps
Create a project with following files:

main.cpp:
```c++
#include "deps/libgit2/include/git2.h"
#include <iostream>

int main()
{
    git_libgit2_init();
    const std::string repoPath = "path_to_linux_repository";  // INSERT YOUR OWN

    git_repository* repo = nullptr;
    if (const auto status = git_repository_open(&repo, repoPath.c_str()); status != 0)
    {
        throw std::runtime_error("Failed to open repository at " + repoPath + ", status: " + std::to_string(status));
    }

    git_oid id{};
    if (const auto status = git_oid_fromstr(&id, "3218357c94af92478ef39163163a81e654385320"); status != 0)
    {
        throw std::runtime_error("Failed to create OID, status: " + std::to_string(status));
    }
    git_commit* commit = nullptr;
    if (const auto status = git_commit_lookup(&commit, repo, &id); status != 0)
    {
        throw std::runtime_error("Failed to lookup commit, status: " + std::to_string(status));
    }
    const std::string summary = git_commit_summary(commit);
    std::cout << "git_commit_summary returned (size: " + std::to_string(summary.size()) + "): " << summary << "\n";
    return 0;
}
```
CMakeLists.txt:
```cmake
project(libgit2-commit-summary-test)
cmake_minimum_required(VERSION 3.0)

add_subdirectory(deps/libgit2)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} git2)
```
Also download libgit2 as the dependency:
```
mkdir deps && cd deps
git clone https://github.com/libgit2/libgit2.git
cd ..
```
Build and run the project:
```
mkdir build && cd build
cmake ..
cmake --build .
./libgit2-commit-summary-test
```

### Expected behavior
The summary should be: `[MIPS] More uaccess.h fixes with gcc >= 4.0.1.`

### Actual behavior
The summary is:
`[MIPS] More uaccess.h fixes with gcc >= 4.0.1. From Richard Sandiford <richard@codesourcery.com>: This patch caused a miscompilation of the restore_gp_regs() block in restore_sigcontext().  This was in a 32-bit kernel compiled with GCC CVS head. restore_gp_regs() copies 64-bit user fields into 32-bit variables, and in this combination, the new __get_user_asm_ll32() clobbers too many registers.  It says: /* * Get a long long 64 using 32 bit registers. */ {                                                                    \ __asm__ __volatile__(                                         \ "1:   lw      %1, (%3)                                \n"     \ "2:   lw      %D1, 4(%3)                              \n"     \ "     move    %0, $0                                  \n"     \ "3:   .section        .fixup,\"ax\"  \n"      \ "4:   li      %0, %4                                  \n"     \ "     move    %1, $0                                  \n"     \ "    move     %D1, $0                                 \n"     \ "     j       3b                                      \n"     \ "     .previous      \n"      \ "     .section        __ex_table,\"a\"                \n"     \ "     " __UA_ADDR "   1b, 4b                          \n"     \ "    " __UA_ADDR "    2b, 4b                          \n"     \ "     .previous                                       \n"     \ : "=r" (__gu_err), "=&r" (val)                                        \ : "0" (0), "r" (addr), "i" (-EFAULT));                                \ }`


### Version of libgit2 (release number or SHA1)
0a8728622ecf77ce4185139761b31f0c6f77f04e

### Operating system(s) tested
Manjaro


Discussion:
Indeed.  The commit message in https://github.com/torvalds/linux/commit/3218357c94af92478ef39163163a81e654385320 is `message<nl><sp><sp><sp><sp><nl>...`  We should treat two newlines as a paragraph separator even when those two newlines have whitespace in between.
The documentation of [git_commit_summary](https://libgit2.org/libgit2/#v0.24.0/group/commit/git_commit_summary) says:
> The returned message is the summary of the commit, comprising the first paragraph of the message with whitespace trimmed and squashed.

So I believe the whitespace at the end should be removed.

Edit: This comment was an answer to another comment, which is no longer visible here (removed?).
Yeah sorry, I posted the question bu re-read the code itself and saw the the behaviour of squashing whitespace at the end was already implemented, so I removed my comment.



Patch:
diff --git a/src/commit.c b/src/commit.c
index 752d98b022f..81e5b02d352 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -546,7 +546,7 @@ const char *git_commit_message(const git_commit *commit)
 const char *git_commit_summary(git_commit *commit)
 {
 	git_str summary = GIT_STR_INIT;
-	const char *msg, *space;
+	const char *msg, *space, *next;
 	bool space_contains_newline = false;
 
 	GIT_ASSERT_ARG_WITH_RETVAL(commit, NULL);
@@ -555,10 +555,21 @@ const char *git_commit_summary(git_commit *commit)
 		for (msg = git_commit_message(commit), space = NULL; *msg; ++msg) {
 			char next_character = msg[0];
 			/* stop processing at the end of the first paragraph */
-			if (next_character == '\n' && (!msg[1] || msg[1] == '\n'))
-				break;
+			if (next_character == '\n') {
+				if (!msg[1])
+					break;
+				if (msg[1] == '\n')
+					break;
+				/* stop processing if next line contains only whitespace */
+				next = msg + 1;
+				while (*next && git__isspace_nonlf(*next)) {
+					++next;
+				}
+				if (!*next || *next == '\n') 
+					break;
+			}
 			/* record the beginning of contiguous whitespace runs */
-			else if (git__isspace(next_character)) {
+			if (git__isspace(next_character)) {
 				if(space == NULL) {
 					space = msg;
 					space_contains_newline = false;


Test patch:
diff --git a/tests/commit/commit.c b/tests/commit/commit.c
index d4e333b6ad8..fd574f7f254 100644
--- a/tests/commit/commit.c
+++ b/tests/commit/commit.c
@@ -139,8 +139,11 @@ void test_commit_commit__summary(void)
 {
 	assert_commit_summary("One-liner with no trailing newline", "One-liner with no trailing newline");
 	assert_commit_summary("One-liner with trailing newline", "One-liner with trailing newline\n");
+	assert_commit_summary("One-liner with trailing newline and space", "One-liner with trailing newline and space\n ");
 	assert_commit_summary("Trimmed leading&trailing newlines", "\n\nTrimmed leading&trailing newlines\n\n");
 	assert_commit_summary("First paragraph only", "\nFirst paragraph only\n\n(There are more!)");
+	assert_commit_summary("First paragraph only with space in the next line", "\nFirst paragraph only with space in the next line\n \n(There are more!)");
+	assert_commit_summary("First paragraph only with spaces in the next line", "\nFirst paragraph only with spaces in the next line\n    \n(There are more!)");
 	assert_commit_summary("First paragraph with  unwrapped trailing\tlines", "\nFirst paragraph\nwith  unwrapped\ntrailing\tlines\n\n(Yes, unwrapped!)");
 	assert_commit_summary("\tLeading tabs", "\tLeading\n\ttabs\n\nare preserved"); /* tabs around newlines are collapsed down to a single space */
 	assert_commit_summary(" Leading Spaces", " Leading\n Spaces\n\nare preserved"); /* spaces around newlines are collapsed down to a single space */