Merge lp:~mwhudson/launchpad/less-import-requestMirrors-bug-487357 into lp:launchpad
- less-import-requestMirrors-bug-487357
- Merge into devel
Proposed by
Michael Hudson-Doyle
Status: | Merged |
---|---|
Approved by: | Michael Hudson-Doyle |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~mwhudson/launchpad/less-import-requestMirrors-bug-487357 |
Merge into: | lp:launchpad |
Diff against target: |
613 lines (+171/-53) 13 files modified
lib/lp/code/browser/branch.py (+9/-1) lib/lp/code/enums.py (+9/-0) lib/lp/code/model/codeimport.py (+2/-1) lib/lp/code/model/codeimportjob.py (+6/-3) lib/lp/code/model/tests/test_codeimport.py (+16/-3) lib/lp/code/model/tests/test_codeimportjob.py (+4/-12) lib/lp/code/stories/codeimport/xx-codeimport-results.txt (+3/-0) lib/lp/code/templates/codeimport-macros.pt (+2/-4) lib/lp/codehosting/codeimport/tests/test_worker.py (+24/-2) lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+35/-2) lib/lp/codehosting/codeimport/worker.py (+40/-10) lib/lp/codehosting/codeimport/workermonitor.py (+18/-13) scripts/code-import-worker.py (+3/-2) |
To merge this branch: | bzr merge lp:~mwhudson/launchpad/less-import-requestMirrors-bug-487357 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Hummer (community) | Approve | ||
Review via email: mp+18361@code.launchpad.net |
Commit message
Extend the contract between the code import 'worker' and 'monitor' scripts by specifying that an exit code of 2 means that the import was successful but didn't import any new revisions so there's no need to request a mirror of the import branch.
Description of the change
To post a comment you must log in.
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote : | # |
Revision history for this message
Paul Hummer (rockstar) wrote : | # |
This all looks good. Thanks for doing this.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/browser/branch.py' | |||
2 | --- lib/lp/code/browser/branch.py 2010-01-29 17:15:31 +0000 | |||
3 | +++ lib/lp/code/browser/branch.py 2010-02-01 05:56:15 +0000 | |||
4 | @@ -81,7 +81,8 @@ | |||
5 | 81 | latest_proposals_for_each_branch) | 81 | latest_proposals_for_each_branch) |
6 | 82 | from lp.code.enums import ( | 82 | from lp.code.enums import ( |
7 | 83 | BranchLifecycleStatus, BranchType, CodeImportJobState, | 83 | BranchLifecycleStatus, BranchType, CodeImportJobState, |
9 | 84 | CodeImportReviewStatus, RevisionControlSystems, UICreatableBranchType) | 84 | CodeImportResultStatus, CodeImportReviewStatus, RevisionControlSystems, |
10 | 85 | UICreatableBranchType) | ||
11 | 85 | from lp.code.errors import InvalidBranchMergeProposal | 86 | from lp.code.errors import InvalidBranchMergeProposal |
12 | 86 | from lp.code.interfaces.branch import ( | 87 | from lp.code.interfaces.branch import ( |
13 | 87 | BranchCreationForbidden, BranchExists, IBranch, | 88 | BranchCreationForbidden, BranchExists, IBranch, |
14 | @@ -509,6 +510,13 @@ | |||
15 | 509 | """Return the last 10 CodeImportResults.""" | 510 | """Return the last 10 CodeImportResults.""" |
16 | 510 | return list(self.context.code_import.results[:10]) | 511 | return list(self.context.code_import.results[:10]) |
17 | 511 | 512 | ||
18 | 513 | def iconForCodeImportResultStatus(self, status): | ||
19 | 514 | """The icon to represent the `CodeImportResultStatus` `status`.""" | ||
20 | 515 | if status in CodeImportResultStatus.successes: | ||
21 | 516 | return "/@@/yes" | ||
22 | 517 | else: | ||
23 | 518 | return "/@@/no" | ||
24 | 519 | |||
25 | 512 | @property | 520 | @property |
26 | 513 | def is_svn_import(self): | 521 | def is_svn_import(self): |
27 | 514 | """True if an imported branch is a SVN import.""" | 522 | """True if an imported branch is a SVN import.""" |
28 | 515 | 523 | ||
29 | === modified file 'lib/lp/code/enums.py' | |||
30 | --- lib/lp/code/enums.py 2010-01-12 02:07:38 +0000 | |||
31 | +++ lib/lp/code/enums.py 2010-02-01 05:56:15 +0000 | |||
32 | @@ -799,6 +799,13 @@ | |||
33 | 799 | Import job completed successfully. | 799 | Import job completed successfully. |
34 | 800 | """) | 800 | """) |
35 | 801 | 801 | ||
36 | 802 | SUCCESS_NOCHANGE = DBItem(110, """ | ||
37 | 803 | Success with no changes | ||
38 | 804 | |||
39 | 805 | Import job completed successfully, but there were no new revisions to | ||
40 | 806 | import. | ||
41 | 807 | """) | ||
42 | 808 | |||
43 | 802 | FAILURE = DBItem(200, """ | 809 | FAILURE = DBItem(200, """ |
44 | 803 | Failure | 810 | Failure |
45 | 804 | 811 | ||
46 | @@ -857,6 +864,8 @@ | |||
47 | 857 | job, or the deletion of a CodeImport which had a running job. | 864 | job, or the deletion of a CodeImport which had a running job. |
48 | 858 | """) | 865 | """) |
49 | 859 | 866 | ||
50 | 867 | successes = [SUCCESS, SUCCESS_NOCHANGE] | ||
51 | 868 | |||
52 | 860 | 869 | ||
53 | 861 | class CodeReviewVote(DBEnumeratedType): | 870 | class CodeReviewVote(DBEnumeratedType): |
54 | 862 | """Code Review Votes | 871 | """Code Review Votes |
55 | 863 | 872 | ||
56 | === modified file 'lib/lp/code/model/codeimport.py' | |||
57 | --- lib/lp/code/model/codeimport.py 2010-01-13 02:51:30 +0000 | |||
58 | +++ lib/lp/code/model/codeimport.py 2010-02-01 05:56:15 +0000 | |||
59 | @@ -160,7 +160,8 @@ | |||
60 | 160 | "coalesce", | 160 | "coalesce", |
61 | 161 | Select( | 161 | Select( |
62 | 162 | CodeImportResult.id, | 162 | CodeImportResult.id, |
64 | 163 | And(CodeImportResult.status == CodeImportResultStatus.SUCCESS, | 163 | And(CodeImportResult.status.is_in( |
65 | 164 | CodeImportResultStatus.successes), | ||
66 | 164 | CodeImportResult.code_import == self), | 165 | CodeImportResult.code_import == self), |
67 | 165 | order_by=Desc(CodeImportResult.id), | 166 | order_by=Desc(CodeImportResult.id), |
68 | 166 | limit=1), | 167 | limit=1), |
69 | 167 | 168 | ||
70 | === modified file 'lib/lp/code/model/codeimportjob.py' | |||
71 | --- lib/lp/code/model/codeimportjob.py 2009-07-17 00:26:05 +0000 | |||
72 | +++ lib/lp/code/model/codeimportjob.py 2010-02-01 05:56:15 +0000 | |||
73 | @@ -287,11 +287,14 @@ | |||
74 | 287 | # Only start a new one if the import is still in the REVIEWED state. | 287 | # Only start a new one if the import is still in the REVIEWED state. |
75 | 288 | if code_import.review_status == CodeImportReviewStatus.REVIEWED: | 288 | if code_import.review_status == CodeImportReviewStatus.REVIEWED: |
76 | 289 | self.newJob(code_import) | 289 | self.newJob(code_import) |
80 | 290 | # If the status was successful, update the date_last_successful and | 290 | # If the status was successful, update date_last_successful. |
81 | 291 | # arrange for the branch to be mirrored. | 291 | if status in [CodeImportResultStatus.SUCCESS, |
82 | 292 | if status == CodeImportResultStatus.SUCCESS: | 292 | CodeImportResultStatus.SUCCESS_NOCHANGE]: |
83 | 293 | naked_import = removeSecurityProxy(code_import) | 293 | naked_import = removeSecurityProxy(code_import) |
84 | 294 | naked_import.date_last_successful = result.date_created | 294 | naked_import.date_last_successful = result.date_created |
85 | 295 | # If the status was successful and revisions were imported, arrange | ||
86 | 296 | # for the branch to be mirrored. | ||
87 | 297 | if status == CodeImportResultStatus.SUCCESS: | ||
88 | 295 | code_import.branch.requestMirror() | 298 | code_import.branch.requestMirror() |
89 | 296 | getUtility(ICodeImportEventSet).newFinish( | 299 | getUtility(ICodeImportEventSet).newFinish( |
90 | 297 | code_import, machine) | 300 | code_import, machine) |
91 | 298 | 301 | ||
92 | === modified file 'lib/lp/code/model/tests/test_codeimport.py' | |||
93 | --- lib/lp/code/model/tests/test_codeimport.py 2010-01-15 23:55:45 +0000 | |||
94 | +++ lib/lp/code/model/tests/test_codeimport.py 2010-02-01 05:56:15 +0000 | |||
95 | @@ -394,11 +394,15 @@ | |||
96 | 394 | getUtility(ICodeImportJobWorkflow).finishJob( | 394 | getUtility(ICodeImportJobWorkflow).finishJob( |
97 | 395 | running_job, CodeImportResultStatus.FAILURE, None) | 395 | running_job, CodeImportResultStatus.FAILURE, None) |
98 | 396 | 396 | ||
100 | 397 | def succeedImport(self, code_import): | 397 | def succeedImport(self, code_import, |
101 | 398 | status=CodeImportResultStatus.SUCCESS): | ||
102 | 398 | """Create if necessary a job for `code_import` and have it succeed.""" | 399 | """Create if necessary a job for `code_import` and have it succeed.""" |
103 | 400 | if status not in CodeImportResultStatus.successes: | ||
104 | 401 | raise AssertionError( | ||
105 | 402 | "succeedImport() should be called with a successful status!") | ||
106 | 399 | running_job = self.makeRunningJob(code_import) | 403 | running_job = self.makeRunningJob(code_import) |
107 | 400 | getUtility(ICodeImportJobWorkflow).finishJob( | 404 | getUtility(ICodeImportJobWorkflow).finishJob( |
109 | 401 | running_job, CodeImportResultStatus.SUCCESS, None) | 405 | running_job, status, None) |
110 | 402 | 406 | ||
111 | 403 | def test_consecutive_failure_count_zero_initially(self): | 407 | def test_consecutive_failure_count_zero_initially(self): |
112 | 404 | # A new code import has a consecutive_failure_count of 0. | 408 | # A new code import has a consecutive_failure_count of 0. |
113 | @@ -407,7 +411,7 @@ | |||
114 | 407 | 411 | ||
115 | 408 | def test_consecutive_failure_count_succeed(self): | 412 | def test_consecutive_failure_count_succeed(self): |
116 | 409 | # A code import that has succeeded once has a | 413 | # A code import that has succeeded once has a |
118 | 410 | # consecutive_failure_count of 1. | 414 | # consecutive_failure_count of 0. |
119 | 411 | code_import = self.factory.makeCodeImport() | 415 | code_import = self.factory.makeCodeImport() |
120 | 412 | self.succeedImport(code_import) | 416 | self.succeedImport(code_import) |
121 | 413 | self.assertEqual(0, code_import.consecutive_failure_count) | 417 | self.assertEqual(0, code_import.consecutive_failure_count) |
122 | @@ -419,6 +423,15 @@ | |||
123 | 419 | self.failImport(code_import) | 423 | self.failImport(code_import) |
124 | 420 | self.assertEqual(1, code_import.consecutive_failure_count) | 424 | self.assertEqual(1, code_import.consecutive_failure_count) |
125 | 421 | 425 | ||
126 | 426 | def test_consecutive_failure_count_succeed_succeed_no_changes(self): | ||
127 | 427 | # A code import that has succeeded then succeeded with no changes has | ||
128 | 428 | # a consecutive_failure_count of 0. | ||
129 | 429 | code_import = self.factory.makeCodeImport() | ||
130 | 430 | self.succeedImport(code_import) | ||
131 | 431 | self.succeedImport( | ||
132 | 432 | code_import, CodeImportResultStatus.SUCCESS_NOCHANGE) | ||
133 | 433 | self.assertEqual(0, code_import.consecutive_failure_count) | ||
134 | 434 | |||
135 | 422 | def test_consecutive_failure_count_fail_fail(self): | 435 | def test_consecutive_failure_count_fail_fail(self): |
136 | 423 | # A code import that has failed twice has a consecutive_failure_count | 436 | # A code import that has failed twice has a consecutive_failure_count |
137 | 424 | # of 2. | 437 | # of 2. |
138 | 425 | 438 | ||
139 | === modified file 'lib/lp/code/model/tests/test_codeimportjob.py' | |||
140 | --- lib/lp/code/model/tests/test_codeimportjob.py 2009-07-17 00:26:05 +0000 | |||
141 | +++ lib/lp/code/model/tests/test_codeimportjob.py 2010-02-01 05:56:15 +0000 | |||
142 | @@ -32,8 +32,7 @@ | |||
143 | 32 | from lp.code.interfaces.codeimportevent import ICodeImportEventSet | 32 | from lp.code.interfaces.codeimportevent import ICodeImportEventSet |
144 | 33 | from lp.code.interfaces.codeimportjob import ( | 33 | from lp.code.interfaces.codeimportjob import ( |
145 | 34 | ICodeImportJobSet, ICodeImportJobWorkflow) | 34 | ICodeImportJobSet, ICodeImportJobWorkflow) |
148 | 35 | from lp.code.interfaces.codeimportresult import ( | 35 | from lp.code.interfaces.codeimportresult import ICodeImportResult |
147 | 36 | ICodeImportResult, ICodeImportResultSet) | ||
149 | 37 | from lp.registry.interfaces.person import IPersonSet | 36 | from lp.registry.interfaces.person import IPersonSet |
150 | 38 | from lp.testing import ANONYMOUS, login, logout, TestCaseWithFactory | 37 | from lp.testing import ANONYMOUS, login, logout, TestCaseWithFactory |
151 | 39 | from canonical.launchpad.testing.codeimporthelpers import ( | 38 | from canonical.launchpad.testing.codeimporthelpers import ( |
152 | @@ -274,7 +273,7 @@ | |||
153 | 274 | self.assertReclaimableJobs([stale_job]) | 273 | self.assertReclaimableJobs([stale_job]) |
154 | 275 | machine = self.factory.makeCodeImportMachine(set_online=True) | 274 | machine = self.factory.makeCodeImportMachine(set_online=True) |
155 | 276 | login(ANONYMOUS) | 275 | login(ANONYMOUS) |
157 | 277 | job = getUtility(ICodeImportJobSet).getJobForMachine( | 276 | getUtility(ICodeImportJobSet).getJobForMachine( |
158 | 278 | machine.hostname) | 277 | machine.hostname) |
159 | 279 | login_for_code_imports() | 278 | login_for_code_imports() |
160 | 280 | # Now there are no reclaimable jobs. | 279 | # Now there are no reclaimable jobs. |
161 | @@ -456,7 +455,7 @@ | |||
162 | 456 | # of the job that was deleted when the CodeImport review status | 455 | # of the job that was deleted when the CodeImport review status |
163 | 457 | # changed from REVIEWED. That is the date_job_started of the most | 456 | # changed from REVIEWED. That is the date_job_started of the most |
164 | 458 | # recent CodeImportResult plus the effective update interval. | 457 | # recent CodeImportResult plus the effective update interval. |
166 | 459 | job = getUtility(ICodeImportJobWorkflow).newJob(code_import) | 458 | getUtility(ICodeImportJobWorkflow).newJob(code_import) |
167 | 460 | self.assertSqlAttributeEqualsDate( | 459 | self.assertSqlAttributeEqualsDate( |
168 | 461 | code_import.import_job, 'date_due', | 460 | code_import.import_job, 'date_due', |
169 | 462 | recent_result.date_job_started + interval) | 461 | recent_result.date_job_started + interval) |
170 | @@ -690,7 +689,6 @@ | |||
171 | 690 | def test_wrongJobState(self): | 689 | def test_wrongJobState(self): |
172 | 691 | # Calling updateHeartbeat with a job whose state is not RUNNING is an | 690 | # Calling updateHeartbeat with a job whose state is not RUNNING is an |
173 | 692 | # error. | 691 | # error. |
174 | 693 | machine = self.factory.makeCodeImportMachine() | ||
175 | 694 | code_import = self.factory.makeCodeImport() | 692 | code_import = self.factory.makeCodeImport() |
176 | 695 | job = self.factory.makeCodeImportJob(code_import) | 693 | job = self.factory.makeCodeImportJob(code_import) |
177 | 696 | self.assertFailure( | 694 | self.assertFailure( |
178 | @@ -740,7 +738,6 @@ | |||
179 | 740 | 738 | ||
180 | 741 | def test_wrongJobState(self): | 739 | def test_wrongJobState(self): |
181 | 742 | # Calling finishJob with a job whose state is not RUNNING is an error. | 740 | # Calling finishJob with a job whose state is not RUNNING is an error. |
182 | 743 | machine = self.factory.makeCodeImportMachine() | ||
183 | 744 | code_import = self.factory.makeCodeImport() | 741 | code_import = self.factory.makeCodeImport() |
184 | 745 | job = self.factory.makeCodeImportJob(code_import) | 742 | job = self.factory.makeCodeImportJob(code_import) |
185 | 746 | self.switchDbUser() | 743 | self.switchDbUser() |
186 | @@ -767,7 +764,6 @@ | |||
187 | 767 | # finishJob() creates a new CodeImportJob for the given CodeImport, | 764 | # finishJob() creates a new CodeImportJob for the given CodeImport, |
188 | 768 | # scheduled appropriately far in the future. | 765 | # scheduled appropriately far in the future. |
189 | 769 | running_job = self.makeRunningJob() | 766 | running_job = self.makeRunningJob() |
190 | 770 | running_job_date_due = running_job.date_due | ||
191 | 771 | code_import = running_job.code_import | 767 | code_import = running_job.code_import |
192 | 772 | self.switchDbUser() | 768 | self.switchDbUser() |
193 | 773 | getUtility(ICodeImportJobWorkflow).finishJob( | 769 | getUtility(ICodeImportJobWorkflow).finishJob( |
194 | @@ -784,7 +780,6 @@ | |||
195 | 784 | # finishJob() creates a new CodeImportJob for the given CodeImport, | 780 | # finishJob() creates a new CodeImportJob for the given CodeImport, |
196 | 785 | # unless the CodeImport has been suspended or marked invalid. | 781 | # unless the CodeImport has been suspended or marked invalid. |
197 | 786 | running_job = self.makeRunningJob() | 782 | running_job = self.makeRunningJob() |
198 | 787 | running_job_date_due = running_job.date_due | ||
199 | 788 | code_import = running_job.code_import | 783 | code_import = running_job.code_import |
200 | 789 | ddaa = getUtility(IPersonSet).getByEmail( | 784 | ddaa = getUtility(IPersonSet).getByEmail( |
201 | 790 | 'david.allouche@canonical.com') | 785 | 'david.allouche@canonical.com') |
202 | @@ -798,9 +793,7 @@ | |||
203 | 798 | def test_createsResultObject(self): | 793 | def test_createsResultObject(self): |
204 | 799 | # finishJob() creates a CodeImportResult object for the given import. | 794 | # finishJob() creates a CodeImportResult object for the given import. |
205 | 800 | running_job = self.makeRunningJob() | 795 | running_job = self.makeRunningJob() |
206 | 801 | running_job_date_due = running_job.date_due | ||
207 | 802 | code_import = running_job.code_import | 796 | code_import = running_job.code_import |
208 | 803 | result_set = getUtility(ICodeImportResultSet) | ||
209 | 804 | # Before calling finishJob() there are no CodeImportResults for the | 797 | # Before calling finishJob() there are no CodeImportResults for the |
210 | 805 | # given import... | 798 | # given import... |
211 | 806 | self.assertEqual(len(list(code_import.results)), 0) | 799 | self.assertEqual(len(list(code_import.results)), 0) |
212 | @@ -903,7 +896,6 @@ | |||
213 | 903 | 896 | ||
214 | 904 | self.switchDbUser() | 897 | self.switchDbUser() |
215 | 905 | log_data = 'several\nlines\nof\nlog data' | 898 | log_data = 'several\nlines\nof\nlog data' |
216 | 906 | log_excerpt = log_data.splitlines()[-1] | ||
217 | 907 | log_alias_id = getUtility(ILibrarianClient).addFile( | 899 | log_alias_id = getUtility(ILibrarianClient).addFile( |
218 | 908 | 'import_log.txt', len(log_data), | 900 | 'import_log.txt', len(log_data), |
219 | 909 | StringIO.StringIO(log_data), 'text/plain') | 901 | StringIO.StringIO(log_data), 'text/plain') |
220 | @@ -939,7 +931,7 @@ | |||
221 | 939 | code_import = job.code_import | 931 | code_import = job.code_import |
222 | 940 | self.assertTrue(code_import.date_last_successful is None) | 932 | self.assertTrue(code_import.date_last_successful is None) |
223 | 941 | getUtility(ICodeImportJobWorkflow).finishJob(job, status, None) | 933 | getUtility(ICodeImportJobWorkflow).finishJob(job, status, None) |
225 | 942 | if status == CodeImportResultStatus.SUCCESS: | 934 | if status in CodeImportResultStatus.successes: |
226 | 943 | self.assertTrue(code_import.date_last_successful is not None) | 935 | self.assertTrue(code_import.date_last_successful is not None) |
227 | 944 | else: | 936 | else: |
228 | 945 | self.assertTrue(code_import.date_last_successful is None) | 937 | self.assertTrue(code_import.date_last_successful is None) |
229 | 946 | 938 | ||
230 | === modified file 'lib/lp/code/stories/codeimport/xx-codeimport-results.txt' | |||
231 | --- lib/lp/code/stories/codeimport/xx-codeimport-results.txt 2009-03-24 12:43:49 +0000 | |||
232 | +++ lib/lp/code/stories/codeimport/xx-codeimport-results.txt 2010-02-01 05:56:15 +0000 | |||
233 | @@ -23,6 +23,8 @@ | |||
234 | 23 | >>> browser.open(branch_url) | 23 | >>> browser.open(branch_url) |
235 | 24 | >>> import_results = find_tag_by_id(browser.contents, 'import-results') | 24 | >>> import_results = find_tag_by_id(browser.contents, 'import-results') |
236 | 25 | >>> print extract_text(import_results).replace('—', '--') | 25 | >>> print extract_text(import_results).replace('—', '--') |
237 | 26 | Import started on 2007-12-10 on odin and finished on 2007-12-10 | ||
238 | 27 | taking ten hours -- see the log | ||
239 | 26 | Import started on 2007-12-09 on odin and finished on 2007-12-09 | 28 | Import started on 2007-12-09 on odin and finished on 2007-12-09 |
240 | 27 | taking nine hours -- see the log | 29 | taking nine hours -- see the log |
241 | 28 | Import started on 2007-12-08 on odin and finished on 2007-12-08 | 30 | Import started on 2007-12-08 on odin and finished on 2007-12-08 |
242 | @@ -58,4 +60,5 @@ | |||
243 | 58 | <img src="/@@/no" title="Source Checkout Failed" /> | 60 | <img src="/@@/no" title="Source Checkout Failed" /> |
244 | 59 | <img src="/@@/no" title="Internal Failure" /> | 61 | <img src="/@@/no" title="Internal Failure" /> |
245 | 60 | <img src="/@@/no" title="Failure" /> | 62 | <img src="/@@/no" title="Failure" /> |
246 | 63 | <img src="/@@/yes" title="Success with no changes" /> | ||
247 | 61 | <img src="/@@/yes" title="Success" /> | 64 | <img src="/@@/yes" title="Success" /> |
248 | 62 | 65 | ||
249 | === modified file 'lib/lp/code/templates/codeimport-macros.pt' | |||
250 | --- lib/lp/code/templates/codeimport-macros.pt 2009-07-17 17:59:07 +0000 | |||
251 | +++ lib/lp/code/templates/codeimport-macros.pt 2010-02-01 05:56:15 +0000 | |||
252 | @@ -8,10 +8,8 @@ | |||
253 | 8 | Expects a parameter called 'result'. | 8 | Expects a parameter called 'result'. |
254 | 9 | </tal:comment> | 9 | </tal:comment> |
255 | 10 | 10 | ||
260 | 11 | <img src="/@@/yes" tal:condition="result/status/enumvalue:SUCCESS" | 11 | <img tal:attributes="src python:view.iconForCodeImportResultStatus(result.status); |
261 | 12 | title="Success"/> | 12 | title result/status/title"/> |
258 | 13 | <img src="/@@/no" tal:condition="not: result/status/enumvalue:SUCCESS" | ||
259 | 14 | tal:attributes="title result/status/title"/> | ||
262 | 15 | Import started | 13 | Import started |
263 | 16 | <tal:when replace="result/date_job_started/fmt:displaydate"> | 14 | <tal:when replace="result/date_job_started/fmt:displaydate"> |
264 | 17 | 4 hours ago | 15 | 4 hours ago |
265 | 18 | 16 | ||
266 | === modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py' | |||
267 | --- lib/lp/codehosting/codeimport/tests/test_worker.py 2010-01-13 02:09:34 +0000 | |||
268 | +++ lib/lp/codehosting/codeimport/tests/test_worker.py 2010-02-01 05:56:15 +0000 | |||
269 | @@ -30,9 +30,9 @@ | |||
270 | 30 | 30 | ||
271 | 31 | from lp.codehosting import load_optional_plugin | 31 | from lp.codehosting import load_optional_plugin |
272 | 32 | from lp.codehosting.codeimport.worker import ( | 32 | from lp.codehosting.codeimport.worker import ( |
274 | 33 | BazaarBranchStore, BzrSvnImportWorker, CSCVSImportWorker, | 33 | BazaarBranchStore, BzrSvnImportWorker, CodeImportWorkerExitCode, |
275 | 34 | ForeignTreeStore, GitImportWorker, HgImportWorker, ImportDataStore, | 34 | ForeignTreeStore, GitImportWorker, HgImportWorker, ImportDataStore, |
277 | 35 | ImportWorker, get_default_bazaar_branch_store) | 35 | ImportWorker, CSCVSImportWorker, get_default_bazaar_branch_store) |
278 | 36 | from lp.codehosting.codeimport.tests.servers import ( | 36 | from lp.codehosting.codeimport.tests.servers import ( |
279 | 37 | CVSServer, GitServer, MercurialServer, SubversionServer) | 37 | CVSServer, GitServer, MercurialServer, SubversionServer) |
280 | 38 | from lp.codehosting.tests.helpers import ( | 38 | from lp.codehosting.tests.helpers import ( |
281 | @@ -710,6 +710,28 @@ | |||
282 | 710 | self.assertEqual( | 710 | self.assertEqual( |
283 | 711 | self.foreign_commit_count, len(branch.revision_history())) | 711 | self.foreign_commit_count, len(branch.revision_history())) |
284 | 712 | 712 | ||
285 | 713 | def test_script_exit_codes(self): | ||
286 | 714 | # After a successful import that imports revisions, the worker exits | ||
287 | 715 | # with a code of CodeImportWorkerExitCode.SUCCESS. After a successful | ||
288 | 716 | # import that does not import revisions, the worker exits with a code | ||
289 | 717 | # of CodeImportWorkerExitCode.SUCCESS_NOCHANGE. | ||
290 | 718 | source_details = self.makeSourceDetails( | ||
291 | 719 | 'trunk', [('README', 'Original contents')]) | ||
292 | 720 | |||
293 | 721 | clean_up_default_stores_for_import(source_details) | ||
294 | 722 | |||
295 | 723 | script_path = os.path.join( | ||
296 | 724 | config.root, 'scripts', 'code-import-worker.py') | ||
297 | 725 | output = tempfile.TemporaryFile() | ||
298 | 726 | retcode = subprocess.call( | ||
299 | 727 | [script_path] + source_details.asArguments(), | ||
300 | 728 | stderr=output, stdout=output) | ||
301 | 729 | self.assertEqual(retcode, CodeImportWorkerExitCode.SUCCESS) | ||
302 | 730 | retcode = subprocess.call( | ||
303 | 731 | [script_path] + source_details.asArguments(), | ||
304 | 732 | stderr=output, stdout=output) | ||
305 | 733 | self.assertEqual(retcode, CodeImportWorkerExitCode.SUCCESS_NOCHANGE) | ||
306 | 734 | |||
307 | 713 | 735 | ||
308 | 714 | class CSCVSActualImportMixin(TestActualImportMixin): | 736 | class CSCVSActualImportMixin(TestActualImportMixin): |
309 | 715 | 737 | ||
310 | 716 | 738 | ||
311 | === modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py' | |||
312 | --- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-01-13 02:09:34 +0000 | |||
313 | +++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-02-01 05:56:15 +0000 | |||
314 | @@ -38,7 +38,8 @@ | |||
315 | 38 | from lp.code.model.codeimportjob import CodeImportJob | 38 | from lp.code.model.codeimportjob import CodeImportJob |
316 | 39 | from lp.codehosting import load_optional_plugin | 39 | from lp.codehosting import load_optional_plugin |
317 | 40 | from lp.codehosting.codeimport.worker import ( | 40 | from lp.codehosting.codeimport.worker import ( |
319 | 41 | CodeImportSourceDetails, get_default_bazaar_branch_store) | 41 | CodeImportSourceDetails, CodeImportWorkerExitCode, |
320 | 42 | get_default_bazaar_branch_store) | ||
321 | 42 | from lp.codehosting.codeimport.workermonitor import ( | 43 | from lp.codehosting.codeimport.workermonitor import ( |
322 | 43 | CodeImportWorkerMonitor, CodeImportWorkerMonitorProtocol, ExitQuietly, | 44 | CodeImportWorkerMonitor, CodeImportWorkerMonitorProtocol, ExitQuietly, |
323 | 44 | read_only_transaction) | 45 | read_only_transaction) |
324 | @@ -292,7 +293,39 @@ | |||
325 | 292 | 293 | ||
326 | 293 | def test_callFinishJobCallsFinishJobFailure(self): | 294 | def test_callFinishJobCallsFinishJobFailure(self): |
327 | 294 | # callFinishJob calls finishJob with CodeImportResultStatus.FAILURE | 295 | # callFinishJob calls finishJob with CodeImportResultStatus.FAILURE |
329 | 295 | # and swallows the failure if its argument is a Failure. | 296 | # and swallows the failure if its argument indicates that the |
330 | 297 | # subprocess exited with an exit code of | ||
331 | 298 | # CodeImportWorkerExitCode.FAILURE. | ||
332 | 299 | calls = self.patchOutFinishJob() | ||
333 | 300 | ret = self.worker_monitor.callFinishJob( | ||
334 | 301 | makeFailure( | ||
335 | 302 | error.ProcessTerminated, | ||
336 | 303 | exitCode=CodeImportWorkerExitCode.FAILURE)) | ||
337 | 304 | self.assertEqual(calls, [CodeImportResultStatus.FAILURE]) | ||
338 | 305 | self.assertOopsesLogged([error.ProcessTerminated]) | ||
339 | 306 | # We return the deferred that callFinishJob returns -- if | ||
340 | 307 | # callFinishJob did not swallow the error, this will fail the test. | ||
341 | 308 | return ret | ||
342 | 309 | |||
343 | 310 | def test_callFinishJobCallsFinishJobSuccessNoChange(self): | ||
344 | 311 | # If the argument to callFinishJob indicates that the subprocess | ||
345 | 312 | # exited with a code of CodeImportWorkerExitCode.SUCCESS_NOCHANGE, it | ||
346 | 313 | # calls finishJob with a status of SUCCESS_NOCHANGE. | ||
347 | 314 | calls = self.patchOutFinishJob() | ||
348 | 315 | ret = self.worker_monitor.callFinishJob( | ||
349 | 316 | makeFailure( | ||
350 | 317 | error.ProcessTerminated, | ||
351 | 318 | exitCode=CodeImportWorkerExitCode.SUCCESS_NOCHANGE)) | ||
352 | 319 | self.assertEqual(calls, [CodeImportResultStatus.SUCCESS_NOCHANGE]) | ||
353 | 320 | self.assertOopsesLogged([]) | ||
354 | 321 | # We return the deferred that callFinishJob returns -- if | ||
355 | 322 | # callFinishJob did not swallow the error, this will fail the test. | ||
356 | 323 | return ret | ||
357 | 324 | |||
358 | 325 | def test_callFinishJobCallsFinishJobArbitraryFailure(self): | ||
359 | 326 | # If the argument to callFinishJob indicates that there was some other | ||
360 | 327 | # failure that had nothing to do with the subprocess, it records | ||
361 | 328 | # failure. | ||
362 | 296 | calls = self.patchOutFinishJob() | 329 | calls = self.patchOutFinishJob() |
363 | 297 | ret = self.worker_monitor.callFinishJob(makeFailure(RuntimeError)) | 330 | ret = self.worker_monitor.callFinishJob(makeFailure(RuntimeError)) |
364 | 298 | self.assertEqual(calls, [CodeImportResultStatus.FAILURE]) | 331 | self.assertEqual(calls, [CodeImportResultStatus.FAILURE]) |
365 | 299 | 332 | ||
366 | === modified file 'lib/lp/codehosting/codeimport/worker.py' | |||
367 | --- lib/lp/codehosting/codeimport/worker.py 2010-01-13 02:09:34 +0000 | |||
368 | +++ lib/lp/codehosting/codeimport/worker.py 2010-02-01 05:56:15 +0000 | |||
369 | @@ -9,6 +9,7 @@ | |||
370 | 9 | 'BzrSvnImportWorker', | 9 | 'BzrSvnImportWorker', |
371 | 10 | 'CSCVSImportWorker', | 10 | 'CSCVSImportWorker', |
372 | 11 | 'CodeImportSourceDetails', | 11 | 'CodeImportSourceDetails', |
373 | 12 | 'CodeImportWorkerExitCode', | ||
374 | 12 | 'ForeignTreeStore', | 13 | 'ForeignTreeStore', |
375 | 13 | 'GitImportWorker', | 14 | 'GitImportWorker', |
376 | 14 | 'HgImportWorker', | 15 | 'HgImportWorker', |
377 | @@ -29,13 +30,13 @@ | |||
378 | 29 | from bzrlib.upgrade import upgrade | 30 | from bzrlib.upgrade import upgrade |
379 | 30 | 31 | ||
380 | 31 | from canonical.cachedproperty import cachedproperty | 32 | from canonical.cachedproperty import cachedproperty |
381 | 33 | from lp.code.enums import RevisionControlSystems | ||
382 | 32 | from lp.codehosting.codeimport.foreigntree import ( | 34 | from lp.codehosting.codeimport.foreigntree import ( |
383 | 33 | CVSWorkingTree, SubversionWorkingTree) | 35 | CVSWorkingTree, SubversionWorkingTree) |
384 | 34 | from lp.codehosting.codeimport.tarball import ( | 36 | from lp.codehosting.codeimport.tarball import ( |
385 | 35 | create_tarball, extract_tarball) | 37 | create_tarball, extract_tarball) |
386 | 36 | from lp.codehosting.codeimport.uifactory import LoggingUIFactory | 38 | from lp.codehosting.codeimport.uifactory import LoggingUIFactory |
387 | 37 | from canonical.config import config | 39 | from canonical.config import config |
388 | 38 | from lp.code.enums import RevisionControlSystems | ||
389 | 39 | 40 | ||
390 | 40 | from cscvs.cmds import totla | 41 | from cscvs.cmds import totla |
391 | 41 | import cscvs | 42 | import cscvs |
392 | @@ -43,6 +44,14 @@ | |||
393 | 43 | import SCM | 44 | import SCM |
394 | 44 | 45 | ||
395 | 45 | 46 | ||
396 | 47 | class CodeImportWorkerExitCode: | ||
397 | 48 | """Exit codes used by the code import worker script.""" | ||
398 | 49 | |||
399 | 50 | SUCCESS = 0 | ||
400 | 51 | FAILURE = 1 | ||
401 | 52 | SUCCESS_NOCHANGE = 2 | ||
402 | 53 | |||
403 | 54 | |||
404 | 46 | class BazaarBranchStore: | 55 | class BazaarBranchStore: |
405 | 47 | """A place where Bazaar branches of code imports are kept.""" | 56 | """A place where Bazaar branches of code imports are kept.""" |
406 | 48 | 57 | ||
407 | @@ -77,7 +86,11 @@ | |||
408 | 77 | return BzrDir.open(target_path).open_workingtree() | 86 | return BzrDir.open(target_path).open_workingtree() |
409 | 78 | 87 | ||
410 | 79 | def push(self, db_branch_id, bzr_tree, required_format): | 88 | def push(self, db_branch_id, bzr_tree, required_format): |
412 | 80 | """Push up `bzr_tree` as the Bazaar branch for `code_import`.""" | 89 | """Push up `bzr_tree` as the Bazaar branch for `code_import`. |
413 | 90 | |||
414 | 91 | :return: A boolean that is true if the push was non-trivial | ||
415 | 92 | (i.e. actually transferred revisions). | ||
416 | 93 | """ | ||
417 | 81 | self.transport.create_prefix() | 94 | self.transport.create_prefix() |
418 | 82 | branch_from = bzr_tree.branch | 95 | branch_from = bzr_tree.branch |
419 | 83 | target_url = self._getMirrorURL(db_branch_id) | 96 | target_url = self._getMirrorURL(db_branch_id) |
420 | @@ -86,7 +99,8 @@ | |||
421 | 86 | except NotBranchError: | 99 | except NotBranchError: |
422 | 87 | branch_to = BzrDir.create_branch_and_repo( | 100 | branch_to = BzrDir.create_branch_and_repo( |
423 | 88 | target_url, format=required_format) | 101 | target_url, format=required_format) |
425 | 89 | branch_to.pull(branch_from, overwrite=True) | 102 | pull_result = branch_to.pull(branch_from, overwrite=True) |
426 | 103 | return pull_result.old_revid != pull_result.new_revid | ||
427 | 90 | 104 | ||
428 | 91 | 105 | ||
429 | 92 | def get_default_bazaar_branch_store(): | 106 | def get_default_bazaar_branch_store(): |
430 | @@ -356,8 +370,11 @@ | |||
431 | 356 | self.required_format) | 370 | self.required_format) |
432 | 357 | 371 | ||
433 | 358 | def pushBazaarWorkingTree(self, bazaar_tree): | 372 | def pushBazaarWorkingTree(self, bazaar_tree): |
436 | 359 | """Push the updated Bazaar working tree to the server.""" | 373 | """Push the updated Bazaar working tree to the server. |
437 | 360 | self.bazaar_branch_store.push( | 374 | |
438 | 375 | :return: True if revisions were transferred. | ||
439 | 376 | """ | ||
440 | 377 | return self.bazaar_branch_store.push( | ||
441 | 361 | self.source_details.branch_id, bazaar_tree, self.required_format) | 378 | self.source_details.branch_id, bazaar_tree, self.required_format) |
442 | 362 | 379 | ||
443 | 363 | def getWorkingDirectory(self): | 380 | def getWorkingDirectory(self): |
444 | @@ -390,12 +407,20 @@ | |||
445 | 390 | saved_pwd = os.getcwd() | 407 | saved_pwd = os.getcwd() |
446 | 391 | os.chdir(working_directory) | 408 | os.chdir(working_directory) |
447 | 392 | try: | 409 | try: |
449 | 393 | self._doImport() | 410 | non_trivial = self._doImport() |
450 | 411 | if non_trivial: | ||
451 | 412 | return CodeImportWorkerExitCode.SUCCESS | ||
452 | 413 | else: | ||
453 | 414 | return CodeImportWorkerExitCode.SUCCESS_NOCHANGE | ||
454 | 394 | finally: | 415 | finally: |
455 | 395 | shutil.rmtree(working_directory) | 416 | shutil.rmtree(working_directory) |
456 | 396 | os.chdir(saved_pwd) | 417 | os.chdir(saved_pwd) |
457 | 397 | 418 | ||
458 | 398 | def _doImport(self): | 419 | def _doImport(self): |
459 | 420 | """Perform the import. | ||
460 | 421 | |||
461 | 422 | :return: True if the import actually imported some new revisions. | ||
462 | 423 | """ | ||
463 | 399 | raise NotImplementedError() | 424 | raise NotImplementedError() |
464 | 400 | 425 | ||
465 | 401 | 426 | ||
466 | @@ -470,8 +495,9 @@ | |||
467 | 470 | foreign_tree = self.getForeignTree() | 495 | foreign_tree = self.getForeignTree() |
468 | 471 | bazaar_tree = self.getBazaarWorkingTree() | 496 | bazaar_tree = self.getBazaarWorkingTree() |
469 | 472 | self.importToBazaar(foreign_tree, bazaar_tree) | 497 | self.importToBazaar(foreign_tree, bazaar_tree) |
471 | 473 | self.pushBazaarWorkingTree(bazaar_tree) | 498 | non_trivial = self.pushBazaarWorkingTree(bazaar_tree) |
472 | 474 | self.foreign_tree_store.archive(foreign_tree) | 499 | self.foreign_tree_store.archive(foreign_tree) |
473 | 500 | return non_trivial | ||
474 | 475 | 501 | ||
475 | 476 | 502 | ||
476 | 477 | class PullingImportWorker(ImportWorker): | 503 | class PullingImportWorker(ImportWorker): |
477 | @@ -506,7 +532,7 @@ | |||
478 | 506 | bazaar_tree.branch.pull(foreign_branch, overwrite=True) | 532 | bazaar_tree.branch.pull(foreign_branch, overwrite=True) |
479 | 507 | finally: | 533 | finally: |
480 | 508 | bzrlib.ui.ui_factory = saved_factory | 534 | bzrlib.ui.ui_factory = saved_factory |
482 | 509 | self.pushBazaarWorkingTree(bazaar_tree) | 535 | return self.pushBazaarWorkingTree(bazaar_tree) |
483 | 510 | 536 | ||
484 | 511 | 537 | ||
485 | 512 | class GitImportWorker(PullingImportWorker): | 538 | class GitImportWorker(PullingImportWorker): |
486 | @@ -542,9 +568,11 @@ | |||
487 | 542 | that bzr-git will have created at .bzr/repository/bzr.git into the | 568 | that bzr-git will have created at .bzr/repository/bzr.git into the |
488 | 543 | import data store. | 569 | import data store. |
489 | 544 | """ | 570 | """ |
491 | 545 | PullingImportWorker.pushBazaarWorkingTree(self, bazaar_tree) | 571 | non_trivial = PullingImportWorker.pushBazaarWorkingTree( |
492 | 572 | self, bazaar_tree) | ||
493 | 546 | self.import_data_store.put( | 573 | self.import_data_store.put( |
494 | 547 | 'git.db', bazaar_tree.branch.repository._transport) | 574 | 'git.db', bazaar_tree.branch.repository._transport) |
495 | 575 | return non_trivial | ||
496 | 548 | 576 | ||
497 | 549 | 577 | ||
498 | 550 | class HgImportWorker(PullingImportWorker): | 578 | class HgImportWorker(PullingImportWorker): |
499 | @@ -581,9 +609,11 @@ | |||
500 | 581 | that bzr-hg will have created at .bzr/repository/hg-v2.db into the | 609 | that bzr-hg will have created at .bzr/repository/hg-v2.db into the |
501 | 582 | import data store. | 610 | import data store. |
502 | 583 | """ | 611 | """ |
504 | 584 | PullingImportWorker.pushBazaarWorkingTree(self, bazaar_tree) | 612 | non_trivial = PullingImportWorker.pushBazaarWorkingTree( |
505 | 613 | self, bazaar_tree) | ||
506 | 585 | self.import_data_store.put( | 614 | self.import_data_store.put( |
507 | 586 | self.db_file, bazaar_tree.branch.repository._transport) | 615 | self.db_file, bazaar_tree.branch.repository._transport) |
508 | 616 | return non_trivial | ||
509 | 587 | 617 | ||
510 | 588 | 618 | ||
511 | 589 | class BzrSvnImportWorker(PullingImportWorker): | 619 | class BzrSvnImportWorker(PullingImportWorker): |
512 | 590 | 620 | ||
513 | === modified file 'lib/lp/codehosting/codeimport/workermonitor.py' | |||
514 | --- lib/lp/codehosting/codeimport/workermonitor.py 2009-06-25 04:06:00 +0000 | |||
515 | +++ lib/lp/codehosting/codeimport/workermonitor.py 2010-02-01 05:56:15 +0000 | |||
516 | @@ -10,10 +10,9 @@ | |||
517 | 10 | 10 | ||
518 | 11 | 11 | ||
519 | 12 | import os | 12 | import os |
520 | 13 | import sys | ||
521 | 14 | import tempfile | 13 | import tempfile |
522 | 15 | 14 | ||
524 | 16 | from twisted.internet import defer, reactor, task | 15 | from twisted.internet import defer, error, reactor, task |
525 | 17 | from twisted.python import failure | 16 | from twisted.python import failure |
526 | 18 | from twisted.python.util import mergeFunctionMetadata | 17 | from twisted.python.util import mergeFunctionMetadata |
527 | 19 | 18 | ||
528 | @@ -32,7 +31,8 @@ | |||
529 | 32 | from lp.code.enums import CodeImportResultStatus | 31 | from lp.code.enums import CodeImportResultStatus |
530 | 33 | from lp.code.interfaces.codeimportjob import ( | 32 | from lp.code.interfaces.codeimportjob import ( |
531 | 34 | ICodeImportJobSet, ICodeImportJobWorkflow) | 33 | ICodeImportJobSet, ICodeImportJobWorkflow) |
533 | 35 | from lp.codehosting.codeimport.worker import CodeImportSourceDetails | 34 | from lp.codehosting.codeimport.worker import ( |
534 | 35 | CodeImportSourceDetails, CodeImportWorkerExitCode) | ||
535 | 36 | from lp.testing import login, logout, ANONYMOUS | 36 | from lp.testing import login, logout, ANONYMOUS |
536 | 37 | 37 | ||
537 | 38 | 38 | ||
538 | @@ -243,19 +243,15 @@ | |||
539 | 243 | def finishJob(self, status): | 243 | def finishJob(self, status): |
540 | 244 | """Call the finishJob method for the job we are working on. | 244 | """Call the finishJob method for the job we are working on. |
541 | 245 | 245 | ||
546 | 246 | This method uploads the log file to the librarian first. If this | 246 | This method uploads the log file to the librarian first. |
543 | 247 | fails, we still try to call finishJob, but return the librarian's | ||
544 | 248 | failure if finishJob succeeded (if finishJob fails, that exception | ||
545 | 249 | 'wins'). | ||
547 | 250 | """ | 247 | """ |
548 | 251 | job = self.getJob() | 248 | job = self.getJob() |
549 | 252 | log_file_size = self._log_file.tell() | 249 | log_file_size = self._log_file.tell() |
550 | 253 | librarian_failure = None | ||
551 | 254 | if log_file_size > 0: | 250 | if log_file_size > 0: |
552 | 255 | self._log_file.seek(0) | 251 | self._log_file.seek(0) |
553 | 256 | branch = job.code_import.branch | 252 | branch = job.code_import.branch |
556 | 257 | log_file_name = '%s-%s-log.txt' % ( | 253 | log_file_name = '%s-%s-%s-log.txt' % ( |
557 | 258 | branch.product.name, branch.name) | 254 | branch.owner.name, branch.product.name, branch.name) |
558 | 259 | try: | 255 | try: |
559 | 260 | log_file_alias = self._createLibrarianFileAlias( | 256 | log_file_alias = self._createLibrarianFileAlias( |
560 | 261 | log_file_name, log_file_size, self._log_file, | 257 | log_file_name, log_file_size, self._log_file, |
561 | @@ -300,16 +296,25 @@ | |||
562 | 300 | failure.trap(ExitQuietly) | 296 | failure.trap(ExitQuietly) |
563 | 301 | return None | 297 | return None |
564 | 302 | 298 | ||
565 | 299 | def _reasonToStatus(self, reason): | ||
566 | 300 | if isinstance(reason, failure.Failure): | ||
567 | 301 | if reason.check(error.ProcessTerminated): | ||
568 | 302 | if reason.value.exitCode == \ | ||
569 | 303 | CodeImportWorkerExitCode.SUCCESS_NOCHANGE: | ||
570 | 304 | return CodeImportResultStatus.SUCCESS_NOCHANGE | ||
571 | 305 | return CodeImportResultStatus.FAILURE | ||
572 | 306 | else: | ||
573 | 307 | return CodeImportResultStatus.SUCCESS | ||
574 | 308 | |||
575 | 303 | def callFinishJob(self, reason): | 309 | def callFinishJob(self, reason): |
576 | 304 | """Call finishJob() with the appropriate status.""" | 310 | """Call finishJob() with the appropriate status.""" |
577 | 305 | if not self._call_finish_job: | 311 | if not self._call_finish_job: |
578 | 306 | return reason | 312 | return reason |
580 | 307 | if isinstance(reason, failure.Failure): | 313 | status = self._reasonToStatus(reason) |
581 | 314 | if status == CodeImportResultStatus.FAILURE: | ||
582 | 308 | self._log_file.write("Import failed:\n") | 315 | self._log_file.write("Import failed:\n") |
583 | 309 | reason.printTraceback(self._log_file) | 316 | reason.printTraceback(self._log_file) |
584 | 310 | self._logOopsFromFailure(reason) | 317 | self._logOopsFromFailure(reason) |
585 | 311 | status = CodeImportResultStatus.FAILURE | ||
586 | 312 | else: | 318 | else: |
587 | 313 | self._logger.info('Import succeeded.') | 319 | self._logger.info('Import succeeded.') |
588 | 314 | status = CodeImportResultStatus.SUCCESS | ||
589 | 315 | return self.finishJob(status) | 320 | return self.finishJob(status) |
590 | 316 | 321 | ||
591 | === modified file 'scripts/code-import-worker.py' | |||
592 | --- scripts/code-import-worker.py 2009-11-20 07:09:54 +0000 | |||
593 | +++ scripts/code-import-worker.py 2010-02-01 05:56:15 +0000 | |||
594 | @@ -19,6 +19,7 @@ | |||
595 | 19 | import _pythonpath | 19 | import _pythonpath |
596 | 20 | 20 | ||
597 | 21 | from optparse import OptionParser | 21 | from optparse import OptionParser |
598 | 22 | import sys | ||
599 | 22 | 23 | ||
600 | 23 | from bzrlib.transport import get_transport | 24 | from bzrlib.transport import get_transport |
601 | 24 | 25 | ||
602 | @@ -58,9 +59,9 @@ | |||
603 | 58 | source_details, | 59 | source_details, |
604 | 59 | get_transport(config.codeimport.foreign_tree_store), | 60 | get_transport(config.codeimport.foreign_tree_store), |
605 | 60 | get_default_bazaar_branch_store(), self.logger) | 61 | get_default_bazaar_branch_store(), self.logger) |
607 | 61 | import_worker.run() | 62 | return import_worker.run() |
608 | 62 | 63 | ||
609 | 63 | 64 | ||
610 | 64 | if __name__ == '__main__': | 65 | if __name__ == '__main__': |
611 | 65 | script = CodeImportWorker() | 66 | script = CodeImportWorker() |
613 | 66 | script.main() | 67 | sys.exit(script.main()) |
Hi,
This branch extends the contract between the code import 'worker' and 'monitor' scripts by specifying that an exit code of 2 means that the import was successful but didn't import any new revisions so there's no need to request a mirror of the import branch. I expect this to substantially reduce the load on the puller, as currently about half of all branches pulled are import branches with no new revisions.
I've had some pre-imp discussion with Tim, Jono and Aaron about this.
Cheers,
mwh