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 26 matching lines...) Expand all Loading... | |
37 breakpad.SendStack(e, | 37 breakpad.SendStack(e, |
38 ''.join(traceback.format_tb(sys.exc_info()[2])), | 38 ''.join(traceback.format_tb(sys.exc_info()[2])), |
39 maxlen=2000) | 39 maxlen=2000) |
40 | 40 |
41 | 41 |
42 class PendingCommit(base.Verified): | 42 class PendingCommit(base.Verified): |
43 """Represents a pending commit that is being processed.""" | 43 """Represents a pending commit that is being processed.""" |
44 persistent = base.Verified.persistent + [ | 44 persistent = base.Verified.persistent + [ |
45 # Important since they tell if we need to revalidate and send try jobs | 45 # Important since they tell if we need to revalidate and send try jobs |
46 # again or not if any of these value changes. | 46 # again or not if any of these value changes. |
47 'issue', 'patchset', 'rietveld_server', 'processed', 'description', | 47 'issue', 'patchset', 'rietveld_server', 'description', |
48 'files', | 48 'files', |
49 # Only a cache, these values can be regenerated. | 49 # Only a cache, these values can be regenerated. |
50 'owner', 'reviewers', 'base_url', | 50 'owner', 'reviewers', 'base_url', |
51 # Only used after a patch was committed. Keeping here for completeness. | 51 # Only used after a patch was committed. Keeping here for completeness. |
52 'revision', | 52 'revision', |
53 ] | 53 ] |
54 | 54 |
55 def __init__(self, issue, owner, reviewers, patchset, base_url, description, | 55 def __init__(self, issue, owner, reviewers, patchset, base_url, description, |
56 messages, rietveld_server): | 56 messages, rietveld_server): |
57 super(PendingCommit, self).__init__() | 57 super(PendingCommit, self).__init__() |
58 self.issue = issue | 58 self.issue = issue |
59 self.owner = owner | 59 self.owner = owner |
60 self.reviewers = reviewers | 60 self.reviewers = reviewers |
61 self.patchset = patchset | 61 self.patchset = patchset |
62 self.base_url = base_url | 62 self.base_url = base_url |
63 self.rietveld_server = rietveld_server | 63 self.rietveld_server = rietveld_server |
64 self.description = description | 64 self.description = description |
65 self.messages = messages | 65 self.messages = messages |
66 self.revision = None | 66 self.revision = None |
67 self.processed = False | |
68 self.files = [] | 67 self.files = [] |
69 | 68 |
70 def patch_url(self): | 69 def patch_url(self): |
71 return ('%s/download/issue%d_%d.diff' % | 70 return ('%s/download/issue%d_%d.diff' % |
72 (self.rietveld_server, self.issue, self.patchset)) | 71 (self.rietveld_server, self.issue, self.patchset)) |
73 | 72 |
74 def pending_name(self): | 73 def pending_name(self): |
75 """The name that should be used for try jobs. | 74 """The name that should be used for try jobs. |
76 | 75 |
77 It makes it possible to regenerate the try_jobs array if ever needed.""" | 76 It makes it possible to regenerate the try_jobs array if ever needed.""" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 patchset with commit+ flag set. | 132 patchset with commit+ flag set. |
134 """ | 133 """ |
135 return json.loads(self.rietveld.get( | 134 return json.loads(self.rietveld.get( |
136 '/search?format=json&commit=True&closed=False&keys_only=True') | 135 '/search?format=json&commit=True&closed=False&keys_only=True') |
137 )['results'] | 136 )['results'] |
138 | 137 |
139 def process_new_pending_commit(self): | 138 def process_new_pending_commit(self): |
140 """Starts verification on newly found pending commits.""" | 139 """Starts verification on newly found pending commits.""" |
141 for pending in self.queue.pending_commits[:]: | 140 for pending in self.queue.pending_commits[:]: |
142 try: | 141 try: |
143 if pending.verifications or pending.processed: | 142 if len(pending.verifications) == len(self.verifiers) or pending.done(): |
Dirk Pranke
2011/01/04 22:10:42
Should this check maybe be part of pending.done()
M-A Ruel
2011/01/11 21:07:40
That's a good question.
Since pending doesn't kno
| |
144 continue | 143 continue |
145 logging.info('Processing issue %s' % pending.issue) | 144 logging.info('Processing issue %s' % pending.issue) |
146 pending.processed = True | |
147 | 145 |
148 if not self._validity_checks(pending): | 146 if not self._validity_checks(pending): |
149 # Silently ignore. | 147 # Silently ignore. |
150 continue | 148 continue |
151 | 149 |
152 # The patch is fine to try. | 150 # The patch is fine to try. |
153 revision = self.checkout.prepare() | 151 revision = self.checkout.prepare() |
154 self._apply_patch(pending, revision) | 152 self._apply_patch(pending, revision) |
155 previous_cwd = os.getcwd() | 153 previous_cwd = os.getcwd() |
156 try: | 154 try: |
157 os.chdir(self.checkout.project_path) | 155 os.chdir(self.checkout.project_path) |
158 for verifier in self.verifiers: | 156 for verifier in self.verifiers: |
159 verifier.verify(pending, revision) | 157 verifier.verify(pending, revision) |
158 if pending.done(): | |
159 break | |
160 finally: | 160 finally: |
161 os.chdir(previous_cwd) | 161 os.chdir(previous_cwd) |
162 except base.DiscardPending, e: | 162 except base.DiscardPending, e: |
163 self._discard_pending(e.pending, e.message) | 163 self._discard_pending(e.pending, e.message) |
164 except Exception, e: | 164 except Exception, e: |
165 # Swallow every exception in that code and move on. Make sure to send a | 165 # Swallow every exception in that code and move on. Make sure to send a |
166 # stack trace though. | 166 # stack trace though. |
167 send_stack(e) | 167 send_stack(e) |
168 | 168 |
169 def update_status(self): | 169 def update_status(self): |
170 """Updates the status for each pending commit verifier.""" | 170 """Updates the status for each pending commit verifier.""" |
171 for verifier in self.verifiers: | 171 for verifier in self.verifiers: |
172 try: | 172 try: |
173 verifier.update_status(self.queue.pending_commits) | 173 verifier.update_status(self.queue.pending_commits) |
174 except base.DiscardPending, e: | 174 except base.DiscardPending, e: |
175 # It's not efficient since it takes a full loop for each pending commit | 175 # It's not efficient since it takes a full loop for each pending commit |
176 # to discard. | 176 # to discard. |
177 self._discard_pending(e.pending, e.message) | 177 self._discard_pending(e.pending, e.message) |
178 except Exception, e: | 178 except Exception, e: |
179 # Swallow every exception in that code and move on. Make sure to send a | 179 # Swallow every exception in that code and move on. Make sure to send a |
180 # stack trace though. | 180 # stack trace though. |
181 send_stack(e) | 181 send_stack(e) |
182 | 182 |
183 def scan_results(self): | 183 def scan_results(self): |
184 """Scans pending commits that can be committed or discarded.""" | 184 """Scans pending commits that can be committed or discarded.""" |
185 for pending in self.queue.pending_commits[:]: | 185 for pending in self.queue.pending_commits[:]: |
186 if pending.failed(): | 186 if pending.ignored(): |
187 self._discard_pending(pending, None) | |
188 elif pending.failed(): | |
187 self._discard_pending(pending, 'Patch verification failed') | 189 self._discard_pending(pending, 'Patch verification failed') |
188 elif pending.succeeded(): | 190 elif pending.succeeded(): |
189 # The item is removed right away. | 191 # The item is removed right away. |
190 self.queue.pending_commits.remove(pending) | 192 self.queue.pending_commits.remove(pending) |
191 try: | 193 try: |
192 self._last_minute_checks(pending) | 194 self._last_minute_checks(pending) |
193 commit_message = '%s\n\nReview URL: %s/%s' % ( | 195 commit_message = '%s\n\nReview URL: %s/%s' % ( |
194 pending.description, | 196 pending.description, |
195 pending.rietveld_server, | 197 pending.rietveld_server, |
196 pending.issue) | 198 pending.issue) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 'Patch failed to apply against %s.' % revision) | 275 'Patch failed to apply against %s.' % revision) |
274 | 276 |
275 def load(self, filename): | 277 def load(self, filename): |
276 """Loads the commit queue state from a JSON file.""" | 278 """Loads the commit queue state from a JSON file.""" |
277 self.queue = model.load_from_json_file(filename) | 279 self.queue = model.load_from_json_file(filename) |
278 self.queue.pending_commits = self.queue.pending_commits or [] | 280 self.queue.pending_commits = self.queue.pending_commits or [] |
279 | 281 |
280 def save(self, filename): | 282 def save(self, filename): |
281 """Save the commit queue state in a simple JSON file.""" | 283 """Save the commit queue state in a simple JSON file.""" |
282 model.save_to_json_file(filename, self.queue) | 284 model.save_to_json_file(filename, self.queue) |
OLD | NEW |