fromupstream: Support picking patches with message-id
We're moving towards using message-ids for tracking patches to the linux
kernel. Instead of requiring users to find the patchwork ID from the
website/UI, support deriving that ID based on the message-id passed in
as an argument. The same semantics as patchwork picks apply here, so
reuse a bunch of that code and hardcode a few different locations to
look for patchwork instances that can supply the patch in mbox format.
BUG=chromium:1008546
TEST=run with valid message id and invalid message id for a patch on
lkml
Change-Id: Ie349e890221b1a421938faf837d4b0b9e6e39937
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/1828169
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Commit-Queue: Douglas Anderson <dianders@chromium.org>
diff --git a/contrib/fromupstream.py b/contrib/fromupstream.py
index 11ebf95..c9d5510 100755
--- a/contrib/fromupstream.py
+++ b/contrib/fromupstream.py
@@ -20,6 +20,7 @@
import sys
import textwrap
import urllib
+import xmlrpclib
errprint = functools.partial(print, file=sys.stderr)
@@ -29,6 +30,14 @@
'https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git',
)
+PATCHWORK_URLS = (
+ 'https://lore.kernel.org/patchwork',
+ 'https://patchwork.kernel.org',
+ 'https://patchwork.ozlabs.org',
+ 'https://patchwork.freedesktop.org',
+ 'https://patchwork.linux-mips.org',
+)
+
COMMIT_MESSAGE_WIDTH = 75
_PWCLIENTRC = os.path.expanduser('~/.pwclientrc')
@@ -114,19 +123,10 @@
indent = ' ' * (len(prefix) + 1)
return textwrap.fill(line, COMMIT_MESSAGE_WIDTH, subsequent_indent=indent)
-def _match_patchwork(match, args):
- """Match location: pw://### or pw://PROJECT/###."""
- pw_project = match.group(2)
- patch_id = int(match.group(3))
-
- if args['debug']:
- print('_match_patchwork: pw_project=%s, patch_id=%d' %
- (pw_project, patch_id))
-
+def _pick_patchwork(url, patch_id, args):
if args['tag'] is None:
args['tag'] = 'FROMLIST: '
- url = _get_pw_url(pw_project)
opener = urllib.urlopen('%s/patch/%d/mbox' % (url, patch_id))
if opener.getcode() != 200:
errprint('Error: could not download patch - error code %d'
@@ -157,6 +157,40 @@
git_am.communicate(patch_contents)
return git_am.returncode
+def _match_patchwork(match, args):
+ """Match location: pw://### or pw://PROJECT/###."""
+ pw_project = match.group(2)
+ patch_id = int(match.group(3))
+
+ if args['debug']:
+ print('_match_patchwork: pw_project=%s, patch_id=%d' %
+ (pw_project, patch_id))
+
+ url = _get_pw_url(pw_project)
+ return _pick_patchwork(url, patch_id, args)
+
+def _match_msgid(match, args):
+ """Match location: msgid://MSGID."""
+ msgid = match.group(1)
+
+ if args['debug']:
+ print('_match_msgid: message_id=%s' % (msgid))
+
+ # Patchwork requires the brackets so force it
+ msgid = '<' + msgid + '>'
+ url = None
+ for url in PATCHWORK_URLS:
+ rpc = xmlrpclib.ServerProxy(url + '/xmlrpc/')
+ res = rpc.patch_list({'msgid': msgid})
+ if res:
+ patch_id = res[0]['id']
+ break
+ else:
+ errprint('Error: could not find patch based on message id')
+ sys.exit(1)
+
+ return _pick_patchwork(url, patch_id, args)
+
def _match_linux(match, args):
"""Match location: linux://HASH."""
commit = match.group(1)
@@ -300,6 +334,7 @@
'where PROJECT is defined in ~/.pwclientrc; if no '
'PROJECT is specified, the default is retrieved from '
'~/.pwclientrc), '
+ 'Message-ID (msgid://MSGID), '
'linux commit like linux://HASH, or '
'git reference like git://remote/branch/HASH or '
'git://repoURL#branch/HASH or '
@@ -345,6 +380,7 @@
re_matches = (
(re.compile(r'^pw://(([^/]+)/)?(\d+)'), _match_patchwork),
+ (re.compile(r'^msgid://<?([^>]*)>?'), _match_msgid),
(re.compile(r'^linux://([0-9a-f]+)'), _match_linux),
(re.compile(r'^(from)?git://([^/\#]+)/([^#]+)/([0-9a-f]+)$'),
_match_fromgit),