183
182
result_branch = source_branch.sprout(
184
183
result, revision_id=revision_id, repository=result_repo)
185
184
if (create_tree_if_local and
186
result.open_branch(name="").name == result_branch.name and
187
185
isinstance(target_transport, LocalTransport) and
188
186
(result_repo is None or result_repo.make_working_trees())):
189
wt = result.create_workingtree(
187
result.create_workingtree(
190
188
accelerator_tree=accelerator_tree,
191
189
hardlink=hardlink, from_branch=result_branch)
194
if recurse == 'down':
195
with cleanup.ExitStack() as stack:
198
basis = wt.basis_tree()
199
elif result_branch is not None:
200
basis = result_branch.basis_tree()
201
elif source_branch is not None:
202
basis = source_branch.basis_tree()
203
if basis is not None:
204
stack.enter_context(basis.lock_read())
205
subtrees = basis.iter_references()
208
for path in subtrees:
209
target = urlutils.join(url, urlutils.escape(path))
210
sublocation = wt.reference_parent(
211
path, possible_transports=possible_transports)
212
if sublocation is None:
214
'Ignoring nested tree %s, parent location unknown.',
217
sublocation.controldir.sprout(
218
target, basis.get_reference_revision(path),
219
force_new_repo=force_new_repo, recurse=recurse,
223
192
def clone_on_transport(self, transport, revision_id=None,
224
193
force_new_repo=False, preserve_stacking=False,
225
194
stacked_on=None, create_prefix=False,
226
use_existing_dir=True, no_tree=False,
195
use_existing_dir=True, no_tree=False):
228
196
"""See ControlDir.clone_on_transport."""
229
197
from ..repository import InterRepository
230
198
from .mapping import default_mapping
231
from ..transport.local import LocalTransport
232
199
if stacked_on is not None:
233
200
raise _mod_branch.UnstackableBranchFormat(
234
201
self._format, self.user_url)
247
214
interrepo = InterRepository.get(source_repo, target_repo)
248
215
if revision_id is not None:
249
216
determine_wants = interrepo.get_determine_wants_revids(
250
[revision_id], include_tags=True, tag_selector=tag_selector)
217
[revision_id], include_tags=True)
252
219
determine_wants = interrepo.determine_wants_all
253
220
(pack_hint, _, refs) = interrepo.fetch_objects(determine_wants,
254
221
mapping=default_mapping)
255
222
for name, val in viewitems(refs):
256
223
target_git_repo.refs[name] = val
257
result_dir = LocalGitDir(transport, target_git_repo, format)
224
result_dir = self.__class__(transport, target_git_repo, format)
258
225
if revision_id is not None:
259
226
result_dir.open_branch().set_last_revision(revision_id)
260
if not no_tree and isinstance(result_dir.root_transport, LocalTransport):
228
# Cheaper to check if the target is not local, than to try making
230
result_dir.root_transport.local_abspath('.')
261
231
if result_dir.open_repository().make_working_trees():
263
local_wt = self.open_workingtree()
264
except brz_errors.NoWorkingTree:
266
except brz_errors.NotLocalUrl:
267
result_dir.create_workingtree(revision_id=revision_id)
269
local_wt.clone(result_dir, revision_id=revision_id)
232
self.open_workingtree().clone(
233
result_dir, revision_id=revision_id)
234
except (brz_errors.NoWorkingTree, brz_errors.NotLocalUrl):
271
237
return result_dir
302
268
return UseExistingRepository(self.find_repository())
304
def branch_names(self):
305
from .refs import ref_to_branch_name
307
for ref in self.get_refs_container().keys():
309
branch_name = ref_to_branch_name(ref)
310
except UnicodeDecodeError:
311
trace.warning("Ignoring branch %r with unicode error ref", ref)
315
ret.append(branch_name)
318
270
def get_branches(self):
319
271
from .refs import ref_to_branch_name
321
273
for ref in self.get_refs_container().keys():
323
275
branch_name = ref_to_branch_name(ref)
324
278
except UnicodeDecodeError:
325
279
trace.warning("Ignoring branch %r with unicode error ref", ref)
329
281
ret[branch_name] = self.open_branch(ref=ref)
335
287
def push_branch(self, source, revision_id=None, overwrite=False,
336
288
remember=False, create_prefix=False, lossy=False,
337
name=None, tag_selector=None):
338
290
"""Push the source branch into this ControlDir."""
339
291
push_result = GitPushResult()
340
292
push_result.workingtree_updated = None
347
299
target = self.open_branch(name, nascent_ok=True)
348
300
push_result.branch_push_result = source.push(
349
301
target, overwrite=overwrite, stop_revision=revision_id,
350
lossy=lossy, tag_selector=tag_selector)
351
303
push_result.new_revid = push_result.branch_push_result.new_revid
352
304
push_result.old_revid = push_result.branch_push_result.old_revid
354
wt = self.open_workingtree()
355
except brz_errors.NoWorkingTree:
356
push_result.workingtree_updated = None
358
if self.open_branch(name="").name == target.name:
360
old_revision=push_result.old_revid,
361
new_revision=push_result.new_revid)
362
push_result.workingtree_updated = True
364
push_result.workingtree_updated = False
365
305
push_result.target_branch = target
366
306
if source.get_push_location() is None or remember:
367
307
source.set_push_location(push_result.target_branch.base)
398
338
from .transportgit import TransportRepo
400
340
def _open(transport):
402
return TransportRepo(transport, self.bare,
403
refs_text=getattr(self, "_refs_text", None))
404
except ValueError as e:
405
if e.args == ('Expected file to start with \'gitdir: \'', ):
406
raise brz_errors.NotBranchError(path=transport.base)
341
return TransportRepo(transport, self.bare,
342
refs_text=getattr(self, "_refs_text", None))
409
344
def redirected(transport, e, redirection_notice):
410
345
trace.note(redirection_notice)
411
346
return transport._redirected_to(e.source, e.target)
412
347
gitrepo = do_catching_redirections(_open, transport, redirected)
413
if not _found and not gitrepo._controltransport.has('objects'):
348
if not gitrepo._controltransport.has('HEAD'):
414
349
raise brz_errors.NotBranchError(path=transport.base)
415
350
return LocalGitDir(transport, gitrepo, self)
469
401
raise brz_errors.NotBranchError(path=transport.base)
470
402
return external_url.startswith("file:")
472
def is_control_filename(self, filename):
473
return (filename == '.git'
474
or filename.startswith('.git/')
475
or filename.startswith('.git\\'))
478
405
class BareLocalGitControlDirFormat(LocalGitControlDirFormat):
519
443
self.transport = transport.clone('.git')
520
444
self._mode_check_done = None
446
def is_control_filename(self, filename):
447
return (filename == '.git'
448
or filename.startswith('.git/')
449
or filename.startswith('.git\\'))
522
451
def _get_symref(self, ref):
523
452
ref_chain, unused_sha = self._git.refs.follow(ref)
524
453
if len(ref_chain) == 1: