diff --git a/tools/patman/control.py b/tools/patman/control.py index f4a6ca145d..a3c50cd9c5 100644 --- a/tools/patman/control.py +++ b/tools/patman/control.py @@ -177,7 +177,7 @@ def send(args): args.smtp_server) def patchwork_status(branch, count, start, end, dest_branch, force, - show_comments): + show_comments, url): """Check the status of patches in patchwork This finds the series in patchwork using the Series-link tag, checks for new @@ -196,6 +196,7 @@ def patchwork_status(branch, count, start, end, dest_branch, force, force (bool): With dest_branch, force overwriting an existing branch show_comments (bool): True to display snippets from the comments provided by reviewers + url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org' Raises: ValueError: if the branch has no Series-link value @@ -228,4 +229,4 @@ def patchwork_status(branch, count, start, end, dest_branch, force, # are not present from patman import status status.check_patchwork_status(series, found[0], branch, dest_branch, force, - show_comments) + show_comments, url) diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py index 5933fcfd14..74a144dc2d 100644 --- a/tools/patman/func_test.py +++ b/tools/patman/func_test.py @@ -625,11 +625,15 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c os.chdir(orig_dir) @staticmethod - def _fake_patchwork(subpath): + def _fake_patchwork(url, subpath): """Fake Patchwork server for the function below This handles accessing a series, providing a list consisting of a single patch + + Args: + url (str): URL of patchwork server + subpath (str): URL subpath to use """ re_series = re.match(r'series/(\d*)/$', subpath) if re_series: @@ -645,7 +649,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c series = Series() with capture_sys_output() as (_, err): - status.collect_patches(series, 1234, self._fake_patchwork) + status.collect_patches(series, 1234, None, self._fake_patchwork) self.assertIn('Warning: Patchwork reports 1 patches, series has 0', err.getvalue()) @@ -655,7 +659,8 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c series = Series() series.commits = [Commit('abcd')] - patches = status.collect_patches(series, 1234, self._fake_patchwork) + patches = status.collect_patches(series, 1234, None, + self._fake_patchwork) self.assertEqual(1, len(patches)) patch = patches[0] self.assertEqual('1', patch.id) @@ -800,11 +805,15 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c "Cannot find commit for patch 3 ('Subject 2')"], warnings) - def _fake_patchwork2(self, subpath): + def _fake_patchwork2(self, url, subpath): """Fake Patchwork server for the function below This handles accessing series, patches and comments, providing the data in self.patches to the caller + + Args: + url (str): URL of patchwork server + subpath (str): URL subpath to use """ re_series = re.match(r'series/(\d*)/$', subpath) re_patch = re.match(r'patches/(\d*)/$', subpath) @@ -861,12 +870,12 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c # Check that the tags are picked up on the first patch status.find_new_responses(new_rtag_list, review_list, 0, commit1, - patch1, self._fake_patchwork2) + patch1, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[0], {'Reviewed-by': {self.joe}}) # Now the second patch status.find_new_responses(new_rtag_list, review_list, 1, commit2, - patch2, self._fake_patchwork2) + patch2, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[1], { 'Reviewed-by': {self.mary, self.fred}, 'Tested-by': {self.leb}}) @@ -876,7 +885,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c new_rtag_list = [None] * count commit1.rtags = {'Reviewed-by': {self.joe}} status.find_new_responses(new_rtag_list, review_list, 0, commit1, - patch1, self._fake_patchwork2) + patch1, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[0], {}) # For the second commit, add Ed and Fred, so only Mary should be left @@ -884,7 +893,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c 'Tested-by': {self.leb}, 'Reviewed-by': {self.fred}} status.find_new_responses(new_rtag_list, review_list, 1, commit2, - patch2, self._fake_patchwork2) + patch2, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[1], {'Reviewed-by': {self.mary}}) # Check that the output patches expectations: @@ -900,7 +909,7 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c series.commits = [commit1, commit2] terminal.SetPrintTestMode() status.check_patchwork_status(series, '1234', None, None, False, False, - self._fake_patchwork2) + None, self._fake_patchwork2) lines = iter(terminal.GetPrintTestLines()) col = terminal.Color() self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.BLUE), @@ -935,11 +944,15 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c '1 new response available in patchwork (use -d to write them to a new branch)', None), next(lines)) - def _fake_patchwork3(self, subpath): + def _fake_patchwork3(self, url, subpath): """Fake Patchwork server for the function below This handles accessing series, patches and comments, providing the data in self.patches to the caller + + Args: + url (str): URL of patchwork server + subpath (str): URL subpath to use """ re_series = re.match(r'series/(\d*)/$', subpath) re_patch = re.match(r'patches/(\d*)/$', subpath) @@ -1011,7 +1024,8 @@ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c terminal.SetPrintTestMode() status.check_patchwork_status(series, '1234', branch, dest_branch, - False, False, self._fake_patchwork3, repo) + False, False, None, self._fake_patchwork3, + repo) lines = terminal.GetPrintTestLines() self.assertEqual(12, len(lines)) self.assertEqual( @@ -1214,7 +1228,7 @@ Reviewed-by: %s series.commits = [commit1, commit2] terminal.SetPrintTestMode() status.check_patchwork_status(series, '1234', None, None, False, True, - self._fake_patchwork2) + None, self._fake_patchwork2) lines = iter(terminal.GetPrintTestLines()) col = terminal.Color() self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.BLUE), diff --git a/tools/patman/main.py b/tools/patman/main.py index e0e03a40a7..5f319eaa9b 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -179,7 +179,8 @@ elif args.cmd == 'status': try: control.patchwork_status(args.branch, args.count, args.start, args.end, args.dest_branch, args.force, - args.show_comments) + args.show_comments, + 'https://patchwork.ozlabs.org') except Exception as e: terminal.Print('patman: %s: %s' % (type(e).__name__, e), colour=terminal.Color.RED) diff --git a/tools/patman/status.py b/tools/patman/status.py index a369d655c5..f3fbc661b2 100644 --- a/tools/patman/status.py +++ b/tools/patman/status.py @@ -198,10 +198,11 @@ def compare_with_series(series, patches): return patch_for_commit, commit_for_patch, warnings -def call_rest_api(subpath): +def call_rest_api(url, subpath): """Call the patchwork API and return the result as JSON Args: + url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org' subpath (str): URL subpath to use Returns: @@ -210,13 +211,13 @@ def call_rest_api(subpath): Raises: ValueError: the URL could not be read """ - url = 'https://patchwork.ozlabs.org/api/1.2/%s' % subpath - response = requests.get(url) + full_url = '%s/api/1.2/%s' % (url, subpath) + response = requests.get(full_url) if response.status_code != 200: - raise ValueError("Could not read URL '%s'" % url) + raise ValueError("Could not read URL '%s'" % full_url) return response.json() -def collect_patches(series, series_id, rest_api=call_rest_api): +def collect_patches(series, series_id, url, rest_api=call_rest_api): """Collect patch information about a series from patchwork Uses the Patchwork REST API to collect information provided by patchwork @@ -226,6 +227,7 @@ def collect_patches(series, series_id, rest_api=call_rest_api): series (Series): Series object corresponding to the local branch containing the series series_id (str): Patch series ID number + url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org' rest_api (function): API function to call to access Patchwork, for testing @@ -236,7 +238,7 @@ def collect_patches(series, series_id, rest_api=call_rest_api): ValueError: if the URL could not be read or the web page does not follow the expected structure """ - data = rest_api('series/%s/' % series_id) + data = rest_api(url, 'series/%s/' % series_id) # Get all the rows, which are patches patch_dict = data['patches'] @@ -261,7 +263,7 @@ def collect_patches(series, series_id, rest_api=call_rest_api): patches = sorted(patches, key=lambda x: x.seq) return patches -def find_new_responses(new_rtag_list, review_list, seq, cmt, patch, +def find_new_responses(new_rtag_list, review_list, seq, cmt, patch, url, rest_api=call_rest_api): """Find new rtags collected by patchwork that we don't know about @@ -279,6 +281,7 @@ def find_new_responses(new_rtag_list, review_list, seq, cmt, patch, seq (int): Position in new_rtag_list to update cmt (Commit): Commit object for this commit patch (Patch): Corresponding Patch object for this patch + url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org' rest_api (function): API function to call to access Patchwork, for testing """ @@ -286,14 +289,14 @@ def find_new_responses(new_rtag_list, review_list, seq, cmt, patch, return # Get the content for the patch email itself as well as all comments - data = rest_api('patches/%s/' % patch.id) + data = rest_api(url, 'patches/%s/' % patch.id) pstrm = PatchStream.process_text(data['content'], True) rtags = collections.defaultdict(set) for response, people in pstrm.commit.rtags.items(): rtags[response].update(people) - data = rest_api('patches/%s/comments/' % patch.id) + data = rest_api(url, 'patches/%s/comments/' % patch.id) reviews = [] for comment in data: @@ -407,7 +410,7 @@ def create_branch(series, new_rtag_list, branch, dest_branch, overwrite, return num_added def check_patchwork_status(series, series_id, branch, dest_branch, force, - show_comments, rest_api=call_rest_api, + show_comments, url, rest_api=call_rest_api, test_repo=None): """Check the status of a series on Patchwork @@ -421,11 +424,12 @@ def check_patchwork_status(series, series_id, branch, dest_branch, force, dest_branch (str): Name of new branch to create, or None force (bool): True to force overwriting dest_branch if it exists show_comments (bool): True to show the comments on each patch + url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org' rest_api (function): API function to call to access Patchwork, for testing test_repo (pygit2.Repository): Repo to use (use None unless testing) """ - patches = collect_patches(series, series_id, rest_api) + patches = collect_patches(series, series_id, url, rest_api) col = terminal.Color() count = len(series.commits) new_rtag_list = [None] * count @@ -440,7 +444,8 @@ def check_patchwork_status(series, series_id, branch, dest_branch, force, with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor: futures = executor.map( find_new_responses, repeat(new_rtag_list), repeat(review_list), - range(count), series.commits, patch_list, repeat(rest_api)) + range(count), series.commits, patch_list, repeat(url), + repeat(rest_api)) for fresponse in futures: if fresponse: raise fresponse.exception()