From 83c16a48fe00ab1bdbe68ecf5561b95fbd3792b9 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Mon, 15 Aug 2016 16:09:44 -0400 Subject: [PATCH] make list-changes smarter about the "previous" version The old implementation of list-changes assumed that the deliverable file included all releases and that they were in order. That assumption does not hold for independent projects, where the history might not be there and new entries might be from different branches than the previous entries, all in the same file. This change uses git to determine the previous tag for each repository, then shows the right diffs based on that instead of the assumed tag from the deliverable file. Change-Id: I122a6ec1792a07cdb23f09a880110dff2446555e Signed-off-by: Doug Hellmann --- openstack_releases/cmds/list_changes.py | 63 ++++++++++++++++++------- openstack_releases/gitutils.py | 7 ++- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/openstack_releases/cmds/list_changes.py b/openstack_releases/cmds/list_changes.py index c1114843b2..c511e1b5b9 100644 --- a/openstack_releases/cmds/list_changes.py +++ b/openstack_releases/cmds/list_changes.py @@ -63,8 +63,9 @@ def git_branch_contains(workdir, repo, title, commit): header('%s %s' % (title, commit)) cmd = ['git', 'branch', '-r', '--contains', commit] print('\n' + ' '.join(cmd) + '\n') - subprocess.check_call(cmd, cwd=os.path.join(workdir, repo)) - print() + out = subprocess.check_output(cmd, cwd=os.path.join(workdir, repo)) + print(out + '\n') + return [o.strip() for o in out.splitlines()] def git_diff(workdir, repo, git_range, file_pattern): @@ -166,13 +167,17 @@ def main(): else: branch = 'stable/' + series - # assume the releases are in order and take the last two + # assume the releases are in order and take the last one new_release = deliverable_info['releases'][-1] - if len(deliverable_info['releases']) >= 2: - previous_release = deliverable_info['releases'][-2] - else: - previous_release = None + + # build a map between version numbers and the release details + by_version = { + str(r['version']): r + for r in deliverable_info['releases'] + } + for project in new_release['projects']: + tag_exists = gitutils.commit_exists( project['repo'], new_release['version'], @@ -182,7 +187,7 @@ def main(): (project['repo'], new_release['version'])) # Check out the code. - print('\nChecking out repository') + print('\nChecking out repository {}'.format(project['repo'])) subprocess.check_call( ['zuul-cloner', '--branch', branch, @@ -192,18 +197,23 @@ def main(): ] ) - start_range = None + # look at the previous tag for the parent of the commit + # getting the new release + previous_tag = gitutils.get_latest_tag( + workdir, + project['repo'], + '{}^'.format(project['hash']) + ) + previous_release = by_version.get(previous_tag) + + start_range = previous_tag if previous_release: previous_project = { x['repo']: x for x in previous_release['projects'] }.get(project['repo']) if previous_project is not None: - start_range = previous_project['hash'] - if not start_range: - start_range = ( - gitutils.get_latest_tag(workdir, project['repo']) or None - ) + start_range = previous_tag if start_range: git_range = '%s..%s' % (start_range, project['hash']) @@ -229,14 +239,32 @@ def main(): ref=project['hash'], ) - git_branch_contains( + branches = git_branch_contains( workdir=workdir, repo=project['repo'], title='Branches containing commit', commit=project['hash'], ) - head_sha = gitutils.sha_for_tag(workdir, project['repo'], 'HEAD') + header('Relationship to HEAD') + if series == '_independent': + interesting_branches = sorted( + b for b in branches + if '->' not in b + ) + head_sha = gitutils.sha_for_tag( + workdir, + project['repo'], + interesting_branches[0], + ) + print('HEAD of {} is {}'.format(interesting_branches[0], head_sha)) + else: + head_sha = gitutils.sha_for_tag( + workdir, + project['repo'], + 'HEAD', + ) + print('HEAD of {} is {}'.format(branch, head_sha)) requested_sha = gitutils.sha_for_tag( workdir, project['repo'], @@ -247,12 +275,11 @@ def main(): # git to give us the real SHA for the requested release in # case the deliverables file has the short version of the # hash. - header('Relationship to HEAD') if head_sha == requested_sha: print('\nRequest releases from HEAD on %s' % branch) else: git_log(workdir, project['repo'], 'Release will NOT include', - '%s..%s~1' % (requested_sha, head_sha), + '%s..%s' % (requested_sha, head_sha), extra_args=['--format=%h %ci %s']) # Show any requirements changes in the upcoming release. diff --git a/openstack_releases/gitutils.py b/openstack_releases/gitutils.py index 6c46ec5b10..04500dc316 100644 --- a/openstack_releases/gitutils.py +++ b/openstack_releases/gitutils.py @@ -112,10 +112,13 @@ def check_ancestry(workdir, repo, old_version, sha): return False -def get_latest_tag(workdir, repo): +def get_latest_tag(workdir, repo, sha=None): + cmd = ['git', 'describe', '--abbrev=0'] + if sha is not None: + cmd.append(sha) try: return subprocess.check_output( - ['git', 'describe', '--abbrev=0'], + cmd, cwd=os.path.join(workdir, repo), stderr=subprocess.STDOUT, ).strip()