OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Utility functions to communicate with Rietveld.""" | 5 """Utility functions to communicate with Rietveld.""" |
6 | 6 |
7 import json | 7 import json |
8 import logging | 8 import logging |
9 import urllib2 | 9 import urllib2 |
10 | 10 |
11 from webkitpy.common.net.buildbot import Build | 11 from webkitpy.common.net.buildbot import Build, filter_latest_builds |
12 | 12 |
13 _log = logging.getLogger(__name__) | 13 _log = logging.getLogger(__name__) |
14 | 14 |
15 BASE_CODEREVIEW_URL = 'https://codereview.chromium.org/api' | 15 BASE_CODEREVIEW_URL = 'https://codereview.chromium.org/api' |
16 | 16 |
17 | 17 |
18 class Rietveld(object): | 18 class Rietveld(object): |
19 | 19 |
20 def __init__(self, web): | 20 def __init__(self, web): |
21 self.web = web | 21 self.web = web |
(...skipping 26 matching lines...) Expand all Loading... |
48 # Normally, a value of -1 or 6 in the "result" field indicates the j
ob is | 48 # Normally, a value of -1 or 6 in the "result" field indicates the j
ob is |
49 # started or pending, and the "buildnumber" field is null. | 49 # started or pending, and the "buildnumber" field is null. |
50 if build.build_number and result_dict['result'] in (-1, 6): | 50 if build.build_number and result_dict['result'] in (-1, 6): |
51 _log.warning('Build %s has result %d, but unexpectedly has a bui
ld number.', build, result_dict['result']) | 51 _log.warning('Build %s has result %d, but unexpectedly has a bui
ld number.', build, result_dict['result']) |
52 build.build_number = None | 52 build.build_number = None |
53 builds.append(build) | 53 builds.append(build) |
54 | 54 |
55 if builder_names is not None: | 55 if builder_names is not None: |
56 builds = [b for b in builds if b.builder_name in builder_names] | 56 builds = [b for b in builds if b.builder_name in builder_names] |
57 | 57 |
58 return self._filter_latest_builds(builds) | 58 return filter_latest_builds(builds) |
59 | |
60 def _filter_latest_builds(self, builds): | |
61 """Filters out a collection of Build objects to include only the latest
for each builder. | |
62 | |
63 Args: | |
64 jobs: A list of Build objects. | |
65 | |
66 Returns: | |
67 A list of Build objects; only one Build object per builder name. If
there are only | |
68 Builds with no build number, then one is kept; if there are Builds w
ith build numbers, | |
69 then the one with the highest build number is kept. | |
70 """ | |
71 builder_to_latest_build = {} | |
72 for build in builds: | |
73 if build.builder_name not in builder_to_latest_build: | |
74 builder_to_latest_build[build.builder_name] = build | |
75 elif build.build_number > builder_to_latest_build[build.builder_name
].build_number: | |
76 builder_to_latest_build[build.builder_name] = build | |
77 return sorted(builder_to_latest_build.values()) | |
78 | 59 |
79 def changed_files(self, issue_number): | 60 def changed_files(self, issue_number): |
80 """Lists the files included in a CL that are changed but not deleted. | 61 """Lists the files included in a CL that are changed but not deleted. |
81 | 62 |
82 File paths are sorted and relative to the repository root. | 63 File paths are sorted and relative to the repository root. |
83 """ | 64 """ |
84 try: | 65 try: |
85 url = self._latest_patchset_url(issue_number) | 66 url = self._latest_patchset_url(issue_number) |
86 issue_data = self._get_json(url) | 67 issue_data = self._get_json(url) |
87 return sorted(path for path, file_change in issue_data['files'].iter
items() if file_change['status'] != 'D') | 68 return sorted(path for path, file_change in issue_data['files'].iter
items() if file_change['status'] != 'D') |
(...skipping 22 matching lines...) Expand all Loading... |
110 return json.loads(contents) | 91 return json.loads(contents) |
111 except ValueError: | 92 except ValueError: |
112 _log.error('Invalid JSON: %s', contents) | 93 _log.error('Invalid JSON: %s', contents) |
113 raise | 94 raise |
114 | 95 |
115 def _issue_url(self, issue_number): | 96 def _issue_url(self, issue_number): |
116 return '%s/%s' % (BASE_CODEREVIEW_URL, issue_number) | 97 return '%s/%s' % (BASE_CODEREVIEW_URL, issue_number) |
117 | 98 |
118 def _patchset_url(self, issue_number, patchset_number): | 99 def _patchset_url(self, issue_number, patchset_number): |
119 return '%s/%s' % (self._issue_url(issue_number), patchset_number) | 100 return '%s/%s' % (self._issue_url(issue_number), patchset_number) |
OLD | NEW |