Merge lp:~thumper/launchpad/hg-imports-using-url into lp:launchpad/db-devel
- hg-imports-using-url
- Merge into db-devel
Status: | Merged |
---|---|
Merged at revision: | 8859 |
Proposed branch: | lp:~thumper/launchpad/hg-imports-using-url |
Merge into: | lp:launchpad/db-devel |
Prerequisite: | lp:~thumper/launchpad/imports-urls |
Diff against target: |
1027 lines (+372/-71) 22 files modified
lib/canonical/config/schema-lazr.conf (+5/-0) lib/lp/code/browser/codeimport.py (+26/-5) lib/lp/code/doc/codeimport-event.txt (+14/-0) lib/lp/code/doc/codeimport.txt (+46/-1) lib/lp/code/mail/codeimport.py (+2/-1) lib/lp/code/model/codeimport.py (+9/-4) lib/lp/code/model/codeimportevent.py (+2/-1) lib/lp/code/model/tests/test_codeimport.py (+29/-33) lib/lp/code/stories/codeimport/xx-admin-codeimport.txt (+22/-1) lib/lp/code/stories/codeimport/xx-codeimport-list.txt (+7/-2) lib/lp/code/stories/codeimport/xx-create-codeimport.txt (+28/-10) lib/lp/code/templates/branch-import-details.pt (+7/-1) lib/lp/code/templates/codeimport-new.pt (+16/-0) lib/lp/codehosting/codeimport/tests/servers.py (+21/-0) lib/lp/codehosting/codeimport/tests/test_worker.py (+55/-5) lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+22/-1) lib/lp/codehosting/codeimport/worker.py (+44/-2) lib/lp/testing/factory.py (+10/-3) scripts/code-import-worker.py (+4/-1) setup.py (+1/-0) utilities/sourcedeps.conf (+1/-0) versions.cfg (+1/-0) |
To merge this branch: | bzr merge lp:~thumper/launchpad/hg-imports-using-url |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Hudson-Doyle | Approve | ||
Review via email: mp+17187@code.launchpad.net |
Commit message
Description of the change
Tim Penhey (thumper) wrote : | # |
Tim Penhey (thumper) wrote : | # |
We are now ready to go.
Local import succeeded \o/
Michael Hudson-Doyle (mwhudson) wrote : | # |
Hi Tim,
Cool to see this arrive! Sadly, I'm not sure it can land yet, because
of the new sourcecode branch. Let's talk to a LOSA about that.
> === modified file 'lib/lp/
I think it would be good to create a Hg import in this test.
> --- lib/lp/
> +++ lib/lp/
> @@ -32,6 +32,7 @@
>
> >>> print_radio_
> ( ) Git
> + ( ) Mercurial
> (*) Subversion
> ( ) CVS
>
> @@ -66,21 +67,14 @@
> Requesting a Git import
> =======
>
> -The default foreign VCS type is Subversion.
> -
> - >>> browser.open("http://
> - >>> print_radio_
> - ( ) Git
> - (*) Subversion
> - ( ) CVS
> -
> The user is required to enter a project that the import is for,
> a name for the import branch, and a subversion branch location.
>
> + >>> browser.open("http://
> >>> browser.
> >>> browser.
> >>> browser.
> - >>> browser.
> + >>> browser.
> ... "git://
> >>> browser.
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -45,6 +45,12 @@
> </p>
> </tal:git-import>
>
> + <tal:hg-import condition=
> + <p>This branch is an import of the Mercurial repo at
I think I overheard some conversation about this, but it's not really
an import of the repo, but of the tip branch or whatever it's called
for Mercurial. Should we try to explain this?
> + <span tal:replace=
> + </p>
> + </tal:hg-import>
> +
> <tal:svn-import condition=
> <p id="svn-
> This branch is an import of the
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -8,6 +8,7 @@
> __all__ = [
> 'CVSServer',
> 'GitServer',
> + 'MercurialServer',
> 'SubversionServer',
> ]
>
> @@ -210,3 +211,23 @@
> builder.finish()
> finally:
> os.chdir(wd)
> +
> +
> +class MercurialServer
> +
> + def __init__(self, repo_url):
> + super(Mercurial
> + self.repo_url = repo_url
> +
> + def makeRepo(self, tree_contents):
> + from mercurial.ui import ui
> + from mercurial.localrepo import localreposit...
Preview Diff
1 | === modified file 'lib/canonical/config/schema-lazr.conf' |
2 | --- lib/canonical/config/schema-lazr.conf 2009-11-17 11:27:51 +0000 |
3 | +++ lib/canonical/config/schema-lazr.conf 2010-01-13 02:53:16 +0000 |
4 | @@ -402,6 +402,11 @@ |
5 | default_interval_git: 21600 |
6 | |
7 | # The default value of the update interval of a code import from |
8 | +# Mercurial, in seconds. |
9 | +# datatype: integer |
10 | +default_interval_hg: 21600 |
11 | + |
12 | +# The default value of the update interval of a code import from |
13 | # CVS, in seconds. |
14 | # datatype: integer |
15 | default_interval_cvs: 43200 |
16 | |
17 | === modified file 'lib/lp/code/browser/codeimport.py' |
18 | --- lib/lp/code/browser/codeimport.py 2010-01-13 02:53:14 +0000 |
19 | +++ lib/lp/code/browser/codeimport.py 2010-01-13 02:53:16 +0000 |
20 | @@ -213,7 +213,7 @@ |
21 | git_repo_url = URIField( |
22 | title=_("Repo URL"), required=False, |
23 | description=_( |
24 | - "The URL of the git repository. The MASTER branch will be " |
25 | + "The URL of the git repository. The HEAD branch will be " |
26 | "imported."), |
27 | allowed_schemes=["git"], |
28 | allow_userinfo=False, # Only anonymous access is supported. |
29 | @@ -222,6 +222,18 @@ |
30 | allow_fragment=False, |
31 | trailing_slash=False) |
32 | |
33 | + hg_repo_url = URIField( |
34 | + title=_("Repo URL"), required=False, |
35 | + description=_( |
36 | + "The URL of the Mercurial repository. The tip branch will be " |
37 | + "imported."), |
38 | + allowed_schemes=["http", "https"], |
39 | + allow_userinfo=False, # Only anonymous access is supported. |
40 | + allow_port=True, |
41 | + allow_query=False, # Query makes no sense in Mercurial |
42 | + allow_fragment=False, # Fragment makes no sense in Mercurial |
43 | + trailing_slash=False) # See http://launchpad.net/bugs/56357. |
44 | + |
45 | branch_name = copy_field( |
46 | IBranch['name'], |
47 | __name__='branch_name', |
48 | @@ -258,16 +270,18 @@ |
49 | # display them separately in the form. |
50 | soup = BeautifulSoup(self.widgets['rcs_type']()) |
51 | fields = soup.findAll('input') |
52 | - [cvs_button, svn_button, git_button, empty_marker] = [ |
53 | + [cvs_button, svn_button, git_button, hg_button, empty_marker] = [ |
54 | field for field in fields |
55 | - if field.get('value') in ['CVS', 'BZR_SVN', 'GIT', '1']] |
56 | + if field.get('value') in ['CVS', 'BZR_SVN', 'GIT', 'HG', '1']] |
57 | cvs_button['onclick'] = 'updateWidgets()' |
58 | svn_button['onclick'] = 'updateWidgets()' |
59 | git_button['onclick'] = 'updateWidgets()' |
60 | + hg_button['onclick'] = 'updateWidgets()' |
61 | # The following attributes are used only in the page template. |
62 | self.rcs_type_cvs = str(cvs_button) |
63 | self.rcs_type_svn = str(svn_button) |
64 | self.rcs_type_git = str(git_button) |
65 | + self.rcs_type_hg = str(hg_button) |
66 | self.rcs_type_emptymarker = str(empty_marker) |
67 | |
68 | def _getImportLocation(self, data): |
69 | @@ -279,6 +293,8 @@ |
70 | return None, None, data.get('svn_branch_url') |
71 | elif rcs_type == RevisionControlSystems.GIT: |
72 | return None, None, data.get('git_repo_url') |
73 | + elif rcs_type == RevisionControlSystems.HG: |
74 | + return None, None, data.get('hg_repo_url') |
75 | else: |
76 | raise AssertionError( |
77 | 'Unexpected revision control type %r.' % rcs_type) |
78 | @@ -379,6 +395,9 @@ |
79 | elif rcs_type == RevisionControlSystems.GIT: |
80 | self._validateURL( |
81 | data.get('git_repo_url'), field_name='git_repo_url') |
82 | + elif rcs_type == RevisionControlSystems.HG: |
83 | + self._validateURL( |
84 | + data.get('hg_repo_url'), field_name='hg_repo_url') |
85 | else: |
86 | raise AssertionError( |
87 | 'Unexpected revision control type %r.' % rcs_type) |
88 | @@ -469,7 +488,8 @@ |
89 | self.form_fields = self.form_fields.omit('url') |
90 | elif self.code_import.rcs_type in (RevisionControlSystems.SVN, |
91 | RevisionControlSystems.BZR_SVN, |
92 | - RevisionControlSystems.GIT): |
93 | + RevisionControlSystems.GIT, |
94 | + RevisionControlSystems.HG): |
95 | self.form_fields = self.form_fields.omit( |
96 | 'cvs_root', 'cvs_module') |
97 | else: |
98 | @@ -503,7 +523,8 @@ |
99 | self.code_import) |
100 | elif self.code_import.rcs_type in (RevisionControlSystems.SVN, |
101 | RevisionControlSystems.BZR_SVN, |
102 | - RevisionControlSystems.GIT): |
103 | + RevisionControlSystems.GIT, |
104 | + RevisionControlSystems.HG): |
105 | self._validateURL(data.get('url'), self.code_import) |
106 | else: |
107 | raise AssertionError('Unknown rcs_type for code import.') |
108 | |
109 | === modified file 'lib/lp/code/doc/codeimport-event.txt' |
110 | --- lib/lp/code/doc/codeimport-event.txt 2010-01-13 02:53:14 +0000 |
111 | +++ lib/lp/code/doc/codeimport-event.txt 2010-01-13 02:53:16 +0000 |
112 | @@ -165,6 +165,20 @@ |
113 | URL u'git://git.example.org/main.git' |
114 | |
115 | |
116 | +And for a Mercurial import, the hg details are recorded. |
117 | + |
118 | + >>> hg_import = factory.makeCodeImport( |
119 | + ... hg_repo_url='http://hg.example.org/main') |
120 | + >>> hg_create_event = event_set.newCreate(hg_import, nopriv) |
121 | + >>> print_items(hg_create_event) |
122 | + CODE_IMPORT <muted> |
123 | + OWNER ... |
124 | + REVIEW_STATUS u'REVIEWED' |
125 | + ASSIGNEE None |
126 | + UPDATE_INTERVAL None |
127 | + URL u'http://hg.example.org/main' |
128 | + |
129 | + |
130 | == MODIFY == |
131 | |
132 | When a code import is modified, the ICodeImportEventSet utility should |
133 | |
134 | === modified file 'lib/lp/code/doc/codeimport.txt' |
135 | --- lib/lp/code/doc/codeimport.txt 2010-01-13 02:53:14 +0000 |
136 | +++ lib/lp/code/doc/codeimport.txt 2010-01-13 02:53:16 +0000 |
137 | @@ -197,6 +197,33 @@ |
138 | >>> git_import == existing_import |
139 | True |
140 | |
141 | +Import from Mercurial |
142 | ++++++++++++++++++++++ |
143 | + |
144 | +Code imports from Mercurial specify the URL used with "hg clone" to |
145 | +retrieve the branch to import. |
146 | + |
147 | + >>> hg = RevisionControlSystems.HG |
148 | + >>> hg_url = 'http://hg.example.com/metallic' |
149 | + >>> hg_import = code_import_set.new( |
150 | + ... registrant=nopriv, product=product, branch_name='trunk-hg', |
151 | + ... rcs_type=hg, url=hg_url) |
152 | + >>> verifyObject(ICodeImport, removeSecurityProxy(hg_import)) |
153 | + True |
154 | + |
155 | +Creating a CodeImport object creates a corresponding CodeImportEvent. |
156 | + |
157 | + >>> hg_events = event_set.getEventsForCodeImport(hg_import) |
158 | + >>> [event.event_type.name for event in hg_events] |
159 | + ['CREATE'] |
160 | + |
161 | +The CodeImportSet is also able to retrieve the code imports with the |
162 | +specified hg repo url. |
163 | + |
164 | + >>> existing_import = code_import_set.getByURL(url=hg_url) |
165 | + >>> hg_import == existing_import |
166 | + True |
167 | + |
168 | |
169 | Updating code import details |
170 | ---------------------------- |
171 | @@ -316,6 +343,8 @@ |
172 | ... seconds=config.codeimport.default_interval_subversion) |
173 | >>> default_interval_git = timedelta( |
174 | ... seconds=config.codeimport.default_interval_git) |
175 | + >>> default_interval_hg = timedelta( |
176 | + ... seconds=config.codeimport.default_interval_hg) |
177 | |
178 | By default, code imports are created with an unspecified update interval. |
179 | |
180 | @@ -345,6 +374,12 @@ |
181 | >>> git_import.effective_update_interval |
182 | datetime.timedelta(0, 21600) |
183 | |
184 | + >>> default_interval_hg |
185 | + datetime.timedelta(0, 21600) |
186 | + >>> hg_import.effective_update_interval |
187 | + datetime.timedelta(0, 21600) |
188 | + |
189 | + |
190 | If the update interval is set, then it overrides the default value. |
191 | |
192 | As explained in the "Modify CodeImports" section, the interface does not allow |
193 | @@ -477,7 +512,7 @@ |
194 | instead of: |
195 | hello from :pserver:anonymous@cvs.example.com:/cvsroot |
196 | |
197 | -And for Git. |
198 | +For Git. |
199 | |
200 | >>> data = {'url': 'git://git.example.com/goodbye.git'} |
201 | >>> modify_event = git_import.updateFromData(data, nopriv) |
202 | @@ -499,6 +534,16 @@ |
203 | instead of: |
204 | svn://svn.example.com/for-bzr-svn/trunk |
205 | |
206 | +And for Mercurial. |
207 | + |
208 | + >>> data = {'url': 'http://metal.example.com/byebye.hg'} |
209 | + >>> modify_event = hg_import.updateFromData(data, nopriv) |
210 | + >>> print make_email_body_for_code_import_update( |
211 | + ... hg_import, modify_event, None) |
212 | + ~no-priv/firefox/trunk-hg is now being imported from: |
213 | + http://metal.example.com/byebye.hg |
214 | + instead of: |
215 | + http://hg.example.com/metallic |
216 | |
217 | In addition, updateFromData can be used to set the branch whiteboard, |
218 | which is also described in the email that is sent. |
219 | |
220 | === modified file 'lib/lp/code/mail/codeimport.py' |
221 | --- lib/lp/code/mail/codeimport.py 2010-01-13 02:53:14 +0000 |
222 | +++ lib/lp/code/mail/codeimport.py 2010-01-13 02:53:16 +0000 |
223 | @@ -97,7 +97,8 @@ |
224 | "\ninstead of:\n" + old_details) |
225 | elif code_import.rcs_type in (RevisionControlSystems.SVN, |
226 | RevisionControlSystems.BZR_SVN, |
227 | - RevisionControlSystems.GIT): |
228 | + RevisionControlSystems.GIT, |
229 | + RevisionControlSystems.HG): |
230 | if CodeImportEventDataType.OLD_URL in event_data: |
231 | old_url = event_data[CodeImportEventDataType.OLD_URL] |
232 | body.append( |
233 | |
234 | === modified file 'lib/lp/code/model/codeimport.py' |
235 | --- lib/lp/code/model/codeimport.py 2010-01-13 02:53:13 +0000 |
236 | +++ lib/lp/code/model/codeimport.py 2010-01-13 02:53:16 +0000 |
237 | @@ -106,6 +106,8 @@ |
238 | config.codeimport.default_interval_subversion, |
239 | RevisionControlSystems.GIT: |
240 | config.codeimport.default_interval_git, |
241 | + RevisionControlSystems.HG: |
242 | + config.codeimport.default_interval_hg, |
243 | } |
244 | seconds = default_interval_dict[self.rcs_type] |
245 | return timedelta(seconds=seconds) |
246 | @@ -122,7 +124,8 @@ |
247 | elif self.rcs_type in ( |
248 | RevisionControlSystems.SVN, |
249 | RevisionControlSystems.GIT, |
250 | - RevisionControlSystems.BZR_SVN): |
251 | + RevisionControlSystems.BZR_SVN, |
252 | + RevisionControlSystems.HG): |
253 | return self.url |
254 | else: |
255 | raise AssertionError( |
256 | @@ -218,7 +221,8 @@ |
257 | assert url is None |
258 | elif rcs_type in (RevisionControlSystems.SVN, |
259 | RevisionControlSystems.BZR_SVN, |
260 | - RevisionControlSystems.GIT): |
261 | + RevisionControlSystems.GIT, |
262 | + RevisionControlSystems.HG): |
263 | assert cvs_root is None and cvs_module is None |
264 | assert url is not None |
265 | else: |
266 | @@ -226,8 +230,9 @@ |
267 | "Don't know how to sanity check source details for unknown " |
268 | "rcs_type %s"%rcs_type) |
269 | if review_status is None: |
270 | - # Auto approve git imports. |
271 | - if rcs_type == RevisionControlSystems.GIT: |
272 | + # Auto approve git and hg imports. |
273 | + if rcs_type in ( |
274 | + RevisionControlSystems.GIT, RevisionControlSystems.HG): |
275 | review_status = CodeImportReviewStatus.REVIEWED |
276 | else: |
277 | review_status = CodeImportReviewStatus.NEW |
278 | |
279 | === modified file 'lib/lp/code/model/codeimportevent.py' |
280 | --- lib/lp/code/model/codeimportevent.py 2010-01-13 02:53:14 +0000 |
281 | +++ lib/lp/code/model/codeimportevent.py 2010-01-13 02:53:16 +0000 |
282 | @@ -258,7 +258,8 @@ |
283 | """Yield key-value tuples describing the source of the import.""" |
284 | if code_import.rcs_type in (RevisionControlSystems.SVN, |
285 | RevisionControlSystems.BZR_SVN, |
286 | - RevisionControlSystems.GIT): |
287 | + RevisionControlSystems.GIT, |
288 | + RevisionControlSystems.HG): |
289 | yield 'URL', code_import.url |
290 | elif code_import.rcs_type == RevisionControlSystems.CVS: |
291 | yield 'CVS_ROOT', code_import.cvs_root |
292 | |
293 | === modified file 'lib/lp/code/model/tests/test_codeimport.py' |
294 | --- lib/lp/code/model/tests/test_codeimport.py 2010-01-13 02:53:14 +0000 |
295 | +++ lib/lp/code/model/tests/test_codeimport.py 2010-01-13 02:53:16 +0000 |
296 | @@ -24,26 +24,17 @@ |
297 | from lp.code.interfaces.codeimportjob import ICodeImportJobWorkflow |
298 | from lp.testing import ( |
299 | login, login_person, logout, TestCaseWithFactory, time_counter) |
300 | -from lp.testing.factory import LaunchpadObjectFactory |
301 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
302 | from canonical.testing import ( |
303 | DatabaseFunctionalLayer, LaunchpadFunctionalLayer, |
304 | LaunchpadZopelessLayer) |
305 | |
306 | |
307 | -class TestCodeImportCreation(unittest.TestCase): |
308 | +class TestCodeImportCreation(TestCaseWithFactory): |
309 | """Test the creation of CodeImports.""" |
310 | |
311 | layer = DatabaseFunctionalLayer |
312 | |
313 | - def setUp(self): |
314 | - unittest.TestCase.setUp(self) |
315 | - self.factory = LaunchpadObjectFactory() |
316 | - login('no-priv@canonical.com') |
317 | - |
318 | - def tearDown(self): |
319 | - logout() |
320 | - |
321 | def test_new_svn_import(self): |
322 | """A new subversion code import should have NEW status.""" |
323 | code_import = CodeImportSet().new( |
324 | @@ -56,7 +47,7 @@ |
325 | CodeImportReviewStatus.NEW, |
326 | code_import.review_status) |
327 | # No job is created for the import. |
328 | - self.assertTrue(code_import.import_job is None) |
329 | + self.assertIs(None, code_import.import_job) |
330 | |
331 | def test_reviewed_svn_import(self): |
332 | """A specific review status can be set for a new import.""" |
333 | @@ -71,7 +62,7 @@ |
334 | CodeImportReviewStatus.REVIEWED, |
335 | code_import.review_status) |
336 | # A job is created for the import. |
337 | - self.assertTrue(code_import.import_job is not None) |
338 | + self.assertIsNot(None, code_import.import_job) |
339 | |
340 | def test_new_cvs_import(self): |
341 | """A new CVS code import should have NEW status.""" |
342 | @@ -86,7 +77,7 @@ |
343 | CodeImportReviewStatus.NEW, |
344 | code_import.review_status) |
345 | # No job is created for the import. |
346 | - self.assertTrue(code_import.import_job is None) |
347 | + self.assertIs(None, code_import.import_job) |
348 | |
349 | def test_reviewed_cvs_import(self): |
350 | """A specific review status can be set for a new import.""" |
351 | @@ -102,7 +93,7 @@ |
352 | CodeImportReviewStatus.REVIEWED, |
353 | code_import.review_status) |
354 | # A job is created for the import. |
355 | - self.assertTrue(code_import.import_job is not None) |
356 | + self.assertIsNot(None, code_import.import_job) |
357 | |
358 | def test_git_import_reviewed(self): |
359 | """A new git import is always reviewed by default.""" |
360 | @@ -117,23 +108,29 @@ |
361 | CodeImportReviewStatus.REVIEWED, |
362 | code_import.review_status) |
363 | # A job is created for the import. |
364 | - self.assertTrue(code_import.import_job is not None) |
365 | - |
366 | - |
367 | -class TestCodeImportDeletion(unittest.TestCase): |
368 | + self.assertIsNot(None, code_import.import_job) |
369 | + |
370 | + def test_hg_import_reviewed(self): |
371 | + """A new hg import is always reviewed by default.""" |
372 | + code_import = CodeImportSet().new( |
373 | + registrant=self.factory.makePerson(), |
374 | + product=self.factory.makeProduct(), |
375 | + branch_name='imported', |
376 | + rcs_type=RevisionControlSystems.HG, |
377 | + url=self.factory.getUniqueURL(), |
378 | + review_status=None) |
379 | + self.assertEqual( |
380 | + CodeImportReviewStatus.REVIEWED, |
381 | + code_import.review_status) |
382 | + # No job is created for the import. |
383 | + self.assertIsNot(None, code_import.import_job) |
384 | + |
385 | + |
386 | +class TestCodeImportDeletion(TestCaseWithFactory): |
387 | """Test the deletion of CodeImports.""" |
388 | |
389 | layer = LaunchpadFunctionalLayer |
390 | |
391 | - def setUp(self): |
392 | - unittest.TestCase.setUp(self) |
393 | - self.factory = LaunchpadObjectFactory() |
394 | - # Log in a vcs import member. |
395 | - login('david.allouche@canonical.com') |
396 | - |
397 | - def tearDown(self): |
398 | - logout() |
399 | - |
400 | def test_delete(self): |
401 | """Ensure CodeImport objects can be deleted via CodeImportSet.""" |
402 | code_import = self.factory.makeCodeImport() |
403 | @@ -302,15 +299,13 @@ |
404 | CodeImportReviewStatus.FAILING, code_import.review_status) |
405 | |
406 | |
407 | -class TestCodeImportResultsAttribute(unittest.TestCase): |
408 | +class TestCodeImportResultsAttribute(TestCaseWithFactory): |
409 | """Test the results attribute of a CodeImport.""" |
410 | |
411 | layer = LaunchpadFunctionalLayer |
412 | |
413 | def setUp(self): |
414 | - unittest.TestCase.setUp(self) |
415 | - login('no-priv@canonical.com') |
416 | - self.factory = LaunchpadObjectFactory() |
417 | + TestCaseWithFactory.setUp(self) |
418 | self.code_import = self.factory.makeCodeImport() |
419 | |
420 | def tearDown(self): |
421 | @@ -534,7 +529,7 @@ |
422 | def make_active_import(factory, project_name=None, product_name=None, |
423 | branch_name=None, svn_branch_url=None, |
424 | cvs_root=None, cvs_module=None, git_repo_url=None, |
425 | - last_update=None, rcs_type=None): |
426 | + hg_repo_url=None, last_update=None, rcs_type=None): |
427 | """Make a new CodeImport for a new Product, maybe in a new Project. |
428 | |
429 | The import will be 'active' in the sense used by |
430 | @@ -549,7 +544,8 @@ |
431 | code_import = factory.makeCodeImport( |
432 | product=product, branch_name=branch_name, |
433 | svn_branch_url=svn_branch_url, cvs_root=cvs_root, |
434 | - cvs_module=cvs_module, git_repo_url=git_repo_url, rcs_type=rcs_type) |
435 | + cvs_module=cvs_module, git_repo_url=git_repo_url, |
436 | + hg_repo_url=hg_repo_url, rcs_type=None) |
437 | make_import_active(factory, code_import, last_update) |
438 | return code_import |
439 | |
440 | |
441 | === modified file 'lib/lp/code/stories/codeimport/xx-admin-codeimport.txt' |
442 | --- lib/lp/code/stories/codeimport/xx-admin-codeimport.txt 2010-01-13 02:53:14 +0000 |
443 | +++ lib/lp/code/stories/codeimport/xx-admin-codeimport.txt 2010-01-13 02:53:16 +0000 |
444 | @@ -32,6 +32,12 @@ |
445 | ... git_repo_url="git://git.example.org/fooix") |
446 | >>> git_import_location = str(canonical_url(git_import.branch)) |
447 | >>> git_import_branch_unique_name = git_import.branch.unique_name |
448 | + |
449 | + >>> hg_import = factory.makeCodeImport( |
450 | + ... hg_repo_url="http://hg.example.org/bar") |
451 | + >>> hg_import_location = str(canonical_url(hg_import.branch)) |
452 | + >>> hg_import_branch_unique_name = hg_import.branch.unique_name |
453 | + |
454 | >>> logout() |
455 | |
456 | >>> import_browser = setupBrowser( |
457 | @@ -97,6 +103,12 @@ |
458 | >>> print_form_fields(import_browser) |
459 | field.url: git://git.example.org/fooix |
460 | |
461 | + >>> import_browser.open(hg_import_location) |
462 | + >>> import_browser.getLink('Edit import source or review import').click() |
463 | + >>> print_form_fields(import_browser) |
464 | + field.url: http://hg.example.org/bar |
465 | + |
466 | + |
467 | Editing the import location |
468 | +++++++++++++++++++++++++++ |
469 | |
470 | @@ -135,7 +147,7 @@ |
471 | ... print extract_text(message) |
472 | The code import has been updated. |
473 | |
474 | -and Git imports. |
475 | +Git imports, |
476 | |
477 | >>> import_browser.open(git_import_location + '/+edit-import') |
478 | >>> import_browser.getControl('URL').value = \ |
479 | @@ -145,6 +157,15 @@ |
480 | ... print extract_text(message) |
481 | The code import has been updated. |
482 | |
483 | +and Mercurial imports. |
484 | + |
485 | + >>> import_browser.open(hg_import_location + '/+edit-import') |
486 | + >>> import_browser.getControl('URL').value = \ |
487 | + ... 'http://metal.example.org/bar' |
488 | + >>> import_browser.getControl('Update').click() |
489 | + >>> for message in get_feedback_messages(import_browser.contents): |
490 | + ... print extract_text(message) |
491 | + The code import has been updated. |
492 | |
493 | Approving an import |
494 | +++++++++++++++++++ |
495 | |
496 | === modified file 'lib/lp/code/stories/codeimport/xx-codeimport-list.txt' |
497 | --- lib/lp/code/stories/codeimport/xx-codeimport-list.txt 2009-12-08 04:31:34 +0000 |
498 | +++ lib/lp/code/stories/codeimport/xx-codeimport-list.txt 2010-01-13 02:53:16 +0000 |
499 | @@ -34,14 +34,18 @@ |
500 | ... factory, product_name="herproj", branch_name="master", |
501 | ... git_repo_url="git://git.example.org/herproj", |
502 | ... last_update=datetime.datetime(2007, 1, 4, tzinfo=pytz.UTC)) |
503 | + >>> active_hg_import = make_active_import( |
504 | + ... factory, product_name="hg-proj", branch_name="tip", |
505 | + ... hg_repo_url="http://hg.example.org/proj", |
506 | + ... last_update=datetime.datetime(2007, 1, 5, tzinfo=pytz.UTC)) |
507 | >>> len(list(code_import_set.getActiveImports())) |
508 | - 4 |
509 | + 5 |
510 | >>> logout() |
511 | |
512 | The page is linked to from the "$N imported branches" text. |
513 | |
514 | >>> browser.open('http://code.launchpad.dev') |
515 | - >>> browser.getLink('4 imported branches').click() |
516 | + >>> browser.getLink('5 imported branches').click() |
517 | >>> print browser.title |
518 | Available code imports |
519 | |
520 | @@ -54,6 +58,7 @@ |
521 | >>> print_import_table() |
522 | Project Branch Name Source Details Last Updated |
523 | herproj master git://git.example.org/herproj 2007-01-04 |
524 | + hg-proj tip http://hg.example.org/proj 2007-01-05 |
525 | hisproj main :pserver:anon@example.com:/cvs hisproj 2007-01-03 |
526 | myproject trunk http://example.com/svn/myproject/trunk 2007-01-01 |
527 | ourproject trunk http://example.com/bzr-svn/myproject/trunk 2007-01-02 |
528 | |
529 | === modified file 'lib/lp/code/stories/codeimport/xx-create-codeimport.txt' |
530 | --- lib/lp/code/stories/codeimport/xx-create-codeimport.txt 2010-01-13 02:53:14 +0000 |
531 | +++ lib/lp/code/stories/codeimport/xx-create-codeimport.txt 2010-01-13 02:53:16 +0000 |
532 | @@ -32,6 +32,7 @@ |
533 | |
534 | >>> print_radio_button_field(browser.contents, "rcs_type") |
535 | ( ) Git |
536 | + ( ) Mercurial |
537 | (*) Subversion |
538 | ( ) CVS |
539 | |
540 | @@ -63,24 +64,18 @@ |
541 | >>> print svn_span['title'] |
542 | Subversion via bzr-svn |
543 | |
544 | + |
545 | Requesting a Git import |
546 | ======================= |
547 | |
548 | -The default foreign VCS type is Subversion. |
549 | - |
550 | - >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
551 | - >>> print_radio_button_field(browser.contents, "rcs_type") |
552 | - ( ) Git |
553 | - (*) Subversion |
554 | - ( ) CVS |
555 | - |
556 | The user is required to enter a project that the import is for, |
557 | a name for the import branch, and a subversion branch location. |
558 | |
559 | + >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
560 | >>> browser.getControl('Project').value = "firefox" |
561 | >>> browser.getControl('Branch Name').value = "git-import" |
562 | >>> browser.getControl('Git').click() |
563 | - >>> browser.getControl('Repo URL').value = ( |
564 | + >>> browser.getControl('Repo URL', index=0).value = ( |
565 | ... "git://example.com/firefox.git") |
566 | >>> browser.getControl('Request Import').click() |
567 | |
568 | @@ -88,11 +83,34 @@ |
569 | |
570 | >>> print extract_text(find_tag_by_id(browser.contents, "import-details")) |
571 | Import Status: Reviewed |
572 | - This branch is an import of the MASTER branch from the Git repo at |
573 | + This branch is an import of the HEAD branch of the Git repository at |
574 | git://example.com/firefox.git. |
575 | The next import is scheduled to run as soon as possible. |
576 | |
577 | |
578 | +Requesting a Mercurial import |
579 | +======================= |
580 | + |
581 | +The user is required to enter a project that the import is for, |
582 | +a name for the import branch, and a mercurial branch location. |
583 | + |
584 | + >>> browser.open("http://code.launchpad.dev/+code-imports/+new") |
585 | + >>> browser.getControl('Project').value = "firefox" |
586 | + >>> browser.getControl('Branch Name').value = "hg-import" |
587 | + >>> browser.getControl('Mercurial').click() |
588 | + >>> browser.getControl('Repo URL', index=1).value = ( |
589 | + ... "http://example.com/firefox.hg") |
590 | + >>> browser.getControl('Request Import').click() |
591 | + |
592 | +When the user clicks continue, the approved import branch is created |
593 | + |
594 | + >>> print extract_text(find_tag_by_id(browser.contents, "import-details")) |
595 | + Import Status: Reviewed |
596 | + This branch is an import of the tip branch of the Mercurial repository at |
597 | + http://example.com/firefox.hg. |
598 | + The next import is scheduled to run as soon as possible. |
599 | + |
600 | + |
601 | Requesting a CVS import |
602 | ======================= |
603 | |
604 | |
605 | === modified file 'lib/lp/code/templates/branch-import-details.pt' |
606 | --- lib/lp/code/templates/branch-import-details.pt 2010-01-13 02:53:14 +0000 |
607 | +++ lib/lp/code/templates/branch-import-details.pt 2010-01-13 02:53:16 +0000 |
608 | @@ -40,11 +40,17 @@ |
609 | </div> |
610 | |
611 | <tal:git-import condition="code_import/rcs_type/enumvalue:GIT"> |
612 | - <p>This branch is an import of the MASTER branch from the Git repo at |
613 | + <p>This branch is an import of the HEAD branch of the Git repository at |
614 | <span tal:replace="code_import/url" />. |
615 | </p> |
616 | </tal:git-import> |
617 | |
618 | + <tal:hg-import condition="code_import/rcs_type/enumvalue:HG"> |
619 | + <p>This branch is an import of the tip branch of the Mercurial repository at |
620 | + <span tal:replace="code_import/url" />. |
621 | + </p> |
622 | + </tal:hg-import> |
623 | + |
624 | <tal:svn-import condition="view/is_svn_import"> |
625 | <p id="svn-import-details"> |
626 | This branch is an import of the |
627 | |
628 | === modified file 'lib/lp/code/templates/codeimport-new.pt' |
629 | --- lib/lp/code/templates/codeimport-new.pt 2009-12-08 02:32:03 +0000 |
630 | +++ lib/lp/code/templates/codeimport-new.pt 2010-01-13 02:53:16 +0000 |
631 | @@ -62,6 +62,20 @@ |
632 | <tr> |
633 | <td> |
634 | <label> |
635 | + <input tal:replace="structure view/rcs_type_hg" /> |
636 | + Mercurial |
637 | + </label> |
638 | + <table class="importdetails"> |
639 | + <tal:widget define="widget nocall:view/widgets/hg_repo_url"> |
640 | + <metal:block use-macro="context/@@launchpad_form/widget_row" /> |
641 | + </tal:widget> |
642 | + </table> |
643 | + </td> |
644 | + </tr> |
645 | + |
646 | + <tr> |
647 | + <td> |
648 | + <label> |
649 | <input tal:replace="structure view/rcs_type_svn" /> |
650 | Subversion |
651 | </label> |
652 | @@ -108,6 +122,8 @@ |
653 | } |
654 | // GIT |
655 | updateField(form['field.git_repo_url'], rcs_type == 'GIT'); |
656 | + // HG |
657 | + updateField(form['field.hg_repo_url'], rcs_type == 'HG'); |
658 | // CVS |
659 | updateField(form['field.cvs_root'], rcs_type == 'CVS'); |
660 | updateField(form['field.cvs_module'], rcs_type == 'CVS'); |
661 | |
662 | === modified file 'lib/lp/codehosting/codeimport/tests/servers.py' |
663 | --- lib/lp/codehosting/codeimport/tests/servers.py 2009-12-04 04:08:12 +0000 |
664 | +++ lib/lp/codehosting/codeimport/tests/servers.py 2010-01-13 02:53:16 +0000 |
665 | @@ -8,6 +8,7 @@ |
666 | __all__ = [ |
667 | 'CVSServer', |
668 | 'GitServer', |
669 | + 'MercurialServer', |
670 | 'SubversionServer', |
671 | ] |
672 | |
673 | @@ -210,3 +211,23 @@ |
674 | builder.finish() |
675 | finally: |
676 | os.chdir(wd) |
677 | + |
678 | + |
679 | +class MercurialServer(Server): |
680 | + |
681 | + def __init__(self, repo_url): |
682 | + super(MercurialServer, self).__init__() |
683 | + self.repo_url = repo_url |
684 | + |
685 | + def makeRepo(self, tree_contents): |
686 | + from mercurial.ui import ui |
687 | + from mercurial.localrepo import localrepository |
688 | + repo = localrepository(ui(), self.repo_url, create=1) |
689 | + for filename, contents in tree_contents: |
690 | + f = open(os.path.join(self.repo_url, filename), 'w') |
691 | + try: |
692 | + f.write(contents) |
693 | + finally: |
694 | + f.close() |
695 | + repo.add([filename]) |
696 | + repo.commit(text='<The commit message>', user='jane Foo <joe@foo.com>') |
697 | |
698 | === modified file 'lib/lp/codehosting/codeimport/tests/test_worker.py' |
699 | --- lib/lp/codehosting/codeimport/tests/test_worker.py 2010-01-13 02:53:14 +0000 |
700 | +++ lib/lp/codehosting/codeimport/tests/test_worker.py 2010-01-13 02:53:16 +0000 |
701 | @@ -9,7 +9,6 @@ |
702 | import os |
703 | import shutil |
704 | import subprocess |
705 | -import sys |
706 | import tempfile |
707 | import time |
708 | import unittest |
709 | @@ -32,10 +31,10 @@ |
710 | from lp.codehosting import load_optional_plugin |
711 | from lp.codehosting.codeimport.worker import ( |
712 | BazaarBranchStore, BzrSvnImportWorker, CSCVSImportWorker, |
713 | - ForeignTreeStore, GitImportWorker, ImportDataStore, ImportWorker, |
714 | - get_default_bazaar_branch_store) |
715 | + ForeignTreeStore, GitImportWorker, HgImportWorker, ImportDataStore, |
716 | + ImportWorker, get_default_bazaar_branch_store) |
717 | from lp.codehosting.codeimport.tests.servers import ( |
718 | - CVSServer, GitServer, SubversionServer) |
719 | + CVSServer, GitServer, MercurialServer, SubversionServer) |
720 | from lp.codehosting.tests.helpers import ( |
721 | create_branch_with_one_revision) |
722 | from lp.testing.factory import LaunchpadObjectFactory |
723 | @@ -822,7 +821,7 @@ |
724 | # import should be rejected. |
725 | args = {'rcstype': self.rcstype} |
726 | reference_url = self.createBranchReference() |
727 | - if self.rcstype in ('git', 'bzr-svn'): |
728 | + if self.rcstype in ('git', 'bzr-svn', 'hg'): |
729 | args['url'] = reference_url |
730 | else: |
731 | raise AssertionError("unexpected rcs_type %r" % self.rcs_type) |
732 | @@ -886,6 +885,57 @@ |
733 | rcstype='git', url=repository_path) |
734 | |
735 | |
736 | +class TestMercurialImport(WorkerTest, TestActualImportMixin, |
737 | + PullingImportWorkerTests): |
738 | + |
739 | + rcstype = 'hg' |
740 | + |
741 | + def setUp(self): |
742 | + super(TestMercurialImport, self).setUp() |
743 | + load_optional_plugin('hg') |
744 | + self.setUpImport() |
745 | + |
746 | + def tearDown(self): |
747 | + """Clear bzr-hg's cache of sqlite connections. |
748 | + |
749 | + This is rather obscure: different test runs tend to re-use the same |
750 | + paths on disk, which confuses bzr-hg as it keeps a cache that maps |
751 | + paths to database connections, which happily returns the connection |
752 | + that corresponds to a path that no longer exists. |
753 | + """ |
754 | + from bzrlib.plugins.hg.idmap import mapdbs |
755 | + mapdbs().clear() |
756 | + WorkerTest.tearDown(self) |
757 | + |
758 | + def makeImportWorker(self, source_details): |
759 | + """Make a new `ImportWorker`.""" |
760 | + return HgImportWorker( |
761 | + source_details, self.get_transport('import_data'), |
762 | + self.bazaar_store, logging.getLogger()) |
763 | + |
764 | + def makeForeignCommit(self, source_details): |
765 | + """Change the foreign tree, generating exactly one commit.""" |
766 | + from mercurial.ui import ui |
767 | + from mercurial.localrepo import localrepository |
768 | + repo = localrepository(ui(), source_details.url) |
769 | + repo.commit(text="hello world!", user="Jane Random Hacker", force=1) |
770 | + self.foreign_commit_count += 1 |
771 | + |
772 | + def makeSourceDetails(self, branch_name, files): |
773 | + """Make a Mercurial `CodeImportSourceDetails` pointing at a real repo. |
774 | + """ |
775 | + repository_path = self.makeTemporaryDirectory() |
776 | + hg_server = MercurialServer(repository_path) |
777 | + hg_server.setUp() |
778 | + self.addCleanup(hg_server.tearDown) |
779 | + |
780 | + hg_server.makeRepo(files) |
781 | + self.foreign_commit_count = 1 |
782 | + |
783 | + return self.factory.makeCodeImportSourceDetails( |
784 | + rcstype='hg', url=repository_path) |
785 | + |
786 | + |
787 | class TestBzrSvnImport(WorkerTest, SubversionImportHelpers, |
788 | TestActualImportMixin, PullingImportWorkerTests): |
789 | |
790 | |
791 | === modified file 'lib/lp/codehosting/codeimport/tests/test_workermonitor.py' |
792 | --- lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-01-13 02:53:14 +0000 |
793 | +++ lib/lp/codehosting/codeimport/tests/test_workermonitor.py 2010-01-13 02:53:16 +0000 |
794 | @@ -43,7 +43,7 @@ |
795 | CodeImportWorkerMonitor, CodeImportWorkerMonitorProtocol, ExitQuietly, |
796 | read_only_transaction) |
797 | from lp.codehosting.codeimport.tests.servers import ( |
798 | - CVSServer, GitServer, SubversionServer) |
799 | + CVSServer, GitServer, MercurialServer, SubversionServer) |
800 | from lp.codehosting.codeimport.tests.test_worker import ( |
801 | clean_up_default_stores_for_import) |
802 | from lp.testing import login, logout |
803 | @@ -501,6 +501,18 @@ |
804 | |
805 | return self.factory.makeCodeImport(git_repo_url=self.repo_path) |
806 | |
807 | + def makeHgCodeImport(self): |
808 | + """Make a `CodeImport` that points to a real Mercurial repository.""" |
809 | + load_optional_plugin('hg') |
810 | + self.hg_server = MercurialServer(self.repo_path) |
811 | + self.hg_server.setUp() |
812 | + self.addCleanup(self.hg_server.tearDown) |
813 | + |
814 | + self.hg_server.makeRepo([('README', 'contents')]) |
815 | + self.foreign_commit_count = 1 |
816 | + |
817 | + return self.factory.makeCodeImport(hg_repo_url=self.repo_path) |
818 | + |
819 | def getStartedJobForImport(self, code_import): |
820 | """Get a started `CodeImportJob` for `code_import`. |
821 | |
822 | @@ -592,6 +604,15 @@ |
823 | result = self.performImport(job_id) |
824 | return result.addCallback(self.assertImported, code_import_id) |
825 | |
826 | + def test_import_hg(self): |
827 | + # Create a Mercurial CodeImport and import it. |
828 | + job = self.getStartedJobForImport(self.makeHgCodeImport()) |
829 | + code_import_id = job.code_import.id |
830 | + job_id = job.id |
831 | + self.layer.txn.commit() |
832 | + result = self.performImport(job_id) |
833 | + return result.addCallback(self.assertImported, code_import_id) |
834 | + |
835 | def test_import_bzrsvn(self): |
836 | # Create a Subversion-via-bzr-svn CodeImport and import it. |
837 | job = self.getStartedJobForImport(self.makeBzrSvnCodeImport()) |
838 | |
839 | === modified file 'lib/lp/codehosting/codeimport/worker.py' |
840 | --- lib/lp/codehosting/codeimport/worker.py 2010-01-13 02:53:14 +0000 |
841 | +++ lib/lp/codehosting/codeimport/worker.py 2010-01-13 02:53:16 +0000 |
842 | @@ -11,6 +11,7 @@ |
843 | 'CodeImportSourceDetails', |
844 | 'ForeignTreeStore', |
845 | 'GitImportWorker', |
846 | + 'HgImportWorker', |
847 | 'ImportWorker', |
848 | 'get_default_bazaar_branch_store', |
849 | ] |
850 | @@ -126,7 +127,7 @@ |
851 | """Convert command line-style arguments to an instance.""" |
852 | branch_id = int(arguments.pop(0)) |
853 | rcstype = arguments.pop(0) |
854 | - if rcstype in ['svn', 'bzr-svn', 'git']: |
855 | + if rcstype in ['svn', 'bzr-svn', 'git', 'hg']: |
856 | [url] = arguments |
857 | cvs_root = cvs_module = None |
858 | elif rcstype == 'cvs': |
859 | @@ -151,6 +152,8 @@ |
860 | cvs_module=str(code_import.cvs_module)) |
861 | elif code_import.rcs_type == RevisionControlSystems.GIT: |
862 | return cls(branch_id, 'git', str(code_import.url)) |
863 | + elif code_import.rcs_type == RevisionControlSystems.HG: |
864 | + return cls(branch_id, 'hg', str(code_import.url)) |
865 | else: |
866 | raise AssertionError("Unknown rcstype %r." % code_import.rcs_type) |
867 | |
868 | @@ -158,7 +161,7 @@ |
869 | """Return a list of arguments suitable for passing to a child process. |
870 | """ |
871 | result = [str(self.branch_id), self.rcstype] |
872 | - if self.rcstype in ['svn', 'bzr-svn', 'git']: |
873 | + if self.rcstype in ['svn', 'bzr-svn', 'git', 'hg']: |
874 | result.append(self.url) |
875 | elif self.rcstype == 'cvs': |
876 | result.append(self.cvs_root) |
877 | @@ -544,6 +547,45 @@ |
878 | 'git.db', bazaar_tree.branch.repository._transport) |
879 | |
880 | |
881 | +class HgImportWorker(PullingImportWorker): |
882 | + """An import worker for Mercurial imports. |
883 | + |
884 | + The only behaviour we add is preserving the id-sha map between runs. |
885 | + """ |
886 | + |
887 | + db_file = 'hg-v2.db' |
888 | + |
889 | + @property |
890 | + def format_classes(self): |
891 | + """See `PullingImportWorker.opening_format`.""" |
892 | + # We only return HgLocalRepository for tests. |
893 | + from bzrlib.plugins.hg import HgBzrDirFormat |
894 | + return [HgBzrDirFormat] |
895 | + |
896 | + def getBazaarWorkingTree(self): |
897 | + """See `ImportWorker.getBazaarWorkingTree`. |
898 | + |
899 | + In addition to the superclass' behaviour, we retrieve the 'hg-v2.db' |
900 | + map from the import data store and put it where bzr-hg will find |
901 | + it in the Bazaar tree, that is at '.bzr/repository/hg-v2.db'. |
902 | + """ |
903 | + tree = PullingImportWorker.getBazaarWorkingTree(self) |
904 | + self.import_data_store.fetch( |
905 | + self.db_file, tree.branch.repository._transport) |
906 | + return tree |
907 | + |
908 | + def pushBazaarWorkingTree(self, bazaar_tree): |
909 | + """See `ImportWorker.pushBazaarWorkingTree`. |
910 | + |
911 | + In addition to the superclass' behaviour, we store the 'hg-v2.db' shamap |
912 | + that bzr-hg will have created at .bzr/repository/hg-v2.db into the |
913 | + import data store. |
914 | + """ |
915 | + PullingImportWorker.pushBazaarWorkingTree(self, bazaar_tree) |
916 | + self.import_data_store.put( |
917 | + self.db_file, bazaar_tree.branch.repository._transport) |
918 | + |
919 | + |
920 | class BzrSvnImportWorker(PullingImportWorker): |
921 | """An import worker for importing Subversion via bzr-svn.""" |
922 | |
923 | |
924 | === modified file 'lib/lp/testing/factory.py' |
925 | --- lib/lp/testing/factory.py 2010-01-13 02:53:14 +0000 |
926 | +++ lib/lp/testing/factory.py 2010-01-13 02:53:16 +0000 |
927 | @@ -1216,14 +1216,16 @@ |
928 | |
929 | def makeCodeImport(self, svn_branch_url=None, cvs_root=None, |
930 | cvs_module=None, product=None, branch_name=None, |
931 | - git_repo_url=None, registrant=None, rcs_type=None): |
932 | + git_repo_url=None, hg_repo_url=None, registrant=None, |
933 | + rcs_type=None): |
934 | """Create and return a new, arbitrary code import. |
935 | |
936 | The type of code import will be inferred from the source details |
937 | passed in, but defaults to a Subversion import from an arbitrary |
938 | unique URL. |
939 | """ |
940 | - if svn_branch_url is cvs_root is cvs_module is git_repo_url is None: |
941 | + if (svn_branch_url is cvs_root is cvs_module is git_repo_url is hg_repo_url |
942 | + is None): |
943 | svn_branch_url = self.getUniqueURL() |
944 | |
945 | if product is None: |
946 | @@ -1249,6 +1251,11 @@ |
947 | registrant, product, branch_name, |
948 | rcs_type=RevisionControlSystems.GIT, |
949 | url=git_repo_url) |
950 | + elif hg_repo_url is not None: |
951 | + return code_import_set.new( |
952 | + registrant, product, branch_name, |
953 | + rcs_type=RevisionControlSystems.HG, |
954 | + url=hg_repo_url) |
955 | else: |
956 | assert rcs_type in (None, RevisionControlSystems.CVS) |
957 | return code_import_set.new( |
958 | @@ -1322,7 +1329,7 @@ |
959 | branch_id = self.getUniqueInteger() |
960 | if rcstype is None: |
961 | rcstype = 'svn' |
962 | - if rcstype in ['svn', 'bzr-svn']: |
963 | + if rcstype in ['svn', 'bzr-svn', 'hg']: |
964 | assert cvs_root is cvs_module is None |
965 | if url is None: |
966 | url = self.getUniqueURL() |
967 | |
968 | === added symlink 'lib/mercurial' |
969 | === target is u'../sourcecode/mercurial/mercurial' |
970 | === added symlink 'optionalbzrplugins/hg' |
971 | === target is u'../sourcecode/bzr-hg' |
972 | === modified file 'scripts/code-import-worker.py' |
973 | --- scripts/code-import-worker.py 2009-11-17 02:49:41 +0000 |
974 | +++ scripts/code-import-worker.py 2010-01-13 02:53:16 +0000 |
975 | @@ -26,7 +26,7 @@ |
976 | from lp.codehosting import load_optional_plugin |
977 | from lp.codehosting.codeimport.worker import ( |
978 | BzrSvnImportWorker, CSCVSImportWorker, CodeImportSourceDetails, |
979 | - GitImportWorker, get_default_bazaar_branch_store) |
980 | + GitImportWorker, HgImportWorker, get_default_bazaar_branch_store) |
981 | from canonical.launchpad import scripts |
982 | |
983 | |
984 | @@ -46,6 +46,9 @@ |
985 | elif source_details.rcstype == 'bzr-svn': |
986 | load_optional_plugin('svn') |
987 | import_worker_cls = BzrSvnImportWorker |
988 | + elif source_details.rcstype == 'hg': |
989 | + load_optional_plugin('hg') |
990 | + import_worker_cls = HgImportWorker |
991 | else: |
992 | if source_details.rcstype not in ['cvs', 'svn']: |
993 | raise AssertionError( |
994 | |
995 | === modified file 'setup.py' |
996 | --- setup.py 2010-01-12 01:45:22 +0000 |
997 | +++ setup.py 2010-01-13 02:53:16 +0000 |
998 | @@ -43,6 +43,7 @@ |
999 | 'lazr.uri', |
1000 | 'lazr-js', |
1001 | 'mechanize', |
1002 | + 'mercurial', |
1003 | 'mocker', |
1004 | 'oauth', |
1005 | 'paramiko', |
1006 | |
1007 | === modified file 'utilities/sourcedeps.conf' |
1008 | --- utilities/sourcedeps.conf 2009-12-02 02:46:05 +0000 |
1009 | +++ utilities/sourcedeps.conf 2010-01-13 02:53:16 +0000 |
1010 | @@ -1,4 +1,5 @@ |
1011 | bzr-git lp:~launchpad-pqm/bzr-git/devel;revno=248 |
1012 | +bzr-hg lp:~launchpad-pqm/bzr-hg/devel;revno=281 |
1013 | bzr-loom lp:~launchpad-pqm/bzr-loom/trunk;revno=47 |
1014 | bzr-svn lp:~launchpad-pqm/bzr-svn/devel;revno=2706 |
1015 | cscvs lp:~launchpad-pqm/launchpad-cscvs/devel;revno=430 |
1016 | |
1017 | === modified file 'versions.cfg' |
1018 | --- versions.cfg 2010-01-12 01:45:22 +0000 |
1019 | +++ versions.cfg 2010-01-13 02:53:16 +0000 |
1020 | @@ -40,6 +40,7 @@ |
1021 | lazr-js = 0.9.2DEV |
1022 | martian = 0.11 |
1023 | mechanize = 0.1.11 |
1024 | +mercurial = 1.3.1 |
1025 | mocker = 0.10.1 |
1026 | mozrunner = 1.3.4 |
1027 | oauth = 1.0 |
This branch merges jelmer's hg import work into the imports-urls branch.