From: Simon Glass <simon.glass@canonical.com>
When the database is upgraded to v5, try to auto-detect the upstream
for each series that has a NULL upstream. This queries the git branch's
remote tracking configuration and sets the upstream if a real remote
(not local tracking with '.') is found.
Series where auto-detection fails are still reported as a warning so the
user can set them manually.
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---
tools/patman/cser_helper.py | 35 +++++++++++++++++++++++++++++++----
tools/patman/test_cseries.py | 32 ++++++++++++++++++++++----------
2 files changed, 53 insertions(+), 14 deletions(-)
@@ -118,12 +118,39 @@ class CseriesHelper:
self.db.open_it()
def _check_null_upstreams(self):
- """Warn about series that have no upstream set"""
+ """Detect and warn about series that have no upstream set
+
+ For each series without an upstream, try to detect it from the
+ git branch's remote tracking configuration. Any series that
+ cannot be auto-detected are reported as a warning.
+ """
names = self.db.series_get_null_upstream()
- if names:
+ if not names:
+ return
+
+ still_null = []
+ git_dir = self.gitdir or '.git'
+ for name in names:
+ remote_name = None
+ if gitutil.check_branch(name, git_dir=self.gitdir):
+ us_ref, _ = gitutil.get_upstream(git_dir, name)
+ if us_ref and '/' in us_ref and not us_ref.startswith(
+ 'refs/'):
+ remote_name = us_ref.split('/')[0]
+ if remote_name:
+ idnum = self.db.series_find_by_name(name)
+ self.db.series_set_upstream(idnum, remote_name)
+ tout.progress(f"Set upstream for series '{name}' to "
+ f"'{remote_name}'", trailer='')
+ else:
+ still_null.append(name)
+
+ if len(still_null) < len(names):
+ self.db.commit()
+ if still_null:
tout.warning(
- f'{len(names)} series without an upstream:')
- for name in names:
+ f'{len(still_null)} series without an upstream:')
+ for name in still_null:
tout.warning(f' {name}')
def close_database(self):
@@ -3367,11 +3367,20 @@ Date: .*
def test_migrate_upstream_warning(self):
"""Test that migrating to v5 warns about series without upstream"""
+ self.make_git_tree()
+
+ # Set 'first' branch to track a remote-style upstream so that
+ # auto-detection can find it
+ self.repo.config.set_multivar('branch.first.remote', '', 'origin')
+ self.repo.config.set_multivar('branch.first.merge', '',
+ 'refs/heads/main')
+
db = database.Database(f'{self.tmpdir}/.patman2.db')
with terminal.capture():
db.open_it()
- # Create a v4 database with some series
+ # Create a v4 database with some series; 'first' has a matching
+ # branch with a detectable remote, 'second' and 'third' do not
with terminal.capture() as (out, _):
db.migrate_to(4)
self.assertEqual(
@@ -3390,10 +3399,9 @@ Date: .*
db.commit()
db.close()
- # Now open via CseriesHelper which triggers migration and check
- self.make_git_tree()
cser = cseries.Cseries(self.tmpdir, terminal.COLOR_NEVER)
cser.topdir = self.tmpdir
+ cser.gitdir = self.gitdir
# Point at our v4 database
database.Database.instances = {}
@@ -3403,18 +3411,22 @@ Date: .*
old_version = cser.db.start()
self.assertEqual(4, old_version)
- # Set upstream on one series so only two are reported
- idnum = cser.db.series_find_by_name('second')
- cser.db.series_set_upstream(idnum, 'us')
- cser.db.commit()
-
- with terminal.capture() as (_, err):
+ # 'first' should be auto-detected, 'second' and 'third' have no
+ # matching branch with a remote upstream
+ with terminal.capture() as (out, err):
cser._check_null_upstreams()
+ self.assertIn("Set upstream for series 'first' to 'origin'",
+ out.getvalue())
lines = err.getvalue().strip().splitlines()
self.assertEqual('2 series without an upstream:', lines[0])
- self.assertEqual(' first', lines[1])
+ self.assertEqual(' second', lines[1])
self.assertEqual(' third', lines[2])
+ # Check that 'first' was actually updated in the database
+ slist = cser.db.series_get_dict()
+ self.assertEqual('origin', slist['first'].upstream)
+ self.assertIsNone(slist['second'].upstream)
+
cser.db.close()
def test_series_scan(self):