diff --git a/releasenotes/notes/cache-scan-all-branches-a935824a844d1d9f.yaml b/releasenotes/notes/cache-scan-all-branches-a935824a844d1d9f.yaml new file mode 100644 index 0000000..0102507 --- /dev/null +++ b/releasenotes/notes/cache-scan-all-branches-a935824a844d1d9f.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + The ``reno cache`` command and ``build_reno`` setuptools command now + default to scanning to all enabled branches. This ensures the cache is + complete for projects that use multiple branches, such as stable branches. diff --git a/reno/cache.py b/reno/cache.py index 20c2a8e..326bae6 100644 --- a/reno/cache.py +++ b/reno/cache.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +import collections import os import sys @@ -21,7 +22,14 @@ from reno import scanner def build_cache_db(conf, versions_to_include): s = scanner.Scanner(conf) - notes = s.get_notes_by_version() + + branches = [conf.branch] + if not conf.branch: # if no branch requested, scan all + branches += s.get_series_branches() + + notes = collections.OrderedDict() + for branch in branches: + notes.update(s.get_notes_by_version(branch)) # Default to including all versions returned by the scanner. if not versions_to_include: diff --git a/reno/scanner.py b/reno/scanner.py index da7f88a..d1dca86 100644 --- a/reno/scanner.py +++ b/reno/scanner.py @@ -810,7 +810,7 @@ class Scanner(object): "Return true if the file exists at the given commit." return bool(self.get_file_at_commit(filename, sha)) - def _get_series_branches(self): + def get_series_branches(self): "Get branches matching the branch_name_re config option." refs = self._repo.get_refs() LOG.debug('refs %s', list(refs.keys())) @@ -846,7 +846,7 @@ class Scanner(object): if branch.startswith('origin/'): branch = branch[7:] LOG.debug('looking for the branch before %s', branch) - branch_names = self._get_series_branches() + branch_names = self.get_series_branches() if branch not in branch_names: LOG.debug('Could not find branch %r among %s', branch, branch_names) @@ -910,7 +910,7 @@ class Scanner(object): return candidate return None - def get_notes_by_version(self): + def get_notes_by_version(self, branch=None): """Return an OrderedDict mapping versions to lists of notes files. The versions are presented in reverse chronological order. @@ -918,13 +918,13 @@ class Scanner(object): Notes files are associated with the earliest version for which they were available, regardless of whether they changed later. - :param reporoot: Path to the root of the git repository. - :type reporoot: str + :param branch: The branch to scan. If not provided, using the branch + configured in ``self.conf``. """ reporoot = self.reporoot notesdir = self.conf.notespath - branch = self.conf.branch + branch = branch or self.conf.branch earliest_version = self.conf.earliest_version collapse_pre_releases = self.conf.collapse_pre_releases stop_at_branch_base = self.conf.stop_at_branch_base @@ -967,7 +967,7 @@ class Scanner(object): # On the current branch, stop at the point where the most # recent branch was created, if we can find one. LOG.debug('working on current branch without earliest_version') - branches = self._get_series_branches() + branches = self.get_series_branches() if branches: for earlier_branch in reversed(branches): LOG.debug('checking if current branch is later than %s', diff --git a/reno/tests/test_cache.py b/reno/tests/test_cache.py index abf19a2..5d158d4 100644 --- a/reno/tests/test_cache.py +++ b/reno/tests/test_cache.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import collections import fixtures import textwrap @@ -24,10 +25,15 @@ from reno.tests import base class TestCache(base.TestCase): - scanner_output = { - '0.0.0': [('note1', 'shaA')], - '1.0.0': [('note2', 'shaB'), ('note3', 'shaC')], - } + scanner_output = [ + collections.OrderedDict([ # master + ('0.0.0', [('note1', 'shaA')]), + ('1.0.0', [('note2', 'shaB'), ('note3', 'shaC')]), + ]), + collections.OrderedDict([ # stable/1.0 + ('1.0.1', [('note4', 'shaD')]), + ]), + ] note_bodies = { 'note1': textwrap.dedent(""" @@ -42,7 +48,11 @@ class TestCache(base.TestCase): 'note3': textwrap.dedent(""" features: - We added a feature! - """) + """), + 'note4': textwrap.dedent(""" + fixes: + - We fixed all the bugs! + """), } def _get_note_body(self, filename, sha): @@ -57,12 +67,18 @@ class TestCache(base.TestCase): self.c = config.Config('.') @mock.patch('reno.scanner.Scanner.get_notes_by_version') - def test_build_cache_db(self, gnbv): - gnbv.return_value = self.scanner_output + @mock.patch('reno.scanner.Scanner.get_series_branches') + def test_build_cache_db(self, mock_get_branches, mock_get_notes): + mock_get_notes.side_effect = self.scanner_output + mock_get_branches.return_value = ['stable/1.0'] expected = { 'notes': [ - {'version': k, 'files': v} - for k, v in self.scanner_output.items() + {'version': '0.0.0', + 'files': [('note1', 'shaA')]}, + {'version': '1.0.0', + 'files': [('note2', 'shaB'), ('note3', 'shaC')]}, + {'version': '1.0.1', + 'files': [('note4', 'shaD')]}, ], 'file-contents': { 'note1': { @@ -77,6 +93,9 @@ class TestCache(base.TestCase): 'note3': { 'features': ['We added a feature!'], }, + 'note4': { + 'fixes': ['We fixed all the bugs!'], + }, }, } @@ -85,4 +104,7 @@ class TestCache(base.TestCase): versions_to_include=[], ) + mock_get_branches.assert_called_once() + mock_get_notes.assert_has_calls([ + mock.call(None), mock.call('stable/1.0')]) self.assertEqual(expected, db) diff --git a/reno/tests/test_scanner.py b/reno/tests/test_scanner.py index 5c7a794..297188c 100644 --- a/reno/tests/test_scanner.py +++ b/reno/tests/test_scanner.py @@ -2432,7 +2432,7 @@ class GetSeriesBranchesTest(Base): self.scanner = scanner.Scanner(self.c) self.assertEqual( [], - self.scanner._get_series_branches(), + self.scanner.get_series_branches(), ) def test_real_branches_sorted_names(self): @@ -2445,7 +2445,7 @@ class GetSeriesBranchesTest(Base): self.scanner = scanner.Scanner(self.c) self.assertEqual( ['stable/a', 'stable/b'], - self.scanner._get_series_branches(), + self.scanner.get_series_branches(), ) def test_eol_tag(self): @@ -2455,7 +2455,7 @@ class GetSeriesBranchesTest(Base): self.scanner = scanner.Scanner(self.c) self.assertEqual( ['stable/a'], - self.scanner._get_series_branches(), + self.scanner.get_series_branches(), ) def test_mix_tag_and_branch(self): @@ -2468,5 +2468,5 @@ class GetSeriesBranchesTest(Base): self.scanner = scanner.Scanner(self.c) self.assertEqual( ['stable/a', 'stable/b'], - self.scanner._get_series_branches(), + self.scanner.get_series_branches(), )