OLD | NEW |
1 # coding=utf8 | 1 # coding=utf8 |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 """Commit queue manager class. | 5 """Commit queue manager class. |
6 | 6 |
7 Security implications: | 7 Security implications: |
8 | 8 |
9 The following hypothesis are made: | 9 The following hypothesis are made: |
10 - Commit queue: | 10 - Commit queue: |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 import find_depot_tools # pylint: disable=W0611 | 23 import find_depot_tools # pylint: disable=W0611 |
24 import breakpad | 24 import breakpad |
25 import patch | 25 import patch |
26 | 26 |
27 import checkout | 27 import checkout |
28 import model | 28 import model |
29 from verification import base | 29 from verification import base |
30 | 30 |
31 | 31 |
32 def TODO(string): | |
33 logging.warning(string) | |
34 | |
35 | |
36 def send_stack(e): | 32 def send_stack(e): |
37 breakpad.SendStack(e, | 33 breakpad.SendStack(e, |
38 ''.join(traceback.format_tb(sys.exc_info()[2])), | 34 ''.join(traceback.format_tb(sys.exc_info()[2])), |
39 maxlen=2000) | 35 maxlen=2000) |
40 | 36 |
41 | 37 |
42 class PendingCommit(base.Verified): | 38 class PendingCommit(base.Verified): |
43 """Represents a pending commit that is being processed.""" | 39 """Represents a pending commit that is being processed.""" |
44 persistent = base.Verified.persistent + [ | 40 persistent = base.Verified.persistent + [ |
45 # Important since they tell if we need to revalidate and send try jobs | 41 # Important since they tell if we need to revalidate and send try jobs |
46 # again or not if any of these value changes. | 42 # again or not if any of these value changes. |
47 'issue', 'patchset', 'rietveld_server', 'description', | 43 'issue', 'patchset', 'rietveld_server', 'description', |
48 'files', | 44 'files', |
49 # Only a cache, these values can be regenerated. | 45 # Only a cache, these values can be regenerated. |
50 'owner', 'reviewers', 'base_url', 'messages', | 46 'owner', 'reviewers', 'base_url', 'messages', 'relpath', |
51 # Only used after a patch was committed. Keeping here for completeness. | 47 # Only used after a patch was committed. Keeping here for completeness. |
52 'revision', | 48 'revision', |
53 ] | 49 ] |
54 | 50 |
55 def __init__(self, issue, owner, reviewers, patchset, base_url, description, | 51 def __init__(self, issue, owner, reviewers, patchset, base_url, description, |
56 messages, rietveld_server): | 52 messages, rietveld_server): |
57 super(PendingCommit, self).__init__() | 53 super(PendingCommit, self).__init__() |
58 self.issue = issue | 54 self.issue = issue |
59 self.owner = owner | 55 self.owner = owner |
60 self.reviewers = reviewers | 56 self.reviewers = reviewers |
61 self.patchset = patchset | 57 self.patchset = patchset |
62 self.base_url = base_url | 58 self.base_url = base_url |
63 self.rietveld_server = rietveld_server | 59 self.rietveld_server = rietveld_server |
64 self.description = description | 60 self.description = description |
65 self.messages = messages | 61 self.messages = messages |
66 self.revision = None | 62 self.revision = None |
| 63 self.relpath = '' |
67 self.files = [] | 64 self.files = [] |
68 | 65 |
69 def patch_url(self): | 66 def patch_url(self): |
70 return ('%s/download/issue%d_%d.diff' % | 67 return ('%s/download/issue%d_%d.diff' % |
71 (self.rietveld_server, self.issue, self.patchset)) | 68 (self.rietveld_server, self.issue, self.patchset)) |
72 | 69 |
73 def pending_name(self): | 70 def pending_name(self): |
74 """The name that should be used for try jobs. | 71 """The name that should be used for try jobs. |
75 | 72 |
76 It makes it possible to regenerate the try_jobs array if ever needed.""" | 73 It makes it possible to regenerate the try_jobs array if ever needed.""" |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 except ValueError: | 272 except ValueError: |
276 pass | 273 pass |
277 | 274 |
278 def _apply_patch(self, pending, revision): | 275 def _apply_patch(self, pending, revision): |
279 """Applies the pending patch to the checkout and throws if it fails. | 276 """Applies the pending patch to the checkout and throws if it fails. |
280 | 277 |
281 This function assumes self.checkout.prepare() was called right before. | 278 This function assumes self.checkout.prepare() was called right before. |
282 """ | 279 """ |
283 try: | 280 try: |
284 patches = self.rietveld.get_patch(pending.issue, pending.patchset) | 281 patches = self.rietveld.get_patch(pending.issue, pending.patchset) |
| 282 if not patches: |
| 283 raise base.DiscardPending( |
| 284 pending, 'No diff was found for this patchset.') |
| 285 if pending.relpath: |
| 286 patches.set_relpath(pending.relpath) |
285 pending.files = [p.filename for p in patches] | 287 pending.files = [p.filename for p in patches] |
286 if not pending.files: | 288 if not pending.files: |
287 raise base.DiscardPending(pending, 'No diff found.') | 289 raise base.DiscardPending( |
| 290 pending, 'No file was found in this patchset.') |
288 self.checkout.apply_patch(patches) | 291 self.checkout.apply_patch(patches) |
289 except checkout.PatchApplicationFailed, e: | 292 except checkout.PatchApplicationFailed, e: |
290 out = 'Can\'t apply patch for file %s.' % e.filename | 293 out = 'Can\'t apply patch for file %s.' % e.filename |
291 if e.status: | 294 if e.status: |
292 out += '\n%s' % e.status | 295 out += '\n%s' % e.status |
293 raise base.DiscardPending(pending, out) | 296 raise base.DiscardPending(pending, out) |
294 except patch.UnsupportedPatchFormat, e: | 297 except patch.UnsupportedPatchFormat, e: |
295 raise base.DiscardPending(pending, str(e)) | 298 raise base.DiscardPending(pending, str(e)) |
296 except subprocess.CalledProcessError, e: | 299 except subprocess.CalledProcessError, e: |
297 stdout = getattr(e, 'stdout', '') | 300 stdout = getattr(e, 'stdout', '') |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 raise base.DiscardPending(pending, out) | 334 raise base.DiscardPending(pending, out) |
332 | 335 |
333 def load(self, filename): | 336 def load(self, filename): |
334 """Loads the commit queue state from a JSON file.""" | 337 """Loads the commit queue state from a JSON file.""" |
335 self.queue = model.load_from_json_file(filename) | 338 self.queue = model.load_from_json_file(filename) |
336 self.queue.pending_commits = self.queue.pending_commits or [] | 339 self.queue.pending_commits = self.queue.pending_commits or [] |
337 | 340 |
338 def save(self, filename): | 341 def save(self, filename): |
339 """Save the commit queue state in a simple JSON file.""" | 342 """Save the commit queue state in a simple JSON file.""" |
340 model.save_to_json_file(filename, self.queue) | 343 model.save_to_json_file(filename, self.queue) |
OLD | NEW |