sequencer: add newline before adding footers
When encountering a commit message that does not end in a newline,
sequencer does not complete the line before determining if a blank line
should be added.  This causes the "(cherry picked..." and sign-off lines
to sometimes appear on the same line as the last line of the commit
message.
This behavior was introduced by commit 967dfd4 ("sequencer: use
trailer's trailer layout", 2016-11-29). However, a revert of that commit
would not resolve this issue completely: prior to that commit, a
conforming footer was deemed to be non-conforming by
has_conforming_footer() if there was no terminating newline, resulting
in both conforming and non-conforming footers being treated the same
when they should not be.
Resolve this issue, both for conforming and non-conforming footers, and
in both do_pick_commit() and append_signoff(), by always adding a
newline to the commit message if it does not end in one before checking
the footer for conformity.
Reported-by: Brian Norris <computersforpeace@gmail.com>
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
This commit is contained in:
		 Jonathan Tan
					Jonathan Tan
				
			
				
					committed by
					
						 Junio C Hamano
						Junio C Hamano
					
				
			
			
				
	
			
			
			 Junio C Hamano
						Junio C Hamano
					
				
			
						parent
						
							967dfd4d56
						
					
				
				
					commit
					44dc738a39
				
			
							
								
								
									
										11
									
								
								sequencer.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								sequencer.c
									
									
									
									
									
								
							| @ -698,6 +698,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit, | ||||
| 			strbuf_addstr(&msgbuf, skip_blank_lines(p + 2)); | ||||
|  | ||||
| 		if (opts->record_origin) { | ||||
| 			strbuf_complete_line(&msgbuf); | ||||
| 			if (!has_conforming_footer(&msgbuf, NULL, 0)) | ||||
| 				strbuf_addch(&msgbuf, '\n'); | ||||
| 			strbuf_addstr(&msgbuf, cherry_picked_prefix); | ||||
| @ -1362,6 +1363,9 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag) | ||||
| 				getenv("GIT_COMMITTER_EMAIL"))); | ||||
| 	strbuf_addch(&sob, '\n'); | ||||
|  | ||||
| 	if (!ignore_footer) | ||||
| 		strbuf_complete_line(msgbuf); | ||||
|  | ||||
| 	/* | ||||
| 	 * If the whole message buffer is equal to the sob, pretend that we | ||||
| 	 * found a conforming footer with a matching sob | ||||
| @ -1382,13 +1386,6 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag) | ||||
| 			 * the title and body to be filled in by the user. | ||||
| 			 */ | ||||
| 			append_newlines = "\n\n"; | ||||
| 		} else if (msgbuf->buf[len - 1] != '\n') { | ||||
| 			/* | ||||
| 			 * Incomplete line.  Complete the line and add a | ||||
| 			 * blank one so that there is an empty line between | ||||
| 			 * the message body and the sob. | ||||
| 			 */ | ||||
| 			append_newlines = "\n\n"; | ||||
| 		} else if (len == 1) { | ||||
| 			/* | ||||
| 			 * Buffer contains a single newline.  Add another | ||||
|  | ||||
| @ -208,6 +208,50 @@ test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists fo | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'cherry-pick -x handles commits with no NL at end of message' ' | ||||
| 	pristine_detach initial && | ||||
| 	printf "title\n\nSigned-off-by: A <a@example.com>" >msg && | ||||
| 	sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) && | ||||
| 	git cherry-pick -x $sha1 && | ||||
| 	git log -1 --pretty=format:%B >actual && | ||||
|  | ||||
| 	printf "\n(cherry picked from commit %s)\n" $sha1 >>msg && | ||||
| 	test_cmp msg actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'cherry-pick -x handles commits with no footer and no NL at end of message' ' | ||||
| 	pristine_detach initial && | ||||
| 	printf "title\n\nnot a footer" >msg && | ||||
| 	sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) && | ||||
| 	git cherry-pick -x $sha1 && | ||||
| 	git log -1 --pretty=format:%B >actual && | ||||
|  | ||||
| 	printf "\n\n(cherry picked from commit %s)\n" $sha1 >>msg && | ||||
| 	test_cmp msg actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'cherry-pick -s handles commits with no NL at end of message' ' | ||||
| 	pristine_detach initial && | ||||
| 	printf "title\n\nSigned-off-by: A <a@example.com>" >msg && | ||||
| 	sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) && | ||||
| 	git cherry-pick -s $sha1 && | ||||
| 	git log -1 --pretty=format:%B >actual && | ||||
|  | ||||
| 	printf "\nSigned-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n" >>msg && | ||||
| 	test_cmp msg actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'cherry-pick -s handles commits with no footer and no NL at end of message' ' | ||||
| 	pristine_detach initial && | ||||
| 	printf "title\n\nnot a footer" >msg && | ||||
| 	sha1=$(git commit-tree -p initial mesg-with-footer^{tree} <msg) && | ||||
| 	git cherry-pick -s $sha1 && | ||||
| 	git log -1 --pretty=format:%B >actual && | ||||
|  | ||||
| 	printf "\n\nSigned-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n" >>msg && | ||||
| 	test_cmp msg actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'cherry-pick -x treats "(cherry picked from..." line as part of footer' ' | ||||
| 	pristine_detach initial && | ||||
| 	sha1=$(git rev-parse mesg-with-cherry-footer^0) && | ||||
|  | ||||
		Reference in New Issue
	
	Block a user