blob: 7bf0e7ff61a621fc1b699c9f14f987f66f64bbd5 [file] [log] [blame]
Simon Glass24725af2020-07-05 21:41:49 -06001# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright 2020 Google LLC
4#
5"""Handles the main control logic of patman
6
7This module provides various functions called by the main program to implement
8the features of patman.
9"""
10
Simon Glass3c0196f2025-04-29 07:21:58 -060011import re
Simon Glass3c0196f2025-04-29 07:21:58 -060012import traceback
Simon Glass24725af2020-07-05 21:41:49 -060013
Simon Glass3c0196f2025-04-29 07:21:58 -060014try:
15 from importlib import resources
16except ImportError:
17 # for Python 3.6
18 import importlib_resources as resources
19
Simon Glassba1b3b92025-02-09 14:26:00 -070020from u_boot_pylib import gitutil
Simon Glass131444f2023-02-23 18:18:04 -070021from u_boot_pylib import terminal
Simon Glass3c0196f2025-04-29 07:21:58 -060022from u_boot_pylib import tools
Simon Glass3c0196f2025-04-29 07:21:58 -060023from patman import patchstream
Simon Glass25b91c12025-04-29 07:22:19 -060024from patman import patchwork
Simon Glassc0257982025-04-29 07:22:11 -060025from patman import send
Simon Glassaaaff532025-04-07 22:51:43 +120026from patman import settings
Simon Glass24725af2020-07-05 21:41:49 -060027
Maxim Cournoyer12f99fd2023-10-12 23:06:24 -040028
Simon Glass24725af2020-07-05 21:41:49 -060029def setup():
30 """Do required setup before doing anything"""
Simon Glass761648b2022-01-29 14:14:11 -070031 gitutil.setup()
Simon Glassaaaff532025-04-07 22:51:43 +120032 alias_fname = gitutil.get_alias_file()
33 if alias_fname:
34 settings.ReadGitAliases(alias_fname)
Simon Glass24725af2020-07-05 21:41:49 -060035
Maxim Cournoyer12f99fd2023-10-12 23:06:24 -040036
Simon Glassc0257982025-04-29 07:22:11 -060037def do_send(args):
Simon Glass24725af2020-07-05 21:41:49 -060038 """Create, check and send patches by email
39
40 Args:
Simon Glasseb101ac2020-07-05 21:41:53 -060041 args (argparse.Namespace): Arguments to patman
Simon Glass24725af2020-07-05 21:41:49 -060042 """
43 setup()
Simon Glassc0257982025-04-29 07:22:11 -060044 send.send(args)
Simon Glass2eb4da72020-07-05 21:41:51 -060045
Simon Glass3db916d2020-10-29 21:46:35 -060046
Simon Glass2112d072020-10-29 21:46:38 -060047def patchwork_status(branch, count, start, end, dest_branch, force,
Simon Glass802eeea2025-04-29 07:22:25 -060048 show_comments, url, single_thread=False):
Simon Glass3db916d2020-10-29 21:46:35 -060049 """Check the status of patches in patchwork
50
51 This finds the series in patchwork using the Series-link tag, checks for new
Simon Glass2112d072020-10-29 21:46:38 -060052 comments and review tags, displays then and creates a new branch with the
53 review tags.
Simon Glass3db916d2020-10-29 21:46:35 -060054
55 Args:
56 branch (str): Branch to create patches from (None = current)
57 count (int): Number of patches to produce, or -1 to produce patches for
58 the current branch back to the upstream commit
59 start (int): Start partch to use (0=first / top of branch)
60 end (int): End patch to use (0=last one in series, 1=one before that,
61 etc.)
Simon Glassd0a0a582020-10-29 21:46:36 -060062 dest_branch (str): Name of new branch to create with the updated tags
63 (None to not create a branch)
64 force (bool): With dest_branch, force overwriting an existing branch
Simon Glass2112d072020-10-29 21:46:38 -060065 show_comments (bool): True to display snippets from the comments
66 provided by reviewers
Simon Glass4acc93c2020-11-03 13:54:16 -070067 url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org'.
68 This is ignored if the series provides a Series-patchwork-url tag.
Simon Glass3db916d2020-10-29 21:46:35 -060069
70 Raises:
71 ValueError: if the branch has no Series-link value
72 """
73 if count == -1:
74 # Work out how many patches to send if we can
Simon Glass761648b2022-01-29 14:14:11 -070075 count = (gitutil.count_commits_to_branch(branch) - start)
Simon Glass3db916d2020-10-29 21:46:35 -060076
77 series = patchstream.get_metadata(branch, start, count - end)
78 warnings = 0
79 for cmt in series.commits:
80 if cmt.warn:
81 print('%d warnings for %s:' % (len(cmt.warn), cmt.hash))
82 for warn in cmt.warn:
83 print('\t', warn)
84 warnings += 1
85 print
86 if warnings:
87 raise ValueError('Please fix warnings before running status')
88 links = series.get('links')
89 if not links:
90 raise ValueError("Branch has no Series-links value")
91
92 # Find the link without a version number (we don't support versions yet)
93 found = [link for link in links.split() if not ':' in link]
94 if not found:
95 raise ValueError('Series-links has no current version (without :)')
96
Simon Glass4acc93c2020-11-03 13:54:16 -070097 # Allow the series to override the URL
98 if 'patchwork_url' in series:
99 url = series.patchwork_url
Simon Glass802eeea2025-04-29 07:22:25 -0600100 pwork = patchwork.Patchwork(url, single_thread=single_thread)
Simon Glass4acc93c2020-11-03 13:54:16 -0700101
Simon Glass3db916d2020-10-29 21:46:35 -0600102 # Import this here to avoid failing on other commands if the dependencies
103 # are not present
104 from patman import status
Simon Glassc100b262025-04-29 07:22:16 -0600105 status.check_and_show_status(series, found[0], branch, dest_branch, force,
Simon Glass25b91c12025-04-29 07:22:19 -0600106 show_comments, pwork)
Simon Glass3c0196f2025-04-29 07:21:58 -0600107
108
109def do_patman(args):
Simon Glassb8a14f92025-05-08 06:30:14 +0200110 """Process a patman command
111
112 Args:
113 args (Namespace): Arguments to process
114 """
115 if args.full_help:
116 with resources.path('patman', 'README.rst') as readme:
117 tools.print_full_help(str(readme))
118 return 0
Simon Glass3c0196f2025-04-29 07:21:58 -0600119 if args.cmd == 'send':
120 # Called from git with a patch filename as argument
121 # Printout a list of additional CC recipients for this patch
122 if args.cc_cmd:
123 re_line = re.compile(r'(\S*) (.*)')
124 with open(args.cc_cmd, 'r', encoding='utf-8') as inf:
125 for line in inf.readlines():
126 match = re_line.match(line)
127 if match and match.group(1) == args.patchfiles[0]:
128 for cca in match.group(2).split('\0'):
129 cca = cca.strip()
130 if cca:
131 print(cca)
Simon Glass3c0196f2025-04-29 07:21:58 -0600132 else:
133 # If we are not processing tags, no need to warning about bad ones
134 if not args.process_tags:
135 args.ignore_bad_tags = True
Simon Glassc0257982025-04-29 07:22:11 -0600136 do_send(args)
Simon Glassb8a14f92025-05-08 06:30:14 +0200137 return 0
Simon Glass3c0196f2025-04-29 07:21:58 -0600138
Simon Glass78ee8f82025-04-29 07:22:09 -0600139 ret_code = 0
140 try:
141 # Check status of patches in patchwork
142 if args.cmd == 'status':
Simon Glass3c0196f2025-04-29 07:21:58 -0600143 patchwork_status(args.branch, args.count, args.start, args.end,
144 args.dest_branch, args.force, args.show_comments,
145 args.patchwork_url)
Simon Glass78ee8f82025-04-29 07:22:09 -0600146 except Exception as exc:
147 terminal.tprint(f'patman: {type(exc).__name__}: {exc}',
148 colour=terminal.Color.RED)
149 if args.debug:
150 print()
151 traceback.print_exc()
152 ret_code = 1
153 return ret_code