@@ -406,7 +406,7 @@ def add_upstream_subparser(subparsers):
upstream = subparsers.add_parser('upstream', aliases=ALIASES['upstream'],
help='Manage upstream destinations')
upstream.defaults_cmds = [
- ['add', 'us', 'http://fred', 'U-Boot'],
+ ['add', 'us', 'http://fred', '-p', 'http://pw', 'U-Boot'],
['delete', 'us'],
]
upstream_subparsers = upstream.add_subparsers(dest='subcmd')
@@ -416,6 +416,10 @@ def add_upstream_subparser(subparsers):
uadd.add_argument(
'url', help='URL to use for this upstream, e.g. '
"'https://gitlab.denx.de/u-boot/u-boot.git'")
+ uadd.add_argument(
+ '-p', '--patchwork-url',
+ help='URL of patchwork server for this upstream, e.g. '
+ "'https://patchwork.ozlabs.org'")
uadd.add_argument(
'project_name', nargs='?',
help="Patchwork project name, e.g. 'U-Boot'")
@@ -134,8 +134,18 @@ def do_series(args, test_db=None, pwork=None, cser=None):
cser.open_database()
if args.subcmd in needs_patchwork:
if not pwork:
- pwork = Patchwork(args.patchwork_url)
ups = cser.get_series_upstream(args.series)
+ pw_url = None
+ if ups:
+ pw_url = cser.db.upstream_get_patchwork_url(ups)
+ if not pw_url:
+ pw_url = args.patchwork_url
+ if not pw_url:
+ raise ValueError(
+ 'No patchwork URL found for upstream '
+ f"'{ups}'; use 'patman upstream add' with "
+ '-p or pass --patchwork-url')
+ pwork = Patchwork(pw_url)
proj = cser.project_get(ups)
if not proj:
proj = cser.project_get()
@@ -239,11 +249,9 @@ def upstream(args, test_db=None):
try:
cser.open_database()
if args.subcmd == 'add':
- pwork = None
- if args.project_name:
- pwork = Patchwork(args.patchwork_url)
cser.upstream_add(args.remote_name, args.url,
- args.project_name, pwork)
+ args.project_name,
+ patchwork_url=args.patchwork_url)
elif args.subcmd == 'default':
if args.unset:
cser.upstream_set_default(None)
@@ -279,7 +287,15 @@ def patchwork(args, test_db=None, pwork=None):
if not args.remote:
raise ValueError('Please specify the remote name')
if not pwork:
- pwork = Patchwork(args.patchwork_url)
+ pw_url = cser.db.upstream_get_patchwork_url(args.remote)
+ if not pw_url:
+ pw_url = args.patchwork_url
+ if not pw_url:
+ raise ValueError(
+ f"No patchwork URL for remote '{args.remote}'"
+ "; use 'patman upstream add' with -p"
+ ' or pass --patchwork-url')
+ pwork = Patchwork(pw_url)
cser.project_set(pwork, args.project_name,
ups=args.remote)
elif args.subcmd == 'get-project':
@@ -16,6 +16,7 @@ from u_boot_pylib import terminal
from u_boot_pylib import tout
from patman import patchstream
+from patman.patchwork import Patchwork
from patman import cser_helper
from patman.cser_helper import AUTOLINK, oid
from patman import send
@@ -1145,7 +1146,8 @@ class Cseries(cser_helper.CseriesHelper):
self.rollback()
tout.info('Dry run completed')
- def upstream_add(self, name, url, project=None, pwork=None):
+ def upstream_add(self, name, url, project=None, pwork=None,
+ patchwork_url=None):
"""Add a new upstream tree
Args:
@@ -1154,12 +1156,21 @@ class Cseries(cser_helper.CseriesHelper):
project (str or None): Patchwork project name to associate
pwork (Patchwork or None): Patchwork object for looking up
the project
+ patchwork_url (str or None): URL of the patchwork server for
+ this upstream
"""
- self.db.upstream_add(name, url)
+ self.db.upstream_add(name, url, patchwork_url)
if project:
+ if not pwork:
+ if not patchwork_url:
+ raise ValueError(
+ 'Patchwork URL is required when setting a project')
+ pwork = Patchwork(patchwork_url)
self.project_set(pwork, project, ups=name, quiet=True)
self.commit()
msg = f"Added upstream '{name}' ({url})"
+ if patchwork_url:
+ msg += f" patchwork '{patchwork_url}'"
if project:
msg += f" project '{project}'"
tout.notice(msg)
@@ -1167,14 +1178,20 @@ class Cseries(cser_helper.CseriesHelper):
def upstream_list(self):
"""List the upstream repos
- Shows a list of the repos, obtained from the database
+ Shows a list of the repos, obtained from the database, along with
+ any associated patchwork project
"""
udict = self.get_upstream_dict()
for name, items in udict.items():
- url, is_default = items
+ url, is_default, patchwork_url = items
default = 'default' if is_default else ''
- print(f'{name:15.15} {default:8} {url}')
+ proj = self.db.patchwork_get(name)
+ proj_name = proj[0] if proj else ''
+ line = f'{name:10.10} {default:8} {proj_name:20} {url}'
+ if patchwork_url:
+ line += f' pw:{patchwork_url}'
+ print(line)
def upstream_set_default(self, name):
"""Set the default upstream target
@@ -791,19 +791,21 @@ class Database: # pylint:disable=R0904
# upstream functions
- def upstream_add(self, name, url):
+ def upstream_add(self, name, url, patchwork_url=None):
"""Add a new upstream record
Args:
name (str): Name of the tree
url (str): URL for the tree
+ patchwork_url (str or None): URL of the patchwork server
Raises:
ValueError if the name already exists in the database
"""
try:
self.execute(
- 'INSERT INTO upstream (name, url) VALUES (?, ?)', (name, url))
+ 'INSERT INTO upstream (name, url, patchwork_url) '
+ 'VALUES (?, ?, ?)', (name, url, patchwork_url))
except sqlite3.IntegrityError as exc:
if 'UNIQUE constraint failed: upstream.name' in str(exc):
raise ValueError(f"Upstream '{name}' already exists") from exc
@@ -853,18 +855,38 @@ class Database: # pylint:disable=R0904
self.rollback()
raise ValueError(f"No such upstream '{name}'")
+ def upstream_get_patchwork_url(self, name):
+ """Get the patchwork URL for an upstream
+
+ Args:
+ name (str): Upstream name
+
+ Return:
+ str or None: Patchwork URL, or None if not set
+ """
+ res = self.execute(
+ 'SELECT patchwork_url FROM upstream WHERE name = ?', (name,))
+ rec = res.fetchone()
+ if rec:
+ return rec[0]
+ return None
+
def upstream_get_dict(self):
"""Get a list of upstream entries from the database
Return:
OrderedDict:
key (str): upstream name
- value (str): url
+ value: tuple:
+ str: url
+ bool: is_default
+ str or None: patchwork_url
"""
- res = self.execute('SELECT name, url, is_default FROM upstream')
+ res = self.execute(
+ 'SELECT name, url, is_default, patchwork_url FROM upstream')
udict = OrderedDict()
- for name, url, is_default in res.fetchall():
- udict[name] = url, is_default
+ for name, url, is_default, patchwork_url in res.fetchall():
+ udict[name] = url, is_default, patchwork_url
return udict
# patchwork functions
@@ -1730,14 +1730,14 @@ Tested-by: Mary Smith <msmith@wibble.com> # yak
cser.upstream_add('us', 'https://one')
ulist = cser.get_upstream_dict()
self.assertEqual(1, len(ulist))
- self.assertEqual(('https://one', None), ulist['us'])
+ self.assertEqual(('https://one', None, None), ulist['us'])
with terminal.capture():
cser.upstream_add('ci', 'git@two')
ulist = cser.get_upstream_dict()
self.assertEqual(2, len(ulist))
- self.assertEqual(('https://one', None), ulist['us'])
- self.assertEqual(('git@two', None), ulist['ci'])
+ self.assertEqual(('https://one', None, None), ulist['us'])
+ self.assertEqual(('git@two', None, None), ulist['ci'])
# Try to add a duplicate
with self.assertRaises(ValueError) as exc:
@@ -1748,8 +1748,39 @@ Tested-by: Mary Smith <msmith@wibble.com> # yak
cser.upstream_list()
lines = out.getvalue().splitlines()
self.assertEqual(2, len(lines))
- self.assertEqual('us https://one', lines[0])
- self.assertEqual('ci git@two', lines[1])
+ self.assertEqual(
+ 'us https://one',
+ lines[0])
+ self.assertEqual(
+ 'ci git@two',
+ lines[1])
+
+ def test_upstream_add_patchwork_url(self):
+ """Test adding an upstream with a patchwork URL"""
+ cser = self.get_cser()
+
+ with terminal.capture():
+ cser.upstream_add('us', 'https://one',
+ patchwork_url='https://pw.example.com')
+ ulist = cser.get_upstream_dict()
+ self.assertEqual(1, len(ulist))
+ self.assertEqual(
+ ('https://one', None, 'https://pw.example.com'), ulist['us'])
+
+ # Check that the patchwork URL shows in the list
+ with terminal.capture() as (out, _):
+ cser.upstream_list()
+ lines = out.getvalue().splitlines()
+ self.assertEqual(1, len(lines))
+ self.assertIn('pw:https://pw.example.com', lines[0])
+
+ # Check database lookup
+ pw_url = cser.db.upstream_get_patchwork_url('us')
+ self.assertEqual('https://pw.example.com', pw_url)
+
+ # Non-existent upstream returns None
+ pw_url = cser.db.upstream_get_patchwork_url('nonexistent')
+ self.assertIsNone(pw_url)
def test_upstream_add_cmdline(self):
"""Test adding an upsream with cmdline"""
@@ -1760,7 +1791,9 @@ Tested-by: Mary Smith <msmith@wibble.com> # yak
self.run_args('upstream', 'list')
lines = out.getvalue().splitlines()
self.assertEqual(1, len(lines))
- self.assertEqual('us https://one', lines[0])
+ self.assertEqual(
+ 'us https://one',
+ lines[0])
def test_upstream_default(self):
"""Operation of the default upstream"""
@@ -1791,8 +1824,12 @@ Tested-by: Mary Smith <msmith@wibble.com> # yak
cser.upstream_list()
lines = out.getvalue().splitlines()
self.assertEqual(2, len(lines))
- self.assertEqual('us https://one', lines[0])
- self.assertEqual('ci default git@two', lines[1])
+ self.assertEqual(
+ 'us https://one',
+ lines[0])
+ self.assertEqual(
+ 'ci default git@two',
+ lines[1])
cser.upstream_set_default(None)
self.assertIsNone(cser.upstream_get_default())