Skip to content

[3.6] bpo-29656: Handle PR branches in 'make patchcheck' (#302) #626

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

Merged
merged 1 commit into from
Mar 12, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 52 additions & 6 deletions Tools/scripts/patchcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

SRCDIR = sysconfig.get_config_var('srcdir')


def n_files_str(count):
"""Return 'N file(s)' with the proper plurality on 'file'."""
return "{} file{}".format(count, "s" if count != 1 else "")
Expand Down Expand Up @@ -46,27 +45,73 @@ def mq_patches_applied():
return st.returncode == 0 and bstdout


def get_git_branch():
"""Get the symbolic name for the current git branch"""
cmd = "git rev-parse --abbrev-ref HEAD".split()
try:
return subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
return None


def get_git_upstream_remote():
"""Get the remote name to use for upstream branches

Uses "upstream" if it exists, "origin" otherwise
"""
cmd = "git remote get-url upstream".split()
try:
subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
return "origin"
return "upstream"


@status("Getting base branch for PR",
info=lambda x: x if x is not None else "not a PR branch")
def get_base_branch():
if not os.path.isdir(os.path.join(SRCDIR, '.git')):
# Not a git checkout, so there's no base branch
return None
version = sys.version_info
if version.releaselevel == 'alpha':
base_branch = "master"
else:
base_branch = "{0.major}.{0.minor}".format(version)
this_branch = get_git_branch()
if this_branch is None or this_branch == base_branch:
# Not on a git PR branch, so there's no base branch
return None
upstream_remote = get_git_upstream_remote()
return upstream_remote + "/" + base_branch


@status("Getting the list of files that have been added/changed",
info=lambda x: n_files_str(len(x)))
def changed_files():
def changed_files(base_branch=None):
"""Get the list of changed or added files from Mercurial or git."""
if os.path.isdir(os.path.join(SRCDIR, '.hg')):
if base_branch is not None:
sys.exit('need a git checkout to check PR status')
cmd = 'hg status --added --modified --no-status'
if mq_patches_applied():
cmd += ' --rev qparent'
with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st:
return [x.decode().rstrip() for x in st.stdout]
elif os.path.isdir(os.path.join(SRCDIR, '.git')):
cmd = 'git status --porcelain'
if base_branch:
cmd = 'git diff --name-status ' + base_branch
else:
cmd = 'git status --porcelain'
filenames = []
with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st:
for line in st.stdout:
line = line.decode().rstrip()
status = set(line[:2])
status_text, filename = line.split(maxsplit=1)
status = set(status_text)
# modified, added or unmerged files
if not status.intersection('MAU'):
continue
filename = line[3:]
if ' -> ' in filename:
# file is renamed
filename = filename.split(' -> ', 2)[1].strip()
Expand Down Expand Up @@ -165,7 +210,8 @@ def regenerated_pyconfig_h_in(file_paths):
return "not needed"

def main():
file_paths = changed_files()
base_branch = get_base_branch()
file_paths = changed_files(base_branch)
python_files = [fn for fn in file_paths if fn.endswith('.py')]
c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))]
doc_files = [fn for fn in file_paths if fn.startswith('Doc') and
Expand Down