Merge lp:~jelmer/brz-git/remote-test-improvements into lp:brz-git
- remote-test-improvements
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Jelmer Vernooij | ||||
Approved revision: | 1877 | ||||
Merge reported by: | The Breezy Bot | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~jelmer/brz-git/remote-test-improvements | ||||
Merge into: | lp:brz-git | ||||
Diff against target: |
647 lines (+276/-69) 12 files modified
branch.py (+1/-1) commands.py (+2/-3) dir.py (+17/-17) fetch.py (+3/-3) object_store.py (+8/-4) push.py (+1/-1) refs.py (+8/-1) remote.py (+30/-15) tests/test_git_remote_helper.py (+1/-1) tests/test_refs.py (+54/-6) tests/test_remote.py (+141/-8) transportgit.py (+10/-9) |
||||
To merge this branch: | bzr merge lp:~jelmer/brz-git/remote-test-improvements | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Review via email: mp+341866@code.launchpad.net |
Commit message
Fix remote branch operations and add more tests.
Description of the change
Fix remote branch operations and add more tests.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'branch.py' |
2 | --- branch.py 2018-03-21 03:06:49 +0000 |
3 | +++ branch.py 2018-03-22 01:32:19 +0000 |
4 | @@ -1081,7 +1081,7 @@ |
5 | stop_revno = self.source.revision_id_to_revno(stop_revision) |
6 | if type(stop_revision) is not str: |
7 | raise TypeError(stop_revision) |
8 | - main_ref = self.target.ref or "refs/heads/master" |
9 | + main_ref = self.target.ref |
10 | refs = { main_ref: (None, stop_revision) } |
11 | if fetch_tags is None: |
12 | c = self.source.get_config_stack() |
13 | |
14 | === modified file 'commands.py' |
15 | --- commands.py 2018-03-17 19:20:55 +0000 |
16 | +++ commands.py 2018-03-22 01:32:19 +0000 |
17 | @@ -124,16 +124,15 @@ |
18 | interrepo = InterRepository.get(source_repo, target_repo) |
19 | mapping = source_repo.get_mapping() |
20 | refs = interrepo.fetch() |
21 | - refs_dict = refs.as_dict() |
22 | pb = ui.ui_factory.nested_progress_bar() |
23 | try: |
24 | - for i, (name, sha) in enumerate(refs_dict.iteritems()): |
25 | + for i, (name, sha) in enumerate(refs.iteritems()): |
26 | try: |
27 | branch_name = ref_to_branch_name(name) |
28 | except ValueError: |
29 | # Not a branch, ignore |
30 | continue |
31 | - pb.update(gettext("creating branches"), i, len(refs_dict)) |
32 | + pb.update(gettext("creating branches"), i, len(refs)) |
33 | if getattr(target_controldir._format, "colocated_branches", False) and colocated: |
34 | if name == "HEAD": |
35 | branch_name = None |
36 | |
37 | === modified file 'dir.py' |
38 | --- dir.py 2018-03-20 21:05:19 +0000 |
39 | +++ dir.py 2018-03-22 01:32:19 +0000 |
40 | @@ -261,6 +261,23 @@ |
41 | """ |
42 | return UseExistingRepository(self.find_repository()) |
43 | |
44 | + def get_branches(self): |
45 | + from .refs import ref_to_branch_name |
46 | + ret = {} |
47 | + for ref in self.get_refs_container().keys(): |
48 | + try: |
49 | + branch_name = ref_to_branch_name(ref) |
50 | + except ValueError: |
51 | + continue |
52 | + except UnicodeDecodeError: |
53 | + trace.warning("Ignoring branch %r with unicode error ref", ref) |
54 | + continue |
55 | + ret[branch_name] = self.open_branch(ref=ref) |
56 | + return ret |
57 | + |
58 | + def list_branches(self): |
59 | + return self.get_branches().values() |
60 | + |
61 | |
62 | class LocalGitControlDirFormat(GitControlDirFormat): |
63 | """The .git directory control format.""" |
64 | @@ -513,23 +530,6 @@ |
65 | def needs_format_conversion(self, format=None): |
66 | return not isinstance(self._format, format.__class__) |
67 | |
68 | - def list_branches(self): |
69 | - return self.get_branches().values() |
70 | - |
71 | - def get_branches(self): |
72 | - from .refs import ref_to_branch_name |
73 | - ret = {} |
74 | - for ref in self._git.refs.keys(): |
75 | - try: |
76 | - branch_name = ref_to_branch_name(ref) |
77 | - except ValueError: |
78 | - continue |
79 | - except UnicodeDecodeError: |
80 | - trace.warning("Ignoring branch %r with unicode error ref", ref) |
81 | - continue |
82 | - ret[branch_name] = self.open_branch(ref=ref) |
83 | - return ret |
84 | - |
85 | def open_repository(self): |
86 | """'open' a repository for this dir.""" |
87 | if self.control_transport.has('commondir'): |
88 | |
89 | === modified file 'fetch.py' |
90 | --- fetch.py 2018-03-21 03:06:49 +0000 |
91 | +++ fetch.py 2018-03-22 01:32:19 +0000 |
92 | @@ -602,7 +602,7 @@ |
93 | |
94 | def determine_wants_all(self, refs): |
95 | potential = set() |
96 | - for k, v in refs.as_dict().iteritems(): |
97 | + for k, v in refs.iteritems(): |
98 | # For non-git target repositories, only worry about peeled |
99 | if v == ZERO_SHA: |
100 | continue |
101 | @@ -614,7 +614,7 @@ |
102 | def determine_wants(refs): |
103 | potential = set(wants) |
104 | if include_tags: |
105 | - for k, unpeeled in refs.as_dict().iteritems(): |
106 | + for k, unpeeled in refs.iteritems(): |
107 | if not is_tag(k): |
108 | continue |
109 | if unpeeled == ZERO_SHA: |
110 | @@ -761,7 +761,7 @@ |
111 | def fetch_objects(self, determine_wants, mapping, limit=None, lossy=False): |
112 | """See `InterGitNonGitRepository`.""" |
113 | self._warn_slow() |
114 | - remote_refs = self.source.controldir.get_refs_container() |
115 | + remote_refs = self.source.controldir.get_refs_container().as_dict() |
116 | wants = determine_wants(remote_refs) |
117 | create_pb = None |
118 | pb = ui.ui_factory.nested_progress_bar() |
119 | |
120 | === modified file 'object_store.py' |
121 | --- object_store.py 2018-03-21 03:06:49 +0000 |
122 | +++ object_store.py 2018-03-22 01:32:19 +0000 |
123 | @@ -29,6 +29,9 @@ |
124 | from dulwich.object_store import ( |
125 | BaseObjectStore, |
126 | ) |
127 | +from dulwich.pack import ( |
128 | + pack_objects_to_data, |
129 | + ) |
130 | |
131 | from ... import ( |
132 | errors, |
133 | @@ -705,10 +708,11 @@ |
134 | else: |
135 | raise KeyError(sha) |
136 | |
137 | - def generate_lossy_pack_contents(self, have, want, progress=None, |
138 | - get_tagged=None): |
139 | - return self.generate_pack_contents(have, want, progress, get_tagged, |
140 | - lossy=True) |
141 | + def generate_lossy_pack_data(self, have, want, progress=None, |
142 | + get_tagged=None, ofs_delta=False): |
143 | + return pack_objects_to_data( |
144 | + self.generate_pack_contents(have, want, progress, get_tagged, |
145 | + lossy=True)) |
146 | |
147 | def generate_pack_contents(self, have, want, progress=None, |
148 | ofs_delta=False, get_tagged=None, lossy=False): |
149 | |
150 | === modified file 'push.py' |
151 | --- push.py 2018-03-21 03:06:49 +0000 |
152 | +++ push.py 2018-03-22 01:32:19 +0000 |
153 | @@ -360,7 +360,7 @@ |
154 | self._warn_slow() |
155 | with self.source_store.lock_read(): |
156 | new_refs = self.target.send_pack(determine_wants, |
157 | - self.source_store.generate_lossy_pack_contents) |
158 | + self.source_store.generate_lossy_pack_data) |
159 | # FIXME: revidmap? |
160 | return revidmap, self.old_refs, self.new_refs |
161 | |
162 | |
163 | === modified file 'refs.py' |
164 | --- refs.py 2018-03-17 17:27:39 +0000 |
165 | +++ refs.py 2018-03-22 01:32:19 +0000 |
166 | @@ -25,6 +25,7 @@ |
167 | from ... import ( |
168 | errors, |
169 | osutils, |
170 | + revision as _mod_revision, |
171 | ) |
172 | |
173 | is_tag = lambda x: x.startswith("refs/tags/") |
174 | @@ -97,6 +98,9 @@ |
175 | self.dir = dir |
176 | self.object_store = object_store |
177 | |
178 | + def get_packed_refs(self): |
179 | + return {} |
180 | + |
181 | def set_symbolic_ref(self, name, other): |
182 | if name == "HEAD": |
183 | pass # FIXME: Switch default branch |
184 | @@ -132,8 +136,11 @@ |
185 | revid = self._get_revid_by_tag_name(tag_name) |
186 | else: |
187 | revid = self._get_revid_by_branch_name(branch_name) |
188 | + if revid == _mod_revision.NULL_REVISION: |
189 | + return None |
190 | # FIXME: Unpeel if necessary |
191 | - return self.object_store._lookup_revision_sha1(revid) |
192 | + with self.object_store.lock_read(): |
193 | + return self.object_store._lookup_revision_sha1(revid) |
194 | |
195 | def get_peeled(self, ref): |
196 | return self.read_loose_ref(ref) |
197 | |
198 | === modified file 'remote.py' |
199 | --- remote.py 2018-03-21 03:46:30 +0000 |
200 | +++ remote.py 2018-03-22 01:32:19 +0000 |
201 | @@ -31,6 +31,7 @@ |
202 | InvalidRevisionId, |
203 | NoSuchFile, |
204 | NoSuchRevision, |
205 | + NoSuchTag, |
206 | NotBranchError, |
207 | NotLocalUrl, |
208 | UninitializableFormat, |
209 | @@ -68,6 +69,7 @@ |
210 | branch_name_to_ref, |
211 | is_peeled, |
212 | ref_to_tag_name, |
213 | + tag_name_to_ref, |
214 | ) |
215 | |
216 | import dulwich |
217 | @@ -77,6 +79,7 @@ |
218 | ) |
219 | from dulwich.pack import ( |
220 | Pack, |
221 | + pack_objects_to_data, |
222 | ) |
223 | from dulwich.repo import DictRefsContainer |
224 | import os |
225 | @@ -295,31 +298,28 @@ |
226 | if result.refs is None: |
227 | result.refs = {} |
228 | self._refs = remote_refs_dict_to_container(result.refs) |
229 | - return result.refs |
230 | + return result |
231 | except GitProtocolError, e: |
232 | raise parse_git_error(self.transport.external_url(), e) |
233 | |
234 | - def send_pack(self, get_changed_refs, generate_pack_contents): |
235 | + def send_pack(self, get_changed_refs, generate_pack_data): |
236 | try: |
237 | return self._client.send_pack(self._client_path, get_changed_refs, |
238 | - generate_pack_contents) |
239 | + generate_pack_data) |
240 | except GitProtocolError, e: |
241 | raise parse_git_error(self.transport.external_url(), e) |
242 | |
243 | - def _get_default_ref(self): |
244 | - return "refs/heads/master" |
245 | - |
246 | def destroy_branch(self, name=None): |
247 | refname = self._get_selected_ref(name) |
248 | def get_changed_refs(old_refs): |
249 | ret = dict(old_refs) |
250 | if not refname in ret: |
251 | raise NotBranchError(self.user_url) |
252 | - ret[refname] = "00" * 20 |
253 | + ret[refname] = dulwich.client.ZERO_SHA |
254 | return ret |
255 | - def generate_pack_contents(have, want, ofs_delta=False): |
256 | - return [] |
257 | - self.send_pack(get_changed_refs, generate_pack_contents) |
258 | + def generate_pack_data(have, want, ofs_delta=False): |
259 | + return pack_objects_to_data([]) |
260 | + self.send_pack(get_changed_refs, generate_pack_data) |
261 | |
262 | @property |
263 | def user_url(self): |
264 | @@ -486,8 +486,8 @@ |
265 | return self.controldir.fetch_pack(determine_wants, graph_walker, |
266 | pack_data, progress) |
267 | |
268 | - def send_pack(self, get_changed_refs, generate_pack_contents): |
269 | - return self.controldir.send_pack(get_changed_refs, generate_pack_contents) |
270 | + def send_pack(self, get_changed_refs, generate_pack_data): |
271 | + return self.controldir.send_pack(get_changed_refs, generate_pack_data) |
272 | |
273 | def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, |
274 | progress=None): |
275 | @@ -501,7 +501,7 @@ |
276 | return EmptyObjectStoreIterator() |
277 | return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref) |
278 | |
279 | - def lookup_bzr_revision_id(self, bzr_revid): |
280 | + def lookup_bzr_revision_id(self, bzr_revid, mapping=None): |
281 | # This won't work for any round-tripped bzr revisions, but it's a start.. |
282 | try: |
283 | return mapping_registry.revision_id_bzr_to_foreign(bzr_revid) |
284 | @@ -530,8 +530,23 @@ |
285 | class RemoteGitTagDict(GitTags): |
286 | |
287 | def set_tag(self, name, revid): |
288 | - # FIXME: Not supported yet, should do a push of a new ref |
289 | - raise NotImplementedError(self.set_tag) |
290 | + sha = self.branch.lookup_bzr_revision_id(revid)[0] |
291 | + self._set_ref(name, sha) |
292 | + |
293 | + def delete_tag(self, name): |
294 | + self._set_ref(name, dulwich.client.ZERO_SHA) |
295 | + |
296 | + def _set_ref(self, name, sha): |
297 | + ref = tag_name_to_ref(name) |
298 | + def get_changed_refs(old_refs): |
299 | + ret = dict(old_refs) |
300 | + if sha == dulwich.client.ZERO_SHA and ref not in ret: |
301 | + raise NoSuchTag(name) |
302 | + ret[ref] = sha |
303 | + return ret |
304 | + def generate_pack_data(have, want, ofs_delta=False): |
305 | + return pack_objects_to_data([]) |
306 | + self.repository.send_pack(get_changed_refs, generate_pack_data) |
307 | |
308 | |
309 | class RemoteGitBranch(GitBranch): |
310 | |
311 | === modified file 'tests/test_git_remote_helper.py' |
312 | --- tests/test_git_remote_helper.py 2018-03-17 17:34:12 +0000 |
313 | +++ tests/test_git_remote_helper.py 2018-03-22 01:32:19 +0000 |
314 | @@ -115,7 +115,7 @@ |
315 | f = StringIO() |
316 | self.helper.cmd_list(f, []) |
317 | self.assertEquals( |
318 | - '0000000000000000000000000000000000000000 HEAD\n\n', |
319 | + '\n', |
320 | f.getvalue()) |
321 | |
322 | def test_import(self): |
323 | |
324 | === modified file 'tests/test_refs.py' |
325 | --- tests/test_refs.py 2018-03-17 17:34:12 +0000 |
326 | +++ tests/test_refs.py 2018-03-22 01:32:19 +0000 |
327 | @@ -22,18 +22,66 @@ |
328 | |
329 | from .... import tests |
330 | |
331 | -from ...git import refs |
332 | +from ..object_store import BazaarObjectStore |
333 | +from ..refs import ( |
334 | + BazaarRefsContainer, |
335 | + ref_to_branch_name, |
336 | + branch_name_to_ref, |
337 | + ) |
338 | |
339 | |
340 | class BranchNameRefConversionTests(tests.TestCase): |
341 | |
342 | def test_head(self): |
343 | - self.assertEquals("", refs.ref_to_branch_name("HEAD")) |
344 | - self.assertEquals("HEAD", refs.branch_name_to_ref("")) |
345 | + self.assertEquals("", ref_to_branch_name("HEAD")) |
346 | + self.assertEquals("HEAD", branch_name_to_ref("")) |
347 | |
348 | def test_tag(self): |
349 | - self.assertRaises(ValueError, refs.ref_to_branch_name, "refs/tags/FOO") |
350 | + self.assertRaises(ValueError, ref_to_branch_name, "refs/tags/FOO") |
351 | |
352 | def test_branch(self): |
353 | - self.assertEquals("frost", refs.ref_to_branch_name("refs/heads/frost")) |
354 | - self.assertEquals("refs/heads/frost", refs.branch_name_to_ref("frost")) |
355 | + self.assertEquals("frost", ref_to_branch_name("refs/heads/frost")) |
356 | + self.assertEquals("refs/heads/frost", branch_name_to_ref("frost")) |
357 | + |
358 | + |
359 | +class BazaarRefsContainerTests(tests.TestCaseWithTransport): |
360 | + |
361 | + def test_empty(self): |
362 | + tree = self.make_branch_and_tree('.') |
363 | + store = BazaarObjectStore(tree.branch.repository) |
364 | + refs = BazaarRefsContainer(tree.controldir, store) |
365 | + self.assertEqual(refs.as_dict(), {}) |
366 | + |
367 | + def test_some_commit(self): |
368 | + tree = self.make_branch_and_tree('.') |
369 | + revid = tree.commit('somechange') |
370 | + store = BazaarObjectStore(tree.branch.repository) |
371 | + refs = BazaarRefsContainer(tree.controldir, store) |
372 | + self.assertEqual( |
373 | + refs.as_dict(), |
374 | + {'HEAD': store._lookup_revision_sha1(revid)}) |
375 | + |
376 | + def test_some_tag(self): |
377 | + tree = self.make_branch_and_tree('.') |
378 | + revid = tree.commit('somechange') |
379 | + tree.branch.tags.set_tag('sometag', revid) |
380 | + store = BazaarObjectStore(tree.branch.repository) |
381 | + refs = BazaarRefsContainer(tree.controldir, store) |
382 | + self.assertEqual( |
383 | + refs.as_dict(), |
384 | + {'HEAD': store._lookup_revision_sha1(revid), |
385 | + 'refs/tags/sometag': store._lookup_revision_sha1(revid), |
386 | + }) |
387 | + |
388 | + def test_some_branch(self): |
389 | + tree = self.make_branch_and_tree('.') |
390 | + revid = tree.commit('somechange') |
391 | + otherbranch = tree.controldir.create_branch(name='otherbranch') |
392 | + otherbranch.generate_revision_history(revid) |
393 | + store = BazaarObjectStore(tree.branch.repository) |
394 | + refs = BazaarRefsContainer(tree.controldir, store) |
395 | + self.assertEqual( |
396 | + refs.as_dict(), |
397 | + {'HEAD': store._lookup_revision_sha1(revid), |
398 | + 'refs/heads/otherbranch': store._lookup_revision_sha1(revid), |
399 | + }) |
400 | |
401 | === modified file 'tests/test_remote.py' |
402 | --- tests/test_remote.py 2018-03-21 03:46:30 +0000 |
403 | +++ tests/test_remote.py 2018-03-22 01:32:19 +0000 |
404 | @@ -24,6 +24,7 @@ |
405 | from ....errors import ( |
406 | BzrError, |
407 | NotBranchError, |
408 | + NoSuchTag, |
409 | ) |
410 | |
411 | from ....tests import ( |
412 | @@ -96,12 +97,14 @@ |
413 | self.assertTrue(self.format.supports_tags()) |
414 | |
415 | |
416 | -class TestFetchFromRemote(TestCaseWithTransport): |
417 | +class FetchFromRemoteTestBase(object): |
418 | |
419 | _test_needs_features = [ExecutableFeature('git')] |
420 | |
421 | + _to_format = None |
422 | + |
423 | def setUp(self): |
424 | - super(TestFetchFromRemote, self).setUp() |
425 | + TestCaseWithTransport.setUp(self) |
426 | self.remote_real = GitRepo.init('remote', mkdir=True) |
427 | self.remote_url = 'git://%s/' % os.path.abspath(self.remote_real.path) |
428 | self.permit_url(self.remote_url) |
429 | @@ -112,8 +115,8 @@ |
430 | committer='committer <committer@example.com>', |
431 | author='author <author@example.com>') |
432 | |
433 | - self.make_branch_and_tree('.') |
434 | remote = ControlDir.open(self.remote_url) |
435 | + self.make_controldir('local', format=self._to_format) |
436 | local = remote.sprout('local') |
437 | self.assertEqual( |
438 | default_mapping.revision_id_foreign_to_bzr(self.remote_real.head()), |
439 | @@ -131,8 +134,8 @@ |
440 | ref='refs/tags/another') |
441 | self.remote_real.refs['refs/tags/blah'] = self.remote_real.head() |
442 | |
443 | - self.make_branch_and_tree('.') |
444 | remote = ControlDir.open(self.remote_url) |
445 | + self.make_controldir('local', format=self._to_format) |
446 | local = remote.sprout('local') |
447 | local_branch = local.open_branch() |
448 | self.assertEqual( |
449 | @@ -144,12 +147,24 @@ |
450 | local_branch.tags.get_tag_dict()) |
451 | |
452 | |
453 | -class TestPushToRemote(TestCaseWithTransport): |
454 | +class FetchFromRemoteToBzrTests(FetchFromRemoteTestBase,TestCaseWithTransport): |
455 | + |
456 | + _to_format = '2a' |
457 | + |
458 | + |
459 | +class FetchFromRemoteToGitTests(FetchFromRemoteTestBase,TestCaseWithTransport): |
460 | + |
461 | + _to_format = 'git' |
462 | + |
463 | + |
464 | +class PushToRemoteBase(object): |
465 | |
466 | _test_needs_features = [ExecutableFeature('git')] |
467 | |
468 | + _from_format = None |
469 | + |
470 | def setUp(self): |
471 | - super(TestPushToRemote, self).setUp() |
472 | + TestCaseWithTransport.setUp(self) |
473 | self.remote_real = GitRepo.init('remote', mkdir=True) |
474 | self.remote_url = 'git://%s/' % os.path.abspath(self.remote_real.path) |
475 | self.permit_url(self.remote_url) |
476 | @@ -160,20 +175,138 @@ |
477 | committer='committer <committer@example.com>', |
478 | author='author <author@example.com>') |
479 | |
480 | - self.make_branch_and_tree('.') |
481 | remote = ControlDir.open(self.remote_url) |
482 | + self.make_controldir('local', format=self._from_format) |
483 | local = remote.sprout('local') |
484 | self.build_tree(['local/blah']) |
485 | wt = local.open_workingtree() |
486 | wt.add(['blah']) |
487 | revid = wt.commit('blah') |
488 | wt.branch.tags.set_tag('sometag', revid) |
489 | + wt.branch.get_config_stack().set('branch.fetch_tags', True) |
490 | |
491 | - remote.push_branch(wt.branch) |
492 | + if self._from_format == 'git': |
493 | + wt.branch.push(remote.open_branch()) |
494 | + else: |
495 | + wt.branch.push(remote.open_branch(), lossy=True) |
496 | |
497 | self.assertNotEqual(self.remote_real.head(), c1) |
498 | self.assertEqual( |
499 | {'refs/heads/master': self.remote_real.head(), |
500 | 'HEAD': self.remote_real.head(), |
501 | + 'refs/tags/sometag': self.remote_real.head(), |
502 | }, |
503 | self.remote_real.get_refs()) |
504 | + |
505 | + |
506 | +class PushToRemoteFromBzrTests(PushToRemoteBase,TestCaseWithTransport): |
507 | + |
508 | + _from_format = '2a' |
509 | + |
510 | + |
511 | +class PushToRemoteFromGitTests(PushToRemoteBase,TestCaseWithTransport): |
512 | + |
513 | + _from_format = 'git' |
514 | + |
515 | + |
516 | +class RemoteControlDirTests(TestCaseWithTransport): |
517 | + |
518 | + _test_needs_features = [ExecutableFeature('git')] |
519 | + |
520 | + def setUp(self): |
521 | + TestCaseWithTransport.setUp(self) |
522 | + self.remote_real = GitRepo.init('remote', mkdir=True) |
523 | + self.remote_url = 'git://%s/' % os.path.abspath(self.remote_real.path) |
524 | + self.permit_url(self.remote_url) |
525 | + |
526 | + def test_remove_branch(self): |
527 | + c1 = self.remote_real.do_commit( |
528 | + message='message', |
529 | + committer='committer <committer@example.com>', |
530 | + author='author <author@example.com>') |
531 | + c2 = self.remote_real.do_commit( |
532 | + message='another commit', |
533 | + committer='committer <committer@example.com>', |
534 | + author='author <author@example.com>', |
535 | + ref='refs/heads/blah') |
536 | + |
537 | + remote = ControlDir.open(self.remote_url) |
538 | + remote.destroy_branch(name='blah') |
539 | + self.assertEqual( |
540 | + self.remote_real.get_refs(), |
541 | + {'refs/heads/master': self.remote_real.head(), |
542 | + 'HEAD': self.remote_real.head(), |
543 | + }) |
544 | + |
545 | + def test_list_branches(self): |
546 | + c1 = self.remote_real.do_commit( |
547 | + message='message', |
548 | + committer='committer <committer@example.com>', |
549 | + author='author <author@example.com>') |
550 | + c2 = self.remote_real.do_commit( |
551 | + message='another commit', |
552 | + committer='committer <committer@example.com>', |
553 | + author='author <author@example.com>', |
554 | + ref='refs/heads/blah') |
555 | + |
556 | + remote = ControlDir.open(self.remote_url) |
557 | + self.assertEqual( |
558 | + ['', 'blah', 'master'], |
559 | + [b.name for b in remote.list_branches()]) |
560 | + |
561 | + def test_get_branches(self): |
562 | + c1 = self.remote_real.do_commit( |
563 | + message='message', |
564 | + committer='committer <committer@example.com>', |
565 | + author='author <author@example.com>') |
566 | + c2 = self.remote_real.do_commit( |
567 | + message='another commit', |
568 | + committer='committer <committer@example.com>', |
569 | + author='author <author@example.com>', |
570 | + ref='refs/heads/blah') |
571 | + |
572 | + remote = ControlDir.open(self.remote_url) |
573 | + self.assertEqual( |
574 | + {'', 'blah', 'master'}, |
575 | + set(remote.get_branches().keys())) |
576 | + |
577 | + def test_remove_tag(self): |
578 | + c1 = self.remote_real.do_commit( |
579 | + message='message', |
580 | + committer='committer <committer@example.com>', |
581 | + author='author <author@example.com>') |
582 | + c2 = self.remote_real.do_commit( |
583 | + message='another commit', |
584 | + committer='committer <committer@example.com>', |
585 | + author='author <author@example.com>', |
586 | + ref='refs/tags/blah') |
587 | + |
588 | + remote = ControlDir.open(self.remote_url) |
589 | + remote_branch = remote.open_branch() |
590 | + remote_branch.tags.delete_tag('blah') |
591 | + self.assertRaises(NoSuchTag, remote_branch.tags.delete_tag, 'blah') |
592 | + self.assertEqual( |
593 | + self.remote_real.get_refs(), |
594 | + {'refs/heads/master': self.remote_real.head(), |
595 | + 'HEAD': self.remote_real.head(), |
596 | + }) |
597 | + |
598 | + def test_set_tag(self): |
599 | + c1 = self.remote_real.do_commit( |
600 | + message='message', |
601 | + committer='committer <committer@example.com>', |
602 | + author='author <author@example.com>') |
603 | + c2 = self.remote_real.do_commit( |
604 | + message='another commit', |
605 | + committer='committer <committer@example.com>', |
606 | + author='author <author@example.com>') |
607 | + |
608 | + remote = ControlDir.open(self.remote_url) |
609 | + remote.open_branch().tags.set_tag( |
610 | + 'blah', default_mapping.revision_id_foreign_to_bzr(c1)) |
611 | + self.assertEqual( |
612 | + self.remote_real.get_refs(), |
613 | + {'refs/heads/master': self.remote_real.head(), |
614 | + 'refs/tags/blah': c1, |
615 | + 'HEAD': self.remote_real.head(), |
616 | + }) |
617 | |
618 | === modified file 'transportgit.py' |
619 | --- transportgit.py 2018-03-17 17:27:39 +0000 |
620 | +++ transportgit.py 2018-03-22 01:32:19 +0000 |
621 | @@ -94,16 +94,17 @@ |
622 | pass |
623 | |
624 | def subkeys(self, base): |
625 | + """Refs present in this container under a base. |
626 | + |
627 | + :param base: The base to return refs under. |
628 | + :return: A set of valid refs in this container under the base; the base |
629 | + prefix is stripped from the ref names returned. |
630 | + """ |
631 | keys = set() |
632 | - try: |
633 | - iter_files = self.transport.clone(base).iter_files_recursive() |
634 | - keys.update(("%s/%s" % (base, urllib.unquote(refname))).strip("/") for |
635 | - refname in iter_files if check_ref_format("%s/%s" % (base, refname))) |
636 | - except (TransportNotPossible, NoSuchFile): |
637 | - pass |
638 | - for key in self.get_packed_refs(): |
639 | - if key.startswith(base): |
640 | - keys.add(key[len(base):].strip("/")) |
641 | + base_len = len(base) + 1 |
642 | + for refname in self.allkeys(): |
643 | + if refname.startswith(base): |
644 | + keys.add(refname[base_len:]) |
645 | return keys |
646 | |
647 | def allkeys(self): |
Rubberstamp! Proposer approves of own proposal.