Skip to content
54 changes: 50 additions & 4 deletions cherry_picker/cherry_picker/cherry_picker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
import subprocess
import webbrowser
import sys
import requests

from gidgethub import sansio

from . import __version__

CPYTHON_CREATE_PR_URL = "https://api.github.com/repos/python/cpython/pulls"

class CherryPicker:

Expand Down Expand Up @@ -139,9 +143,10 @@ def amend_commit_message(self, cherry_pick_branch):
except subprocess.CalledProcessError as cpe:
click.echo("Failed to amend the commit message \u2639")
click.echo(cpe.output)
return updated_commit_message


def push_to_remote(self, base_branch, head_branch):
def push_to_remote(self, base_branch, head_branch, commit_message=""):
""" git push <origin> <branchname> """

cmd = f"git push {self.pr_remote} {head_branch}"
Expand All @@ -150,7 +155,36 @@ def push_to_remote(self, base_branch, head_branch):
except subprocess.CalledProcessError:
click.echo(f"Failed to push to {self.pr_remote} \u2639")
else:
self.open_pr(self.get_pr_url(base_branch, head_branch))
gh_auth = os.getenv("GH_AUTH")
if gh_auth:
self.create_gh_pr(base_branch, head_branch,
commit_message=commit_message,
gh_auth=gh_auth)
else:
self.open_pr(self.get_pr_url(base_branch, head_branch))

def create_gh_pr(self, base_branch, head_branch, *,
commit_message,
gh_auth):
"""
Create PR in GitHub
"""
request_headers = sansio.create_headers(
self.username, oauth_token=gh_auth)
title, body = normalize_commit_message(commit_message)
data = {
"title": title,
"body": body,
"head": f"{self.username}:{head_branch}",
"base": base_branch,
"maintainer_can_modify": True
}
response = requests.post(CPYTHON_CREATE_PR_URL, headers=request_headers, json=data)
if response.status_code == requests.codes.created:
click.echo(f"Backport PR created at {response.json()['_links']['html']}")
else:
click.echo(response.status_code)
click.echo(response.text)

def open_pr(self, url):
"""
Expand Down Expand Up @@ -184,16 +218,19 @@ def backport(self):

cherry_pick_branch = self.get_cherry_pick_branch(maint_branch)
self.checkout_branch(maint_branch)
commit_message = ""
try:
self.cherry_pick()
self.amend_commit_message(cherry_pick_branch)
commit_message = self.amend_commit_message(cherry_pick_branch)
except subprocess.CalledProcessError as cpe:
click.echo(cpe.output)
click.echo(self.get_exit_message(maint_branch))
sys.exit(-1)
else:
if self.push:
self.push_to_remote(maint_branch, cherry_pick_branch)
self.push_to_remote(maint_branch,
cherry_pick_branch,
commit_message)
self.cleanup_branch(cherry_pick_branch)
else:
click.echo(\
Expand Down Expand Up @@ -331,6 +368,15 @@ def is_cpython_repo():
return False
return True

def normalize_commit_message(commit_message):
"""
Return a tuple of title and body from the commit message
"""
split_commit_message = commit_message.split("\n")
title = split_commit_message[0]
body = "\n".join(split_commit_message[1:])
return title, body.lstrip("\n")


if __name__ == '__main__':
cherry_pick_cli()
24 changes: 23 additions & 1 deletion cherry_picker/cherry_picker/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pytest

from .cherry_picker import get_base_branch, get_current_branch, \
get_full_sha_from_short, is_cpython_repo, CherryPicker
get_full_sha_from_short, is_cpython_repo, CherryPicker, \
normalize_commit_message


def test_get_base_branch():
Expand Down Expand Up @@ -112,3 +113,24 @@ def test_is_cpython_repo(subprocess_check_output):
def test_is_not_cpython_repo():
assert is_cpython_repo() == False

def test_normalize_long_commit_message():
commit_message = """[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)"""
title, body = normalize_commit_message(commit_message)
assert title == "[3.6] Fix broken `Show Source` links on documentation pages (GH-3113)"
assert body == """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)"""

def test_normalize_short_commit_message():
commit_message = """[3.6] Fix broken `Show Source` links on documentation pages (GH-3113)

(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69)"""
title, body = normalize_commit_message(commit_message)
assert title == "[3.6] Fix broken `Show Source` links on documentation pages (GH-3113)"
assert body == """(cherry picked from commit b9ff498793611d1c6a9b99df464812931a1e2d69)"""
2 changes: 2 additions & 0 deletions cherry_picker/flit.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ maintainer = Python Core Developers
maintainer-email = core-workflow@python.org
home-page = https://github.com/python/core-workflow/tree/master/cherry_picker
requires = click~=6.7
gidgethub
requests
dev-requires = pytest~=3.0.7
description-file = readme.rst
classifiers = Programming Language :: Python :: 3.6
Expand Down
2 changes: 1 addition & 1 deletion cherry_picker/readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ maintenance branches (``3.6``, ``3.5``, ``2.7``).
It will prefix the commit message with the branch, e.g. ``[3.6]``, and then
opens up the pull request page.

Tests are to be written using pytest.
Tests are to be written using `pytest <https://docs.pytest.org/en/latest/>`_.


Setup Info
Expand Down