-
-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Respect existing trailers (including co-author lines) when backporting #46
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -293,14 +293,48 @@ def get_exit_message(self, branch): | |
""" | ||
|
||
def get_updated_commit_message(self, cherry_pick_branch): | ||
""" | ||
Get updated commit message for the cherry-picked commit. | ||
""" | ||
# Get the original commit message and prefix it with the branch name | ||
# if that's enabled. | ||
commit_prefix = "" | ||
if self.prefix_commit: | ||
commit_prefix = f"[{get_base_branch(cherry_pick_branch)}] " | ||
return f"""{commit_prefix}{self.get_commit_message(self.commit_sha1)} | ||
(cherry picked from commit {self.commit_sha1}) | ||
updated_commit_message = f"{commit_prefix}{self.get_commit_message(self.commit_sha1)}" | ||
|
||
# Add '(cherry picked from commit ...)' to the message | ||
# and add new Co-authored-by trailer if necessary. | ||
cherry_pick_information = f"(cherry picked from commit {self.commit_sha1})\n:" | ||
# Here, we're inserting new Co-authored-by trailer and we *somewhat* | ||
# abuse interpret-trailers by also adding cherry_pick_information which | ||
# is not an actual trailer. | ||
# `--where start` makes it so we insert new trailers *before* the existing | ||
# trailers so cherry-pick information gets added before any of the trailers | ||
# which prevents us from breaking the trailers. | ||
cmd = [ | ||
"git", | ||
"interpret-trailers", | ||
"--where", | ||
"start", | ||
"--trailer", | ||
f"Co-authored-by: {get_author_info_from_short_sha(self.commit_sha1)}", | ||
"--trailer", | ||
cherry_pick_information, | ||
] | ||
output = subprocess.check_output(cmd, input=updated_commit_message.encode()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (One of the comments from my previous review got lost.) It would be helpful to add a docstring and a couple more comments to this function to explain what it does, since it's not immediately obvious.
I also wonder if there's a more straightforward way to do achieve this. f"""{commit_prefix}{original_commit_message}
(cherry picked from commit {self.commit_sha1})
{metadata}""" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Welp, some value sure was lost by me not adding more comments in there in the first place... I added some now to explain the way this is supposed to work.
I can look into an alternative way of doing this. The important things are:
One of the problems is that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If we can isolate all the trailers (and
Recently I was looking into manually adding co-authors, and apparently you had to leave two empty lines between the message and the trailers, so an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
cherry-picker is Python 3.7+ so this could just rely on the insertion order of dictionaries, possibly with the help of
The problem with this is that we would need to write a proper detection of trailers or we risk the trailers no longer being trailers. A single split is not enough as we plan on adding a trailer and that means we need to make sure that we add a trailer with other trailers. For example, if this were the original commit message:
Then we can't just simply add it to the last part:
On the other hand, we also have to keep all trailers together so if this were the original commit message:
Then this would not be acceptable:
For reference, here's the logic that git uses: https://github.com/git/git/blob/afa70145a25e81faa685dc0b465e52b45d2444bd/trailer.c#L818-L915
Based on these two:
I think this falls into same category as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Given this:
$ cat msg.txt | git interpret-trailers --only-trailers
Co-authored-by: Co-Author Name <[email protected]>
Co-authored-by: Author Name <[email protected]> You could do something like this: >>> # get these from self.get_commit_message(self.commit_sha1).splitlines()
>>> with open('msg.txt') as f:
... lines = [line.strip() for line in f] # remove trailing whitespace/newlines
...
>>> # get these from `git interpret-trailers --only-trailers`
>>> trailers = ['Co-authored-by: Co-Author Name <[email protected]>',
... 'Co-authored-by: Author Name <[email protected]>']
>>> # remove trailers from the full message
>>> for trailer in trailers:
... lines.remove(trailer)
...
>>> msg = '\n'.join(lines).strip() # this is the msg without trailers
>>> trailers.append('Co-authored-by: Another Author')
>>> metadata = '\n'.join(trailers) # these are the updated trailers
>>> print(f"""[3.10] {msg}
... (cherry-picked from somewhere)
...
... {metadata}""") # this is the final message
[3.10] gh-12345: fix some broken stuff
Some stuff was broken and now
it's fixed.
(cherry-picked from somewhere)
Co-authored-by: Co-Author Name <[email protected]>
Co-authored-by: Author Name <[email protected]>
Co-authored-by: Another Author That is, if you take the full commit and remove the trailer lines you obtained with |
||
# Replace the right most-occurence of the "cherry picked from commit" string. | ||
# | ||
# This needs to be done because `git interpret-trailers` required us to add `:` | ||
# to `cherry_pick_information` when we don't actually want it. | ||
before, after = output.strip().decode().rsplit(f"\n{cherry_pick_information}", 1) | ||
if not before.endswith("\n"): | ||
# ensure that we still have a newline between cherry pick information | ||
# and commit headline | ||
cherry_pick_information = f"\n{cherry_pick_information}" | ||
updated_commit_message = cherry_pick_information[:-1].join((before, after)) | ||
|
||
|
||
Co-authored-by: {get_author_info_from_short_sha(self.commit_sha1)}""" | ||
return updated_commit_message | ||
|
||
def amend_commit_message(self, cherry_pick_branch): | ||
""" prefix the commit message with (X.Y) """ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -468,6 +468,96 @@ def test_normalize_short_commit_message(): | |
) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"commit_message,expected_commit_message", | ||
( | ||
# ensure existing co-author is retained | ||
( | ||
"""Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
Co-authored-by: PR Co-Author <[email protected]>""", | ||
"""[3.6] Fix broken `Show Source` links on documentation pages (GH-3113) | ||
(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69) | ||
|
||
Co-authored-by: PR Author <[email protected]> | ||
Co-authored-by: PR Co-Author <[email protected]>""", | ||
), | ||
# ensure co-author trailer is not duplicated | ||
( | ||
"""Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
Co-authored-by: PR Author <[email protected]>""", | ||
"""[3.6] Fix broken `Show Source` links on documentation pages (GH-3113) | ||
(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69) | ||
|
||
Co-authored-by: PR Author <[email protected]>""", | ||
), | ||
# ensure message is formatted properly when original commit is short | ||
( | ||
"Fix broken `Show Source` links on documentation pages (GH-3113)", | ||
"""[3.6] Fix broken `Show Source` links on documentation pages (GH-3113) | ||
(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69) | ||
|
||
Co-authored-by: PR Author <[email protected]>""", | ||
), | ||
# ensure message is formatted properly when original commit is long | ||
( | ||
"""Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
The `Show Source` was broken because of a change made in sphinx 1.5.1 | ||
In Sphinx 1.4.9, the sourcename was "index.txt". | ||
In Sphinx 1.5.1+, it is now "index.rst.txt".""", | ||
"""[3.6] Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
The `Show Source` was broken because of a change made in sphinx 1.5.1 | ||
In Sphinx 1.4.9, the sourcename was "index.txt". | ||
In Sphinx 1.5.1+, it is now "index.rst.txt". | ||
(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69) | ||
|
||
Co-authored-by: PR Author <[email protected]>""", | ||
), | ||
# ensure message is formatted properly when original commit is long | ||
# and it has a co-author | ||
( | ||
"""Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
The `Show Source` was broken because of a change made in sphinx 1.5.1 | ||
In Sphinx 1.4.9, the sourcename was "index.txt". | ||
In Sphinx 1.5.1+, it is now "index.rst.txt". | ||
|
||
Co-authored-by: PR Co-Author <[email protected]>""", | ||
"""[3.6] Fix broken `Show Source` links on documentation pages (GH-3113) | ||
|
||
The `Show Source` was broken because of a change made in sphinx 1.5.1 | ||
In Sphinx 1.4.9, the sourcename was "index.txt". | ||
In Sphinx 1.5.1+, it is now "index.rst.txt". | ||
(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69) | ||
|
||
Co-authored-by: PR Author <[email protected]> | ||
Co-authored-by: PR Co-Author <[email protected]>""", | ||
), | ||
), | ||
) | ||
def test_get_updated_commit_message_with_trailers(commit_message, expected_commit_message): | ||
cherry_pick_branch = "backport-22a594a-3.6" | ||
commit = "b9ff498793611d1c6a9b99df464812931a1e2d69" | ||
|
||
with mock.patch("cherry_picker.cherry_picker.validate_sha", return_value=True): | ||
cherry_picker = CherryPicker("origin", commit, []) | ||
|
||
with mock.patch( | ||
"cherry_picker.cherry_picker.validate_sha", return_value=True | ||
), mock.patch.object( | ||
cherry_picker, "get_commit_message", return_value=commit_message | ||
), mock.patch( | ||
"cherry_picker.cherry_picker.get_author_info_from_short_sha", | ||
return_value="PR Author <[email protected]>", | ||
): | ||
updated_commit_message = cherry_picker.get_updated_commit_message(cherry_pick_branch) | ||
|
||
assert updated_commit_message == expected_commit_message | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"input_path", ("/some/path/without/revision", "HEAD:some/non-existent/path") | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of a tangent, but maybe we should make it a trailer?
Cherry-Picked-From: {self.commit_sha1}
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message
cherry picked from commit ...
is the default message generated bygit
when we usegit cherry-pick -X
. So I think it should be kept that way.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or this can perhaps be addressed in a separate PR :)