stop scanning at the base of a branch
By default, stop scanning when we hit the version that is at the base of a branch. Change-Id: I4eaa03d15bafa8dc3bdbdae3707295040482ec04 Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
parent
e2fe07d13f
commit
6f6e7addfb
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- Automatically stop scanning branches at the point where they
|
||||
diverge from master. This avoids having release notes from older
|
||||
versions, that appear on master before the branch, from showing up
|
||||
in the versions from the branch. This logic is only applied to
|
||||
branches created from master.
|
@ -78,6 +78,64 @@ def _get_unique_id(filename):
|
||||
return uniqueid
|
||||
|
||||
|
||||
def _get_branch_base(reporoot, branch):
|
||||
"Return the tag at base of the branch."
|
||||
# Based on
|
||||
# http://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git
|
||||
# git rev-list $(git rev-list --first-parent \
|
||||
# ^origin/stable/newton master | tail -n1)^^!
|
||||
#
|
||||
# Determine the list of commits accessible from the branch we are
|
||||
# supposed to be scanning, but not on master.
|
||||
cmd = [
|
||||
'git',
|
||||
'rev-list',
|
||||
'--first-parent',
|
||||
branch, # on the branch
|
||||
'^master', # not on master
|
||||
]
|
||||
try:
|
||||
LOG.debug(' '.join(cmd))
|
||||
parents = utils.check_output(cmd, cwd=reporoot).strip()
|
||||
if not parents:
|
||||
# There are no commits on the branch, yet, so we can use
|
||||
# our current-version logic.
|
||||
return _get_current_version(reporoot, branch)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warning('failed to retrieve branch base: %s [%s]',
|
||||
e, e.output.strip())
|
||||
return None
|
||||
parent = parents.splitlines()[-1]
|
||||
LOG.debug('parent = %r', parent)
|
||||
# Now get the previous commit, which should be the one we tagged
|
||||
# to create the branch.
|
||||
cmd = [
|
||||
'git',
|
||||
'rev-list',
|
||||
'{}^^!'.format(parent),
|
||||
]
|
||||
try:
|
||||
sha = utils.check_output(cmd, cwd=reporoot).strip()
|
||||
LOG.debug('sha = %r', sha)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warning('failed to retrieve branch base: %s [%s]',
|
||||
e, e.output.strip())
|
||||
return None
|
||||
# Now get the tag for that commit.
|
||||
cmd = [
|
||||
'git',
|
||||
'describe',
|
||||
'--abbrev=0',
|
||||
sha,
|
||||
]
|
||||
try:
|
||||
return utils.check_output(cmd, cwd=reporoot).strip()
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warning('failed to retrieve branch base: %s [%s]',
|
||||
e, e.output.strip())
|
||||
return None
|
||||
|
||||
|
||||
# The git log output from _get_tags_on_branch() looks like this sample
|
||||
# from the openstack/nova repository for git 1.9.1:
|
||||
#
|
||||
@ -164,9 +222,26 @@ def get_notes_by_version(conf):
|
||||
reporoot = conf.reporoot
|
||||
notesdir = conf.notespath
|
||||
branch = conf.branch
|
||||
earliest_version = conf.earliest_version
|
||||
collapse_pre_releases = conf.collapse_pre_releases
|
||||
|
||||
LOG.debug('scanning %s/%s (branch=%s)' % (reporoot, notesdir, branch))
|
||||
|
||||
# If the user has not told us where to stop, try to work it out
|
||||
# for ourselves. If branch is set and is not "master", then we
|
||||
# want to stop at the base of the branch.
|
||||
if (not earliest_version) and branch and (branch != 'master'):
|
||||
LOG.debug('determining earliest_version from branch')
|
||||
earliest_version = _get_branch_base(reporoot, branch)
|
||||
if earliest_version and collapse_pre_releases:
|
||||
if PRE_RELEASE_RE.search(earliest_version):
|
||||
# The earliest version won't actually be the pre-release
|
||||
# that might have been tagged when the branch was created,
|
||||
# but the final version. Strip the pre-release portion of
|
||||
# the version number.
|
||||
earliest_version = '.'.join(earliest_version.split('.')[:-1])
|
||||
LOG.debug('using earliest_version = %r', earliest_version)
|
||||
|
||||
# Determine all of the tags known on the branch, in their date
|
||||
# order. We scan the commit history in topological order to ensure
|
||||
# we have the commits in the right version, so we might encounter
|
||||
@ -319,7 +394,7 @@ def get_notes_by_version(conf):
|
||||
|
||||
# Combine pre-releases into the final release, if we are told to
|
||||
# and the final release exists.
|
||||
if conf.collapse_pre_releases:
|
||||
if collapse_pre_releases:
|
||||
collapsing = files_and_tags
|
||||
files_and_tags = collections.OrderedDict()
|
||||
for ov in versions_by_date:
|
||||
@ -365,7 +440,7 @@ def get_notes_by_version(conf):
|
||||
trimmed[ov] = sorted(files_and_tags[ov])
|
||||
# If we have been told to stop at a version, we can do that
|
||||
# now.
|
||||
if conf.earliest_version and ov == conf.earliest_version:
|
||||
if earliest_version and ov == earliest_version:
|
||||
break
|
||||
|
||||
LOG.debug('[reno] found %d versions and %d files',
|
||||
|
@ -815,13 +815,179 @@ class BranchTest(Base):
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'1.0.0': [self.f1],
|
||||
'2.0.0': [self.f2],
|
||||
'2.0.0-1': [f21],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
def test_pre_release_branch_no_collapse(self):
|
||||
f4 = self._add_notes_file('slug4')
|
||||
self._run_git('tag', '-s', '-m', 'pre-release', '4.0.0.0rc1')
|
||||
# Add a commit on master after the tag
|
||||
self._add_notes_file('slug5')
|
||||
# Move back to the tag and create the branch
|
||||
self._run_git('checkout', '4.0.0.0rc1')
|
||||
self._run_git('checkout', '-b', 'stable/4')
|
||||
# Create a commit on the branch
|
||||
f41 = self._add_notes_file('slug41')
|
||||
log_text = self._run_git(
|
||||
'log', '--pretty=%x00%H %d', '--name-only', '--graph',
|
||||
'--all', '--decorate',
|
||||
)
|
||||
self.addDetail('git log', text_content(log_text))
|
||||
rev_list = self._run_git('rev-list', '--first-parent',
|
||||
'^stable/4', 'master')
|
||||
self.addDetail('rev-list', text_content(rev_list))
|
||||
self.c.override(
|
||||
branch='stable/4',
|
||||
collapse_pre_releases=False,
|
||||
)
|
||||
raw_results = scanner.get_notes_by_version(self.c)
|
||||
results = {
|
||||
k: [f for (f, n) in v]
|
||||
for (k, v) in raw_results.items()
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'4.0.0.0rc1': [f4],
|
||||
'4.0.0.0rc1-1': [f41],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
def test_pre_release_branch_collapse(self):
|
||||
f4 = self._add_notes_file('slug4')
|
||||
self._run_git('tag', '-s', '-m', 'pre-release', '4.0.0.0rc1')
|
||||
# Add a commit on master after the tag
|
||||
self._add_notes_file('slug5')
|
||||
# Move back to the tag and create the branch
|
||||
self._run_git('checkout', '4.0.0.0rc1')
|
||||
self._run_git('checkout', '-b', 'stable/4')
|
||||
# Create a commit on the branch
|
||||
f41 = self._add_notes_file('slug41')
|
||||
self._run_git('tag', '-s', '-m', 'release', '4.0.0')
|
||||
log_text = self._run_git(
|
||||
'log', '--pretty=%x00%H %d', '--name-only', '--graph',
|
||||
'--all', '--decorate',
|
||||
)
|
||||
self.addDetail('git log', text_content(log_text))
|
||||
rev_list = self._run_git('rev-list', '--first-parent',
|
||||
'^stable/4', 'master')
|
||||
self.addDetail('rev-list', text_content(rev_list))
|
||||
self.c.override(
|
||||
branch='stable/4',
|
||||
collapse_pre_releases=True,
|
||||
)
|
||||
raw_results = scanner.get_notes_by_version(self.c)
|
||||
results = {
|
||||
k: [f for (f, n) in v]
|
||||
for (k, v) in raw_results.items()
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'4.0.0': [f4, f41],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
def test_full_release_branch(self):
|
||||
f4 = self._add_notes_file('slug4')
|
||||
self._run_git('tag', '-s', '-m', 'release', '4.0.0')
|
||||
# Add a commit on master after the tag
|
||||
self._add_notes_file('slug5')
|
||||
# Move back to the tag and create the branch
|
||||
self._run_git('checkout', '4.0.0')
|
||||
self._run_git('checkout', '-b', 'stable/4')
|
||||
# Create a commit on the branch
|
||||
f41 = self._add_notes_file('slug41')
|
||||
log_text = self._run_git(
|
||||
'log', '--pretty=%x00%H %d', '--name-only', '--graph',
|
||||
'--all', '--decorate',
|
||||
)
|
||||
self.addDetail('git log', text_content(log_text))
|
||||
rev_list = self._run_git('rev-list', '--first-parent',
|
||||
'^stable/4', 'master')
|
||||
self.addDetail('rev-list', text_content(rev_list))
|
||||
self.c.override(
|
||||
branch='stable/4',
|
||||
)
|
||||
raw_results = scanner.get_notes_by_version(self.c)
|
||||
results = {
|
||||
k: [f for (f, n) in v]
|
||||
for (k, v) in raw_results.items()
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'4.0.0': [f4],
|
||||
'4.0.0-1': [f41],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
def test_branch_tip_of_master(self):
|
||||
# We have branched from master, but not added any commits to
|
||||
# master.
|
||||
f4 = self._add_notes_file('slug4')
|
||||
self._run_git('tag', '-s', '-m', 'release', '4.0.0')
|
||||
self._run_git('checkout', '-b', 'stable/4')
|
||||
# Create a commit on the branch
|
||||
f41 = self._add_notes_file('slug41')
|
||||
f42 = self._add_notes_file('slug42')
|
||||
log_text = self._run_git(
|
||||
'log', '--pretty=%x00%H %d', '--name-only', '--graph',
|
||||
'--all', '--decorate',
|
||||
)
|
||||
self.addDetail('git log', text_content(log_text))
|
||||
rev_list = self._run_git('rev-list', '--first-parent',
|
||||
'^stable/4', 'master')
|
||||
self.addDetail('rev-list', text_content(rev_list))
|
||||
self.c.override(
|
||||
branch='stable/4',
|
||||
)
|
||||
raw_results = scanner.get_notes_by_version(self.c)
|
||||
results = {
|
||||
k: [f for (f, n) in v]
|
||||
for (k, v) in raw_results.items()
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'4.0.0': [f4],
|
||||
'4.0.0-2': [f41, f42],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
def test_branch_no_more_commits(self):
|
||||
# We have branched from master, but not added any commits to
|
||||
# our branch or to master.
|
||||
f4 = self._add_notes_file('slug4')
|
||||
self._run_git('tag', '-s', '-m', 'release', '4.0.0')
|
||||
self._run_git('checkout', '-b', 'stable/4')
|
||||
# Create a commit on the branch
|
||||
log_text = self._run_git(
|
||||
'log', '--pretty=%x00%H %d', '--name-only', '--graph',
|
||||
'--all', '--decorate',
|
||||
)
|
||||
self.addDetail('git log', text_content(log_text))
|
||||
rev_list = self._run_git('rev-list', '--first-parent',
|
||||
'^stable/4', 'master')
|
||||
self.addDetail('rev-list', text_content(rev_list))
|
||||
self.c.override(
|
||||
branch='stable/4',
|
||||
)
|
||||
raw_results = scanner.get_notes_by_version(self.c)
|
||||
results = {
|
||||
k: [f for (f, n) in v]
|
||||
for (k, v) in raw_results.items()
|
||||
}
|
||||
self.assertEqual(
|
||||
{
|
||||
'4.0.0': [f4],
|
||||
},
|
||||
results,
|
||||
)
|
||||
|
||||
|
||||
class GetTagsParseTest(base.TestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user