143
158
format.get_format_description(),
146
def clone(self, url, revision_id=None, force_new_repo=False):
161
def clone(self, url, revision_id=None, force_new_repo=False,
162
preserve_stacking=False):
147
163
"""Clone this bzrdir and its contents to url verbatim.
149
If urls last component does not exist, it will be created.
151
if revision_id is not None, then the clone operation may tune
152
itself to download less data.
153
:param force_new_repo: Do not use a shared repository for the target
154
even if one is available.
157
result = self._format.initialize(url)
165
:param url: The url create the clone at. If url's last component does
166
not exist, it will be created.
167
:param revision_id: The tip revision-id to use for any branch or
168
working tree. If not None, then the clone operation may tune
169
itself to download less data.
170
:param force_new_repo: Do not use a shared repository for the target
171
even if one is available.
172
:param preserve_stacking: When cloning a stacked branch, stack the
173
new branch on top of the other branch's stacked-on branch.
175
return self.clone_on_transport(get_transport(url),
176
revision_id=revision_id,
177
force_new_repo=force_new_repo,
178
preserve_stacking=preserve_stacking)
180
def clone_on_transport(self, transport, revision_id=None,
181
force_new_repo=False, preserve_stacking=False,
183
"""Clone this bzrdir and its contents to transport verbatim.
185
:param transport: The transport for the location to produce the clone
186
at. If the target directory does not exist, it will be created.
187
:param revision_id: The tip revision-id to use for any branch or
188
working tree. If not None, then the clone operation may tune
189
itself to download less data.
190
:param force_new_repo: Do not use a shared repository for the target,
191
even if one is available.
192
:param preserve_stacking: When cloning a stacked branch, stack the
193
new branch on top of the other branch's stacked-on branch.
195
transport.ensure_base()
196
require_stacking = (stacked_on is not None)
197
format = self.cloning_metadir(require_stacking)
198
# Bug: We create a metadir without knowing if it can support stacking,
199
# we should look up the policy needs first.
200
result = format.initialize_on_transport(transport)
201
repository_policy = None
159
203
local_repo = self.find_repository()
160
204
except errors.NoRepositoryPresent:
161
205
local_repo = None
207
local_branch = self.open_branch()
208
except errors.NotBranchError:
211
# enable fallbacks when branch is not a branch reference
212
if local_branch.repository.has_same_location(local_repo):
213
local_repo = local_branch.repository
214
if preserve_stacking:
216
stacked_on = local_branch.get_stacked_on_url()
217
except (errors.UnstackableBranchFormat,
218
errors.UnstackableRepositoryFormat,
163
223
# may need to copy content in
165
result_repo = local_repo.clone(
167
revision_id=revision_id)
168
result_repo.set_make_working_trees(local_repo.make_working_trees())
224
repository_policy = result.determine_repository_policy(
225
force_new_repo, stacked_on, self.root_transport.base,
226
require_stacking=require_stacking)
227
make_working_trees = local_repo.make_working_trees()
228
result_repo, is_new_repo = repository_policy.acquire_repository(
229
make_working_trees, local_repo.is_shared())
230
if not require_stacking and repository_policy._require_stacking:
231
require_stacking = True
232
result._format.require_stacking()
233
if is_new_repo and not require_stacking and revision_id is not None:
234
fetch_spec = graph.PendingAncestryResult(
235
[revision_id], local_repo)
236
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
171
result_repo = result.find_repository()
172
# fetch content this dir needs.
173
result_repo.fetch(local_repo, revision_id=revision_id)
174
except errors.NoRepositoryPresent:
175
# needed to make one anyway.
176
result_repo = local_repo.clone(
178
revision_id=revision_id)
179
result_repo.set_make_working_trees(local_repo.make_working_trees())
238
result_repo.fetch(local_repo, revision_id=revision_id)
180
241
# 1 if there is a branch present
181
242
# make sure its content is available in the target repository
184
self.open_branch().clone(result, revision_id=revision_id)
185
except errors.NotBranchError:
188
self.open_workingtree().clone(result)
244
if local_branch is not None:
245
result_branch = local_branch.clone(result, revision_id=revision_id,
246
repository_policy=repository_policy)
248
# Cheaper to check if the target is not local, than to try making
250
result.root_transport.local_abspath('.')
251
if result_repo is None or result_repo.make_working_trees():
252
self.open_workingtree().clone(result)
189
253
except (errors.NoWorkingTree, errors.NotLocalUrl):
193
257
# TODO: This should be given a Transport, and should chdir up; otherwise
194
258
# this will open a new connection.
195
259
def _make_tail(self, url):
196
head, tail = urlutils.split(url)
197
if tail and tail != '.':
198
t = get_transport(head)
201
except errors.FileExists:
260
t = get_transport(url)
204
# TODO: Should take a Transport
206
def create(cls, base, format=None):
264
def create(cls, base, format=None, possible_transports=None):
207
265
"""Create a new BzrDir at the url 'base'.
209
This will call the current default formats initialize with base
210
as the only parameter.
212
267
:param format: If supplied, the format of branch to create. If not
213
268
supplied, the default is used.
269
:param possible_transports: If supplied, a list of transports that
270
can be reused to share a remote connection.
215
272
if cls is not BzrDir:
216
273
raise AssertionError("BzrDir.create always creates the default"
217
274
" format, not one of %r" % cls)
218
head, tail = urlutils.split(base)
219
if tail and tail != '.':
220
t = get_transport(head)
223
except errors.FileExists:
275
t = get_transport(base, possible_transports)
225
277
if format is None:
226
278
format = BzrDirFormat.get_default_format()
227
return format.initialize(safe_unicode(base))
279
return format.initialize_on_transport(t)
282
def find_bzrdirs(transport, evaluate=None, list_current=None):
283
"""Find bzrdirs recursively from current location.
285
This is intended primarily as a building block for more sophisticated
286
functionality, like finding trees under a directory, or finding
287
branches that use a given repository.
288
:param evaluate: An optional callable that yields recurse, value,
289
where recurse controls whether this bzrdir is recursed into
290
and value is the value to yield. By default, all bzrdirs
291
are recursed into, and the return value is the bzrdir.
292
:param list_current: if supplied, use this function to list the current
293
directory, instead of Transport.list_dir
294
:return: a generator of found bzrdirs, or whatever evaluate returns.
296
if list_current is None:
297
def list_current(transport):
298
return transport.list_dir('')
300
def evaluate(bzrdir):
303
pending = [transport]
304
while len(pending) > 0:
305
current_transport = pending.pop()
308
bzrdir = BzrDir.open_from_transport(current_transport)
309
except errors.NotBranchError:
312
recurse, value = evaluate(bzrdir)
315
subdirs = list_current(current_transport)
316
except errors.NoSuchFile:
319
for subdir in sorted(subdirs, reverse=True):
320
pending.append(current_transport.clone(subdir))
323
def find_branches(transport):
324
"""Find all branches under a transport.
326
This will find all branches below the transport, including branches
327
inside other branches. Where possible, it will use
328
Repository.find_branches.
330
To list all the branches that use a particular Repository, see
331
Repository.find_branches
333
def evaluate(bzrdir):
335
repository = bzrdir.open_repository()
336
except errors.NoRepositoryPresent:
339
return False, (None, repository)
341
branch = bzrdir.open_branch()
342
except errors.NotBranchError:
343
return True, (None, None)
345
return True, (branch, None)
347
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
349
branches.extend(repo.find_branches())
350
if branch is not None:
351
branches.append(branch)
354
def destroy_repository(self):
355
"""Destroy the repository in this BzrDir"""
356
raise NotImplementedError(self.destroy_repository)
229
358
def create_branch(self):
230
359
"""Create a branch in this BzrDir.
232
The bzrdirs format will control what branch format is created.
361
The bzrdir's format will control what branch format is created.
233
362
For more control see BranchFormatXX.create(a_bzrdir).
235
364
raise NotImplementedError(self.create_branch)
366
def destroy_branch(self):
367
"""Destroy the branch in this BzrDir"""
368
raise NotImplementedError(self.destroy_branch)
238
371
def create_branch_and_repo(base, force_new_repo=False, format=None):
239
372
"""Create a new BzrDir, Branch and Repository at the url 'base'.
241
This will use the current default BzrDirFormat, and use whatever
374
This will use the current default BzrDirFormat unless one is
375
specified, and use whatever
242
376
repository format that that uses via bzrdir.create_branch and
243
377
create_repository. If a shared repository is available that is used
248
382
:param base: The URL to create the branch at.
249
383
:param force_new_repo: If True a new repository is always created.
384
:param format: If supplied, the format of branch to create. If not
385
supplied, the default is used.
251
387
bzrdir = BzrDir.create(base, format)
252
388
bzrdir._find_or_create_repository(force_new_repo)
253
389
return bzrdir.create_branch()
391
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
392
stack_on_pwd=None, require_stacking=False):
393
"""Return an object representing a policy to use.
395
This controls whether a new repository is created, and the format of
396
that repository, or some existing shared repository used instead.
398
If stack_on is supplied, will not seek a containing shared repo.
400
:param force_new_repo: If True, require a new repository to be created.
401
:param stack_on: If supplied, the location to stack on. If not
402
supplied, a default_stack_on location may be used.
403
:param stack_on_pwd: If stack_on is relative, the location it is
406
def repository_policy(found_bzrdir):
409
config = found_bzrdir.get_config()
411
if config is not None:
412
stack_on = config.get_default_stack_on()
413
if stack_on is not None:
414
stack_on_pwd = found_bzrdir.root_transport.base
416
# does it have a repository ?
418
repository = found_bzrdir.open_repository()
419
except errors.NoRepositoryPresent:
422
if ((found_bzrdir.root_transport.base !=
423
self.root_transport.base) and not repository.is_shared()):
424
# Don't look higher, can't use a higher shared repo.
432
return UseExistingRepository(repository, stack_on,
433
stack_on_pwd, require_stacking=require_stacking), True
435
return CreateRepository(self, stack_on, stack_on_pwd,
436
require_stacking=require_stacking), True
438
if not force_new_repo:
440
policy = self._find_containing(repository_policy)
441
if policy is not None:
445
return UseExistingRepository(self.open_repository(),
446
stack_on, stack_on_pwd,
447
require_stacking=require_stacking)
448
except errors.NoRepositoryPresent:
450
return CreateRepository(self, stack_on, stack_on_pwd,
451
require_stacking=require_stacking)
255
453
def _find_or_create_repository(self, force_new_repo):
256
454
"""Create a new repository if needed, returning the repository."""
258
return self.create_repository()
260
return self.find_repository()
261
except errors.NoRepositoryPresent:
262
return self.create_repository()
455
policy = self.determine_repository_policy(force_new_repo)
456
return policy.acquire_repository()[0]
265
459
def create_branch_convenience(base, force_new_repo=False,
266
force_new_tree=None, format=None):
460
force_new_tree=None, format=None,
461
possible_transports=None):
267
462
"""Create a new BzrDir, Branch and Repository at the url 'base'.
269
464
This is a convenience function - it will use an existing repository
270
465
if possible, can be told explicitly whether to create a working tree or
273
This will use the current default BzrDirFormat, and use whatever
468
This will use the current default BzrDirFormat unless one is
469
specified, and use whatever
274
470
repository format that that uses via bzrdir.create_branch and
275
471
create_repository. If a shared repository is available that is used
276
472
preferentially. Whatever repository is used, its tree creation policy
279
475
The created Branch object is returned.
280
476
If a working tree cannot be made due to base not being a file:// url,
281
no error is raised unless force_new_tree is True, in which case no
477
no error is raised unless force_new_tree is True, in which case no
282
478
data is created on disk and NotLocalUrl is raised.
284
480
:param base: The URL to create the branch at.
285
481
:param force_new_repo: If True a new repository is always created.
286
:param force_new_tree: If True or False force creation of a tree or
482
:param force_new_tree: If True or False force creation of a tree or
287
483
prevent such creation respectively.
288
:param format: Override for the for the bzrdir format to create
484
:param format: Override for the bzrdir format to create.
485
:param possible_transports: An optional reusable transports list.
290
487
if force_new_tree:
291
488
# check for non local urls
292
t = get_transport(safe_unicode(base))
293
if not isinstance(t, LocalTransport):
489
t = get_transport(base, possible_transports)
490
if not isinstance(t, local.LocalTransport):
294
491
raise errors.NotLocalUrl(base)
295
bzrdir = BzrDir.create(base, format)
492
bzrdir = BzrDir.create(base, format, possible_transports)
296
493
repo = bzrdir._find_or_create_repository(force_new_repo)
297
494
result = bzrdir.create_branch()
298
if force_new_tree or (repo.make_working_trees() and
495
if force_new_tree or (repo.make_working_trees() and
299
496
force_new_tree is None):
301
498
bzrdir.create_workingtree()
302
499
except errors.NotLocalUrl:
307
def create_repository(base, shared=False, format=None):
308
"""Create a new BzrDir and Repository at the url 'base'.
310
If no format is supplied, this will default to the current default
311
BzrDirFormat by default, and use whatever repository format that that
312
uses for bzrdirformat.create_repository.
314
:param shared: Create a shared repository rather than a standalone
316
The Repository object is returned.
318
This must be overridden as an instance method in child classes, where
319
it should take no parameters and construct whatever repository format
320
that child class desires.
322
bzrdir = BzrDir.create(base, format)
323
return bzrdir.create_repository(shared)
326
504
def create_standalone_workingtree(base, format=None):
329
507
'base' must be a local path or a file:// url.
331
This will use the current default BzrDirFormat, and use whatever
509
This will use the current default BzrDirFormat unless one is
510
specified, and use whatever
332
511
repository format that that uses for bzrdirformat.create_workingtree,
333
512
create_branch and create_repository.
514
:param format: Override for the bzrdir format to create.
335
515
:return: The WorkingTree object.
337
t = get_transport(safe_unicode(base))
338
if not isinstance(t, LocalTransport):
517
t = get_transport(base)
518
if not isinstance(t, local.LocalTransport):
339
519
raise errors.NotLocalUrl(base)
340
bzrdir = BzrDir.create_branch_and_repo(safe_unicode(base),
520
bzrdir = BzrDir.create_branch_and_repo(base,
341
521
force_new_repo=True,
342
522
format=format).bzrdir
343
523
return bzrdir.create_workingtree()
345
def create_workingtree(self, revision_id=None):
525
def create_workingtree(self, revision_id=None, from_branch=None,
526
accelerator_tree=None, hardlink=False):
346
527
"""Create a working tree at this BzrDir.
348
revision_id: create it as of this revision id.
529
:param revision_id: create it as of this revision id.
530
:param from_branch: override bzrdir branch (for lightweight checkouts)
531
:param accelerator_tree: A tree which can be used for retrieving file
532
contents more quickly than the revision tree, i.e. a workingtree.
533
The revision tree will be used for cases where accelerator_tree's
534
content is different.
350
536
raise NotImplementedError(self.create_workingtree)
352
def retire_bzrdir(self):
538
def backup_bzrdir(self):
539
"""Backup this bzr control directory.
541
:return: Tuple with old path name and new path name
543
pb = ui.ui_factory.nested_progress_bar()
545
# FIXME: bug 300001 -- the backup fails if the backup directory
546
# already exists, but it should instead either remove it or make
547
# a new backup directory.
549
# FIXME: bug 262450 -- the backup directory should have the same
550
# permissions as the .bzr directory (probably a bug in copy_tree)
551
old_path = self.root_transport.abspath('.bzr')
552
new_path = self.root_transport.abspath('backup.bzr')
553
pb.note('making backup of %s' % (old_path,))
554
pb.note(' to %s' % (new_path,))
555
self.root_transport.copy_tree('.bzr', 'backup.bzr')
556
return (old_path, new_path)
560
def retire_bzrdir(self, limit=10000):
353
561
"""Permanently disable the bzrdir.
355
563
This is done by renaming it to give the user some ability to recover
384
598
raise NotImplementedError(self.destroy_workingtree_metadata)
600
def _find_containing(self, evaluate):
601
"""Find something in a containing control directory.
603
This method will scan containing control dirs, until it finds what
604
it is looking for, decides that it will never find it, or runs out
605
of containing control directories to check.
607
It is used to implement find_repository and
608
determine_repository_policy.
610
:param evaluate: A function returning (value, stop). If stop is True,
611
the value will be returned.
615
result, stop = evaluate(found_bzrdir)
618
next_transport = found_bzrdir.root_transport.clone('..')
619
if (found_bzrdir.root_transport.base == next_transport.base):
620
# top of the file system
622
# find the next containing bzrdir
624
found_bzrdir = BzrDir.open_containing_from_transport(
626
except errors.NotBranchError:
386
629
def find_repository(self):
387
"""Find the repository that should be used for a_bzrdir.
630
"""Find the repository that should be used.
389
632
This does not require a branch as we use it to find the repo for
390
633
new branches as well as to hook existing branches up to their
394
return self.open_repository()
395
except errors.NoRepositoryPresent:
397
next_transport = self.root_transport.clone('..')
399
# find the next containing bzrdir
401
found_bzrdir = BzrDir.open_containing_from_transport(
403
except errors.NotBranchError:
405
raise errors.NoRepositoryPresent(self)
636
def usable_repository(found_bzrdir):
406
637
# does it have a repository ?
408
639
repository = found_bzrdir.open_repository()
409
640
except errors.NoRepositoryPresent:
410
next_transport = found_bzrdir.root_transport.clone('..')
411
if (found_bzrdir.root_transport.base == next_transport.base):
412
# top of the file system
416
if ((found_bzrdir.root_transport.base ==
417
self.root_transport.base) or repository.is_shared()):
642
if found_bzrdir.root_transport.base == self.root_transport.base:
643
return repository, True
644
elif repository.is_shared():
645
return repository, True
420
raise errors.NoRepositoryPresent(self)
421
raise errors.NoRepositoryPresent(self)
649
found_repo = self._find_containing(usable_repository)
650
if found_repo is None:
651
raise errors.NoRepositoryPresent(self)
654
def get_branch_reference(self):
655
"""Return the referenced URL for the branch in this bzrdir.
657
:raises NotBranchError: If there is no Branch.
658
:return: The URL the branch in this bzrdir references if it is a
659
reference branch, or None for regular branches.
423
663
def get_branch_transport(self, branch_format):
424
664
"""Get the transport for use by branch format in this BzrDir.
427
667
IncompatibleFormat if the branch format they are given has
428
668
a format string, and vice versa.
430
If branch_format is None, the transport is returned with no
431
checking. if it is not None, then the returned transport is
670
If branch_format is None, the transport is returned with no
671
checking. If it is not None, then the returned transport is
432
672
guaranteed to point to an existing directory ready for use.
434
674
raise NotImplementedError(self.get_branch_transport)
676
def _find_creation_modes(self):
677
"""Determine the appropriate modes for files and directories.
679
They're always set to be consistent with the base directory,
680
assuming that this transport allows setting modes.
682
# TODO: Do we need or want an option (maybe a config setting) to turn
683
# this off or override it for particular locations? -- mbp 20080512
684
if self._mode_check_done:
686
self._mode_check_done = True
688
st = self.transport.stat('.')
689
except errors.TransportNotPossible:
690
self._dir_mode = None
691
self._file_mode = None
693
# Check the directory mode, but also make sure the created
694
# directories and files are read-write for this user. This is
695
# mostly a workaround for filesystems which lie about being able to
696
# write to a directory (cygwin & win32)
697
if (st.st_mode & 07777 == 00000):
698
# FTP allows stat but does not return dir/file modes
699
self._dir_mode = None
700
self._file_mode = None
702
self._dir_mode = (st.st_mode & 07777) | 00700
703
# Remove the sticky and execute bits for files
704
self._file_mode = self._dir_mode & ~07111
706
def _get_file_mode(self):
707
"""Return Unix mode for newly created files, or None.
709
if not self._mode_check_done:
710
self._find_creation_modes()
711
return self._file_mode
713
def _get_dir_mode(self):
714
"""Return Unix mode for newly created directories, or None.
716
if not self._mode_check_done:
717
self._find_creation_modes()
718
return self._dir_mode
436
720
def get_repository_transport(self, repository_format):
437
721
"""Get the transport for use by repository format in this BzrDir.
506
796
def open_unsupported(base):
507
797
"""Open a branch which is not supported."""
508
798
return BzrDir.open(base, _unsupported=True)
511
def open(base, _unsupported=False):
512
"""Open an existing bzrdir, rooted at 'base' (url)
514
_unsupported is a private parameter to the BzrDir class.
801
def open(base, _unsupported=False, possible_transports=None):
802
"""Open an existing bzrdir, rooted at 'base' (url).
804
:param _unsupported: a private parameter to the BzrDir class.
516
t = get_transport(base)
806
t = get_transport(base, possible_transports=possible_transports)
517
807
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
520
def open_from_transport(transport, _unsupported=False):
810
def open_from_transport(transport, _unsupported=False,
811
_server_formats=True):
521
812
"""Open a bzrdir within a particular directory.
523
814
:param transport: Transport containing the bzrdir.
524
815
:param _unsupported: private.
817
for hook in BzrDir.hooks['pre_open']:
819
# Keep initial base since 'transport' may be modified while following
526
821
base = transport.base
528
822
def find_format(transport):
529
return transport, BzrDirFormat.find_format(transport)
823
return transport, BzrDirFormat.find_format(
824
transport, _server_formats=_server_formats)
531
826
def redirected(transport, e, redirection_notice):
532
qualified_source = e.get_source_url()
533
relpath = transport.relpath(qualified_source)
534
if not e.target.endswith(relpath):
535
# Not redirected to a branch-format, not a branch
536
raise errors.NotBranchError(path=e.target)
537
target = e.target[:-len(relpath)]
827
redirected_transport = transport._redirected_to(e.source, e.target)
828
if redirected_transport is None:
829
raise errors.NotBranchError(base)
538
830
note('%s is%s redirected to %s',
539
transport.base, e.permanently, target)
540
# Let's try with a new transport
541
qualified_target = e.get_target_url()[:-len(relpath)]
542
# FIXME: If 'transport' has a qualifier, this should
543
# be applied again to the new transport *iff* the
544
# schemes used are the same. It's a bit tricky to
545
# verify, so I'll punt for now
547
return get_transport(target)
831
transport.base, e.permanently, redirected_transport.base)
832
return redirected_transport
550
835
transport, format = do_catching_redirections(find_format,
615
933
relpath is the portion of the path that is contained by the branch.
617
935
bzrdir, relpath = klass.open_containing(location)
619
tree = bzrdir.open_workingtree()
620
except (errors.NoWorkingTree, errors.NotLocalUrl):
622
branch = bzrdir.open_branch()
936
tree, branch = bzrdir._get_tree_branch()
625
937
return tree, branch, relpath
940
def open_containing_tree_branch_or_repository(klass, location):
941
"""Return the working tree, branch and repo contained by a location.
943
Returns (tree, branch, repository, relpath).
944
If there is no tree containing the location, tree will be None.
945
If there is no branch containing the location, branch will be None.
946
If there is no repository containing the location, repository will be
948
relpath is the portion of the path that is contained by the innermost
951
If no tree, branch or repository is found, a NotBranchError is raised.
953
bzrdir, relpath = klass.open_containing(location)
955
tree, branch = bzrdir._get_tree_branch()
956
except errors.NotBranchError:
958
repo = bzrdir.find_repository()
959
return None, None, repo, relpath
960
except (errors.NoRepositoryPresent):
961
raise errors.NotBranchError(location)
962
return tree, branch, branch.repository, relpath
627
964
def open_repository(self, _unsupported=False):
628
965
"""Open the repository object at this BzrDir if one is present.
630
This will not follow the Branch object pointer - its strictly a direct
967
This will not follow the Branch object pointer - it's strictly a direct
631
968
open facility. Most client code should use open_branch().repository to
632
969
get at a repository.
634
_unsupported is a private parameter, not part of the api.
971
:param _unsupported: a private parameter, not part of the api.
635
972
TODO: static convenience version of this?
637
974
raise NotImplementedError(self.open_repository)
639
def open_workingtree(self, _unsupported=False):
976
def open_workingtree(self, _unsupported=False,
977
recommend_upgrade=True, from_branch=None):
640
978
"""Open the workingtree object at this BzrDir if one is present.
642
TODO: static convenience version of this?
980
:param recommend_upgrade: Optional keyword parameter, when True (the
981
default), emit through the ui module a recommendation that the user
982
upgrade the working tree when the workingtree being opened is old
983
(but still fully supported).
984
:param from_branch: override bzrdir branch (for lightweight checkouts)
644
986
raise NotImplementedError(self.open_workingtree)
646
988
def has_branch(self):
647
989
"""Tell if this bzrdir contains a branch.
649
991
Note: if you're going to open the branch, you should just go ahead
650
and try, and not ask permission first. (This method just opens the
651
branch and discards it, and that's somewhat expensive.)
992
and try, and not ask permission first. (This method just opens the
993
branch and discards it, and that's somewhat expensive.)
654
996
self.open_branch()
728
1093
if revision_id is not None, then the clone operation may tune
729
1094
itself to download less data.
1095
:param accelerator_tree: A tree which can be used for retrieving file
1096
contents more quickly than the revision tree, i.e. a workingtree.
1097
The revision tree will be used for cases where accelerator_tree's
1098
content is different.
1099
:param hardlink: If true, hard-link files from accelerator_tree,
1101
:param stacked: If true, create a stacked branch referring to the
1102
location of this control directory.
1103
:param create_tree_if_local: If true, a working-tree will be created
1104
when working locally.
732
cloning_format = self.cloning_metadir()
733
result = cloning_format.initialize(url)
735
source_branch = self.open_branch()
1106
target_transport = get_transport(url, possible_transports)
1107
target_transport.ensure_base()
1108
cloning_format = self.cloning_metadir(stacked)
1109
# Create/update the result branch
1110
result = cloning_format.initialize_on_transport(target_transport)
1111
# if a stacked branch wasn't requested, we don't create one
1112
# even if the origin was stacked
1113
stacked_branch_url = None
1114
if source_branch is not None:
1116
stacked_branch_url = self.root_transport.base
736
1117
source_repository = source_branch.repository
737
except errors.NotBranchError:
740
source_repository = self.open_repository()
741
except errors.NoRepositoryPresent:
742
source_repository = None
747
result_repo = result.find_repository()
748
except errors.NoRepositoryPresent:
750
if source_repository is None and result_repo is not None:
752
elif source_repository is None and result_repo is None:
753
# no repo available, make a new one
754
result.create_repository()
755
elif source_repository is not None and result_repo is None:
756
# have source, and want to make a new target repo
757
# we don't clone the repo because that preserves attributes
758
# like is_shared(), and we have not yet implemented a
759
# repository sprout().
760
result_repo = result.create_repository()
761
if result_repo is not None:
762
# fetch needed content into target.
763
if source_repository is not None:
1120
source_branch = self.open_branch()
1121
source_repository = source_branch.repository
1123
stacked_branch_url = self.root_transport.base
1124
except errors.NotBranchError:
1125
source_branch = None
1127
source_repository = self.open_repository()
1128
except errors.NoRepositoryPresent:
1129
source_repository = None
1130
repository_policy = result.determine_repository_policy(
1131
force_new_repo, stacked_branch_url, require_stacking=stacked)
1132
result_repo, is_new_repo = repository_policy.acquire_repository()
1133
if is_new_repo and revision_id is not None and not stacked:
1134
fetch_spec = graph.PendingAncestryResult(
1135
[revision_id], source_repository)
1138
if source_repository is not None:
1139
# Fetch while stacked to prevent unstacked fetch from
1141
if fetch_spec is None:
764
1142
result_repo.fetch(source_repository, revision_id=revision_id)
765
if source_branch is not None:
766
source_branch.sprout(result, revision_id=revision_id)
1144
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
1146
if source_branch is None:
1147
# this is for sprouting a bzrdir without a branch; is that
1149
# Not especially, but it's part of the contract.
1150
result_branch = result.create_branch()
768
result.create_branch()
769
# TODO: jam 20060426 we probably need a test in here in the
770
# case that the newly sprouted branch is a remote one
771
if result_repo is None or result_repo.make_working_trees():
772
wt = result.create_workingtree()
1152
result_branch = source_branch.sprout(result,
1153
revision_id=revision_id, repository_policy=repository_policy)
1154
mutter("created new branch %r" % (result_branch,))
1156
# Create/update the result working tree
1157
if (create_tree_if_local and
1158
isinstance(target_transport, local.LocalTransport) and
1159
(result_repo is None or result_repo.make_working_trees())):
1160
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
775
1164
if wt.path2id('') is None:
801
1192
sublocation = source_branch.reference_parent(file_id, path)
802
1193
sublocation.bzrdir.sprout(target,
803
1194
basis.get_reference_revision(file_id, path),
804
force_new_repo=force_new_repo, recurse=recurse)
1195
force_new_repo=force_new_repo, recurse=recurse,
806
1198
if basis is not None:
1202
def push_branch(self, source, revision_id=None, overwrite=False,
1204
"""Push the source branch into this BzrDir."""
1206
# If we can open a branch, use its direct repository, otherwise see
1207
# if there is a repository without a branch.
1209
br_to = self.open_branch()
1210
except errors.NotBranchError:
1211
# Didn't find a branch, can we find a repository?
1212
repository_to = self.find_repository()
1214
# Found a branch, so we must have found a repository
1215
repository_to = br_to.repository
1217
push_result = PushResult()
1218
push_result.source_branch = source
1220
# We have a repository but no branch, copy the revisions, and then
1222
repository_to.fetch(source.repository, revision_id=revision_id)
1223
br_to = source.clone(self, revision_id=revision_id)
1224
if source.get_push_location() is None or remember:
1225
source.set_push_location(br_to.base)
1226
push_result.stacked_on = None
1227
push_result.branch_push_result = None
1228
push_result.old_revno = None
1229
push_result.old_revid = _mod_revision.NULL_REVISION
1230
push_result.target_branch = br_to
1231
push_result.master_branch = None
1232
push_result.workingtree_updated = False
1234
# We have successfully opened the branch, remember if necessary:
1235
if source.get_push_location() is None or remember:
1236
source.set_push_location(br_to.base)
1238
tree_to = self.open_workingtree()
1239
except errors.NotLocalUrl:
1240
push_result.branch_push_result = source.push(br_to,
1241
overwrite, stop_revision=revision_id)
1242
push_result.workingtree_updated = False
1243
except errors.NoWorkingTree:
1244
push_result.branch_push_result = source.push(br_to,
1245
overwrite, stop_revision=revision_id)
1246
push_result.workingtree_updated = None # Not applicable
1248
tree_to.lock_write()
1250
push_result.branch_push_result = source.push(
1251
tree_to.branch, overwrite, stop_revision=revision_id)
1255
push_result.workingtree_updated = True
1256
push_result.old_revno = push_result.branch_push_result.old_revno
1257
push_result.old_revid = push_result.branch_push_result.old_revid
1258
push_result.target_branch = \
1259
push_result.branch_push_result.target_branch
1263
class BzrDirHooks(hooks.Hooks):
1264
"""Hooks for BzrDir operations."""
1267
"""Create the default hooks."""
1268
hooks.Hooks.__init__(self)
1269
self.create_hook(hooks.HookPoint('pre_open',
1270
"Invoked before attempting to open a BzrDir with the transport "
1271
"that the open will use.", (1, 14), None))
1273
# install the default hooks
1274
BzrDir.hooks = BzrDirHooks()
811
1277
class BzrDirPreSplitOut(BzrDir):
812
1278
"""A common class for the all-in-one formats."""
825
1289
"""Pre-splitout bzrdirs do not suffer from stale locks."""
826
1290
raise NotImplementedError(self.break_lock)
828
def clone(self, url, revision_id=None, force_new_repo=False):
829
"""See BzrDir.clone()."""
830
from bzrlib.workingtree import WorkingTreeFormat2
1292
def cloning_metadir(self, require_stacking=False):
1293
"""Produce a metadir suitable for cloning with."""
1294
if require_stacking:
1295
return format_registry.make_bzrdir('1.6')
1296
return self._format.__class__()
1298
def clone(self, url, revision_id=None, force_new_repo=False,
1299
preserve_stacking=False):
1300
"""See BzrDir.clone().
1302
force_new_repo has no effect, since this family of formats always
1303
require a new repository.
1304
preserve_stacking has no effect, since no source branch using this
1305
family of formats can be stacked, so there is no stacking to preserve.
831
1307
self._make_tail(url)
832
1308
result = self._format._initialize_for_clone(url)
833
1309
self.open_repository().clone(result, revision_id=revision_id)
834
1310
from_branch = self.open_branch()
835
1311
from_branch.clone(result, revision_id=revision_id)
837
self.open_workingtree().clone(result)
1313
tree = self.open_workingtree()
838
1314
except errors.NotLocalUrl:
839
1315
# make a new one, this format always has to have one.
841
WorkingTreeFormat2().initialize(result)
842
except errors.NotLocalUrl:
843
# but we cannot do it for remote trees.
844
to_branch = result.open_branch()
845
WorkingTreeFormat2().stub_initialize_remote(to_branch.control_files)
1316
result._init_workingtree()
848
1321
def create_branch(self):
849
1322
"""See BzrDir.create_branch."""
850
return self.open_branch()
1323
return self._format.get_branch_format().initialize(self)
1325
def destroy_branch(self):
1326
"""See BzrDir.destroy_branch."""
1327
raise errors.UnsupportedOperation(self.destroy_branch, self)
852
1329
def create_repository(self, shared=False):
853
1330
"""See BzrDir.create_repository."""
1024
1545
"""See BzrDir.create_branch."""
1025
1546
return self._format.get_branch_format().initialize(self)
1548
def destroy_branch(self):
1549
"""See BzrDir.create_branch."""
1550
self.transport.delete_tree('branch')
1027
1552
def create_repository(self, shared=False):
1028
1553
"""See BzrDir.create_repository."""
1029
1554
return self._format.repository_format.initialize(self, shared)
1031
def create_workingtree(self, revision_id=None):
1556
def destroy_repository(self):
1557
"""See BzrDir.destroy_repository."""
1558
self.transport.delete_tree('repository')
1560
def create_workingtree(self, revision_id=None, from_branch=None,
1561
accelerator_tree=None, hardlink=False):
1032
1562
"""See BzrDir.create_workingtree."""
1033
from bzrlib.workingtree import WorkingTreeFormat
1034
return self._format.workingtree_format.initialize(self, revision_id)
1563
return self._format.workingtree_format.initialize(
1564
self, revision_id, from_branch=from_branch,
1565
accelerator_tree=accelerator_tree, hardlink=hardlink)
1036
1567
def destroy_workingtree(self):
1037
1568
"""See BzrDir.destroy_workingtree."""
1038
1569
wt = self.open_workingtree(recommend_upgrade=False)
1039
1570
repository = wt.branch.repository
1040
1571
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1041
wt.revert([], old_tree=empty)
1572
wt.revert(old_tree=empty)
1042
1573
self.destroy_workingtree_metadata()
1044
1575
def destroy_workingtree_metadata(self):
1045
1576
self.transport.delete_tree('checkout')
1578
def find_branch_format(self):
1579
"""Find the branch 'format' for this bzrdir.
1581
This might be a synthetic object for e.g. RemoteBranch and SVN.
1583
from bzrlib.branch import BranchFormat
1584
return BranchFormat.find_format(self)
1047
1586
def _get_mkdir_mode(self):
1048
1587
"""Figure out the mode to use when creating a bzrdir subdir."""
1049
1588
temp_control = lockable_files.LockableFiles(self.transport, '',
1050
1589
lockable_files.TransportLock)
1051
1590
return temp_control._dir_mode
1592
def get_branch_reference(self):
1593
"""See BzrDir.get_branch_reference()."""
1594
from bzrlib.branch import BranchFormat
1595
format = BranchFormat.find_format(self)
1596
return format.get_reference(self)
1053
1598
def get_branch_transport(self, branch_format):
1054
1599
"""See BzrDir.get_branch_transport()."""
1055
1600
if branch_format is None:
1590
2236
"""See BzrDirFormat.get_format_description()."""
1591
2237
return "Meta directory format 1"
2239
def network_name(self):
2240
return self.get_format_string()
1593
2242
def _open(self, transport):
1594
2243
"""See BzrDirFormat._open."""
1595
2244
return BzrDirMeta1(transport, self)
1597
2246
def __return_repository_format(self):
1598
2247
"""Circular import protection."""
1599
if getattr(self, '_repository_format', None):
2248
if self._repository_format:
1600
2249
return self._repository_format
1601
2250
from bzrlib.repository import RepositoryFormat
1602
2251
return RepositoryFormat.get_default_format()
1604
def __set_repository_format(self, value):
1605
"""Allow changint the repository format for metadir formats."""
2253
def _set_repository_format(self, value):
2254
"""Allow changing the repository format for metadir formats."""
1606
2255
self._repository_format = value
1608
repository_format = property(__return_repository_format, __set_repository_format)
2257
repository_format = property(__return_repository_format,
2258
_set_repository_format)
2260
def _supply_sub_formats_to(self, other_format):
2261
"""Give other_format the same values for sub formats as this has.
2263
This method is expected to be used when parameterising a
2264
RemoteBzrDirFormat instance with the parameters from a
2265
BzrDirMetaFormat1 instance.
2267
:param other_format: other_format is a format which should be
2268
compatible with whatever sub formats are supported by self.
2271
if getattr(self, '_repository_format', None) is not None:
2272
other_format.repository_format = self.repository_format
2273
if self._branch_format is not None:
2274
other_format._branch_format = self._branch_format
2275
if self._workingtree_format is not None:
2276
other_format.workingtree_format = self.workingtree_format
1610
2278
def __get_workingtree_format(self):
1611
2279
if self._workingtree_format is None:
2142
2805
# TODO: conversions of Branch and Tree should be done by
2143
2806
# InterXFormat lookups
2144
2807
if (isinstance(tree, workingtree.WorkingTree3) and
2145
not isinstance(tree, workingtree_4.WorkingTree4) and
2808
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2146
2809
isinstance(self.target_format.workingtree_format,
2147
workingtree_4.WorkingTreeFormat4)):
2810
workingtree_4.DirStateWorkingTreeFormat)):
2148
2811
workingtree_4.Converter3to4().convert(tree)
2812
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2813
not isinstance(tree, workingtree_4.WorkingTree5) and
2814
isinstance(self.target_format.workingtree_format,
2815
workingtree_4.WorkingTreeFormat5)):
2816
workingtree_4.Converter4to5().convert(tree)
2817
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2818
not isinstance(tree, workingtree_4.WorkingTree6) and
2819
isinstance(self.target_format.workingtree_format,
2820
workingtree_4.WorkingTreeFormat6)):
2821
workingtree_4.Converter4or5to6().convert(tree)
2149
2822
return to_convert
2825
# This is not in remote.py because it's small, and needs to be registered.
2826
# Putting it in remote.py creates a circular import problem.
2827
# we can make it a lazy object if the control formats is turned into something
2829
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2830
"""Format representing bzrdirs accessed via a smart server"""
2833
BzrDirMetaFormat1.__init__(self)
2834
self._network_name = None
2836
def get_format_description(self):
2837
return 'bzr remote bzrdir'
2839
def get_format_string(self):
2840
raise NotImplementedError(self.get_format_string)
2842
def network_name(self):
2843
if self._network_name:
2844
return self._network_name
2846
raise AssertionError("No network name set.")
2849
def probe_transport(klass, transport):
2850
"""Return a RemoteBzrDirFormat object if it looks possible."""
2852
medium = transport.get_smart_medium()
2853
except (NotImplementedError, AttributeError,
2854
errors.TransportNotPossible, errors.NoSmartMedium,
2855
errors.SmartProtocolError):
2856
# no smart server, so not a branch for this format type.
2857
raise errors.NotBranchError(path=transport.base)
2859
# Decline to open it if the server doesn't support our required
2860
# version (3) so that the VFS-based transport will do it.
2861
if medium.should_probe():
2863
server_version = medium.protocol_version()
2864
except errors.SmartProtocolError:
2865
# Apparently there's no usable smart server there, even though
2866
# the medium supports the smart protocol.
2867
raise errors.NotBranchError(path=transport.base)
2868
if server_version != '2':
2869
raise errors.NotBranchError(path=transport.base)
2872
def initialize_on_transport(self, transport):
2874
# hand off the request to the smart server
2875
client_medium = transport.get_smart_medium()
2876
except errors.NoSmartMedium:
2877
# TODO: lookup the local format from a server hint.
2878
local_dir_format = BzrDirMetaFormat1()
2879
return local_dir_format.initialize_on_transport(transport)
2880
client = _SmartClient(client_medium)
2881
path = client.remote_path_from_transport(transport)
2882
response = client.call('BzrDirFormat.initialize', path)
2883
if response[0] != 'ok':
2884
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2885
format = RemoteBzrDirFormat()
2886
self._supply_sub_formats_to(format)
2887
return remote.RemoteBzrDir(transport, format)
2889
def _open(self, transport):
2890
return remote.RemoteBzrDir(transport, self)
2892
def __eq__(self, other):
2893
if not isinstance(other, RemoteBzrDirFormat):
2895
return self.get_format_description() == other.get_format_description()
2897
def __return_repository_format(self):
2898
# Always return a RemoteRepositoryFormat object, but if a specific bzr
2899
# repository format has been asked for, tell the RemoteRepositoryFormat
2900
# that it should use that for init() etc.
2901
result = remote.RemoteRepositoryFormat()
2902
custom_format = getattr(self, '_repository_format', None)
2904
if isinstance(custom_format, remote.RemoteRepositoryFormat):
2905
return custom_format
2907
# We will use the custom format to create repositories over the
2908
# wire; expose its details like rich_root_data for code to
2910
result._custom_format = custom_format
2913
def get_branch_format(self):
2914
result = BzrDirMetaFormat1.get_branch_format(self)
2915
if not isinstance(result, remote.RemoteBranchFormat):
2916
new_result = remote.RemoteBranchFormat()
2917
new_result._custom_format = result
2919
self.set_branch_format(new_result)
2923
repository_format = property(__return_repository_format,
2924
BzrDirMetaFormat1._set_repository_format) #.im_func)
2927
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2152
2930
class BzrDirFormatInfo(object):
2154
def __init__(self, native, deprecated, hidden):
2932
def __init__(self, native, deprecated, hidden, experimental):
2155
2933
self.deprecated = deprecated
2156
2934
self.native = native
2157
2935
self.hidden = hidden
2936
self.experimental = experimental
2160
2939
class BzrDirFormatRegistry(registry.Registry):
2161
2940
"""Registry of user-selectable BzrDir subformats.
2163
2942
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2164
2943
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2947
"""Create a BzrDirFormatRegistry."""
2948
self._aliases = set()
2949
self._registration_order = list()
2950
super(BzrDirFormatRegistry, self).__init__()
2953
"""Return a set of the format names which are aliases."""
2954
return frozenset(self._aliases)
2167
2956
def register_metadir(self, key,
2168
2957
repository_format, help, native=True, deprecated=False,
2169
2958
branch_format=None,
2170
2959
tree_format=None,
2172
2963
"""Register a metadir subformat.
2174
2965
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2175
by the Repository format.
2966
by the Repository/Branch/WorkingTreeformats.
2177
2968
:param repository_format: The fully-qualified repository format class
2178
2969
name as a string.
2206
2997
if repository_format is not None:
2207
2998
bd.repository_format = _load(repository_format)
2209
self.register(key, helper, help, native, deprecated, hidden)
3000
self.register(key, helper, help, native, deprecated, hidden,
3001
experimental, alias)
2211
3003
def register(self, key, factory, help, native=True, deprecated=False,
3004
hidden=False, experimental=False, alias=False):
2213
3005
"""Register a BzrDirFormat factory.
2215
3007
The factory must be a callable that takes one parameter: the key.
2216
3008
It must produce an instance of the BzrDirFormat when called.
2218
3010
This function mainly exists to prevent the info object from being
2219
3011
supplied directly.
2221
registry.Registry.register(self, key, factory, help,
2222
BzrDirFormatInfo(native, deprecated, hidden))
3013
registry.Registry.register(self, key, factory, help,
3014
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3016
self._aliases.add(key)
3017
self._registration_order.append(key)
2224
3019
def register_lazy(self, key, module_name, member_name, help, native=True,
2225
deprecated=False, hidden=False):
2226
registry.Registry.register_lazy(self, key, module_name, member_name,
2227
help, BzrDirFormatInfo(native, deprecated, hidden))
3020
deprecated=False, hidden=False, experimental=False, alias=False):
3021
registry.Registry.register_lazy(self, key, module_name, member_name,
3022
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3024
self._aliases.add(key)
3025
self._registration_order.append(key)
2229
3027
def set_default(self, key):
2230
3028
"""Set the 'default' key to be a clone of the supplied key.
2232
3030
This method must be called once and only once.
2234
registry.Registry.register(self, 'default', self.get(key),
3032
registry.Registry.register(self, 'default', self.get(key),
2235
3033
self.get_help(key), info=self.get_info(key))
3034
self._aliases.add('default')
2237
3036
def set_default_repository(self, key):
2238
3037
"""Set the FormatRegistry default and Repository default.
2240
3039
This is a transitional method while Repository.set_default_format
2272
3064
def wrapped(key, help, info):
2273
3065
if info.native:
2274
3066
help = '(native) ' + help
2275
return ' %s:\n%s\n\n' % (key,
2276
textwrap.fill(help, initial_indent=' ',
3067
return ':%s:\n%s\n\n' % (key,
3068
textwrap.fill(help, initial_indent=' ',
2277
3069
subsequent_indent=' '))
2278
output += wrapped('%s/default' % default_realkey, default_help,
2279
self.get_info('default'))
3070
if default_realkey is not None:
3071
output += wrapped(default_realkey, '(default) %s' % default_help,
3072
self.get_info('default'))
2280
3073
deprecated_pairs = []
3074
experimental_pairs = []
2281
3075
for key, help in help_pairs:
2282
3076
info = self.get_info(key)
2283
3077
if info.hidden:
2285
3079
elif info.deprecated:
2286
3080
deprecated_pairs.append((key, help))
3081
elif info.experimental:
3082
experimental_pairs.append((key, help))
2288
3084
output += wrapped(key, help, info)
3085
output += "\nSee ``bzr help formats`` for more about storage formats."
3087
if len(experimental_pairs) > 0:
3088
other_output += "Experimental formats are shown below.\n\n"
3089
for key, help in experimental_pairs:
3090
info = self.get_info(key)
3091
other_output += wrapped(key, help, info)
3094
"No experimental formats are available.\n\n"
2289
3095
if len(deprecated_pairs) > 0:
2290
output += "Deprecated formats\n------------------\n\n"
3096
other_output += "\nDeprecated formats are shown below.\n\n"
2291
3097
for key, help in deprecated_pairs:
2292
3098
info = self.get_info(key)
2293
output += wrapped(key, help, info)
3099
other_output += wrapped(key, help, info)
3102
"\nNo deprecated formats are available.\n\n"
3104
"\nSee ``bzr help formats`` for more about storage formats."
3106
if topic == 'other-formats':
3112
class RepositoryAcquisitionPolicy(object):
3113
"""Abstract base class for repository acquisition policies.
3115
A repository acquisition policy decides how a BzrDir acquires a repository
3116
for a branch that is being created. The most basic policy decision is
3117
whether to create a new repository or use an existing one.
3119
def __init__(self, stack_on, stack_on_pwd, require_stacking):
3122
:param stack_on: A location to stack on
3123
:param stack_on_pwd: If stack_on is relative, the location it is
3125
:param require_stacking: If True, it is a failure to not stack.
3127
self._stack_on = stack_on
3128
self._stack_on_pwd = stack_on_pwd
3129
self._require_stacking = require_stacking
3131
def configure_branch(self, branch):
3132
"""Apply any configuration data from this policy to the branch.
3134
Default implementation sets repository stacking.
3136
if self._stack_on is None:
3138
if self._stack_on_pwd is None:
3139
stack_on = self._stack_on
3142
stack_on = urlutils.rebase_url(self._stack_on,
3144
branch.bzrdir.root_transport.base)
3145
except errors.InvalidRebaseURLs:
3146
stack_on = self._get_full_stack_on()
3148
branch.set_stacked_on_url(stack_on)
3149
except (errors.UnstackableBranchFormat,
3150
errors.UnstackableRepositoryFormat):
3151
if self._require_stacking:
3154
def _get_full_stack_on(self):
3155
"""Get a fully-qualified URL for the stack_on location."""
3156
if self._stack_on is None:
3158
if self._stack_on_pwd is None:
3159
return self._stack_on
3161
return urlutils.join(self._stack_on_pwd, self._stack_on)
3163
def _add_fallback(self, repository, possible_transports=None):
3164
"""Add a fallback to the supplied repository, if stacking is set."""
3165
stack_on = self._get_full_stack_on()
3166
if stack_on is None:
3168
stacked_dir = BzrDir.open(stack_on,
3169
possible_transports=possible_transports)
3171
stacked_repo = stacked_dir.open_branch().repository
3172
except errors.NotBranchError:
3173
stacked_repo = stacked_dir.open_repository()
3175
repository.add_fallback_repository(stacked_repo)
3176
except errors.UnstackableRepositoryFormat:
3177
if self._require_stacking:
3180
self._require_stacking = True
3182
def acquire_repository(self, make_working_trees=None, shared=False):
3183
"""Acquire a repository for this bzrdir.
3185
Implementations may create a new repository or use a pre-exising
3187
:param make_working_trees: If creating a repository, set
3188
make_working_trees to this value (if non-None)
3189
:param shared: If creating a repository, make it shared if True
3190
:return: A repository, is_new_flag (True if the repository was
3193
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3196
class CreateRepository(RepositoryAcquisitionPolicy):
3197
"""A policy of creating a new repository"""
3199
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3200
require_stacking=False):
3203
:param bzrdir: The bzrdir to create the repository on.
3204
:param stack_on: A location to stack on
3205
:param stack_on_pwd: If stack_on is relative, the location it is
3208
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3210
self._bzrdir = bzrdir
3212
def acquire_repository(self, make_working_trees=None, shared=False):
3213
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3215
Creates the desired repository in the bzrdir we already have.
3217
stack_on = self._get_full_stack_on()
3219
# Stacking is desired. requested by the target, but does the place it
3220
# points at support stacking? If it doesn't then we should
3221
# not implicitly upgrade. We check this here.
3222
format = self._bzrdir._format
3223
if not (format.repository_format.supports_external_lookups
3224
and format.get_branch_format().supports_stacking()):
3225
# May need to upgrade - but only do if the target also
3226
# supports stacking. Note that this currently wastes
3227
# network round trips to check - but we only do this
3228
# when the source can't stack so it will fade away
3229
# as people do upgrade.
3231
target_dir = BzrDir.open(stack_on,
3232
possible_transports=[self._bzrdir.root_transport])
3233
except errors.NotBranchError:
3234
# Nothing there, don't change formats
3238
target_branch = target_dir.open_branch()
3239
except errors.NotBranchError:
3240
# No branch, don't change formats
3243
branch_format = target_branch._format
3244
repo_format = target_branch.repository._format
3245
if not (branch_format.supports_stacking()
3246
and repo_format.supports_external_lookups):
3247
# Doesn't stack itself, don't force an upgrade
3250
# Does support stacking, use its format.
3251
format.repository_format = repo_format
3252
format.set_branch_format(branch_format)
3253
note('Source format does not support stacking, '
3254
'using format: \'%s\'\n %s\n',
3255
branch_format.get_format_description(),
3256
repo_format.get_format_description())
3257
if not self._require_stacking:
3258
# We have picked up automatic stacking somewhere.
3259
note('Using default stacking branch %s at %s', self._stack_on,
3261
repository = self._bzrdir.create_repository(shared=shared)
3262
self._add_fallback(repository,
3263
possible_transports=[self._bzrdir.transport])
3264
if make_working_trees is not None:
3265
repository.set_make_working_trees(make_working_trees)
3266
return repository, True
3269
class UseExistingRepository(RepositoryAcquisitionPolicy):
3270
"""A policy of reusing an existing repository"""
3272
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3273
require_stacking=False):
3276
:param repository: The repository to use.
3277
:param stack_on: A location to stack on
3278
:param stack_on_pwd: If stack_on is relative, the location it is
3281
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3283
self._repository = repository
3285
def acquire_repository(self, make_working_trees=None, shared=False):
3286
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3288
Returns an existing repository to use.
3290
self._add_fallback(self._repository,
3291
possible_transports=[self._repository.bzrdir.transport])
3292
return self._repository, False
3295
# Please register new formats after old formats so that formats
3296
# appear in chronological order and format descriptions can build
2298
3298
format_registry = BzrDirFormatRegistry()
3299
# The pre-0.8 formats have their repository format network name registered in
3300
# repository.py. MetaDir formats have their repository format network name
3301
# inferred from their disk format string.
2299
3302
format_registry.register('weave', BzrDirFormat6,
2300
3303
'Pre-0.8 format. Slower than knit and does not'
2301
3304
' support checkouts or shared repositories.',
2302
3305
deprecated=True)
2303
format_registry.register_metadir('knit',
2304
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2305
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2306
branch_format='bzrlib.branch.BzrBranchFormat5',
2307
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2308
3306
format_registry.register_metadir('metaweave',
2309
3307
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2310
3308
'Transitional format in 0.8. Slower than knit.',
2311
3309
branch_format='bzrlib.branch.BzrBranchFormat5',
2312
3310
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2313
3311
deprecated=True)
3312
format_registry.register_metadir('knit',
3313
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3314
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3315
branch_format='bzrlib.branch.BzrBranchFormat5',
3316
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2314
3318
format_registry.register_metadir('dirstate',
2315
3319
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2316
3320
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2335
3346
'bzr branches. Incompatible with bzr < 0.15.',
2336
3347
branch_format='bzrlib.branch.BzrBranchFormat6',
2337
3348
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2340
format_registry.set_default('dirstate')
3352
format_registry.register_metadir('pack-0.92',
3353
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3354
help='New in 0.92: Pack-based format with data compatible with '
3355
'dirstate-tags format repositories. Interoperates with '
3356
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3357
'Previously called knitpack-experimental. '
3358
'For more information, see '
3359
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3360
branch_format='bzrlib.branch.BzrBranchFormat6',
3361
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3363
format_registry.register_metadir('pack-0.92-subtree',
3364
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3365
help='New in 0.92: Pack-based format with data compatible with '
3366
'dirstate-with-subtree format repositories. Interoperates with '
3367
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3368
'Previously called knitpack-experimental. '
3369
'For more information, see '
3370
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3371
branch_format='bzrlib.branch.BzrBranchFormat6',
3372
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3376
format_registry.register_metadir('rich-root-pack',
3377
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3378
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3379
'(needed for bzr-svn and bzr-git).',
3380
branch_format='bzrlib.branch.BzrBranchFormat6',
3381
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3383
format_registry.register_metadir('1.6',
3384
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3385
help='A format that allows a branch to indicate that there is another '
3386
'(stacked) repository that should be used to access data that is '
3387
'not present locally.',
3388
branch_format='bzrlib.branch.BzrBranchFormat7',
3389
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3391
format_registry.register_metadir('1.6.1-rich-root',
3392
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3393
help='A variant of 1.6 that supports rich-root data '
3394
'(needed for bzr-svn and bzr-git).',
3395
branch_format='bzrlib.branch.BzrBranchFormat7',
3396
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3398
format_registry.register_metadir('1.9',
3399
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3400
help='A repository format using B+tree indexes. These indexes '
3401
'are smaller in size, have smarter caching and provide faster '
3402
'performance for most operations.',
3403
branch_format='bzrlib.branch.BzrBranchFormat7',
3404
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3406
format_registry.register_metadir('1.9-rich-root',
3407
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3408
help='A variant of 1.9 that supports rich-root data '
3409
'(needed for bzr-svn and bzr-git).',
3410
branch_format='bzrlib.branch.BzrBranchFormat7',
3411
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3413
format_registry.register_metadir('1.14',
3414
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3415
help='A working-tree format that supports content filtering.',
3416
branch_format='bzrlib.branch.BzrBranchFormat7',
3417
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3419
format_registry.register_metadir('1.14-rich-root',
3420
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3421
help='A variant of 1.14 that supports rich-root data '
3422
'(needed for bzr-svn and bzr-git).',
3423
branch_format='bzrlib.branch.BzrBranchFormat7',
3424
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3426
# The following un-numbered 'development' formats should always just be aliases.
3427
format_registry.register_metadir('development-rich-root',
3428
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3429
help='Current development format. Can convert data to and from pack-0.92 '
3430
'(and anything compatible with pack-0.92) format repositories. '
3431
'Repositories and branches in this format can only be read by bzr.dev. '
3433
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3435
branch_format='bzrlib.branch.BzrBranchFormat7',
3436
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3440
format_registry.register_metadir('development-subtree',
3441
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3442
help='Current development format, subtree variant. Can convert data to and '
3443
'from pack-0.92-subtree (and anything compatible with '
3444
'pack-0.92-subtree) format repositories. Repositories and branches in '
3445
'this format can only be read by bzr.dev. Please read '
3446
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3448
branch_format='bzrlib.branch.BzrBranchFormat7',
3449
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3451
alias=False, # Restore to being an alias when an actual development subtree format is added
3452
# This current non-alias status is simply because we did not introduce a
3453
# chk based subtree format.
3456
# And the development formats above will have aliased one of the following:
3457
format_registry.register_metadir('development6-rich-root',
3458
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3459
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3461
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3463
branch_format='bzrlib.branch.BzrBranchFormat7',
3464
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3469
# The following format should be an alias for the rich root equivalent
3470
# of the default format
3471
format_registry.register_metadir('default-rich-root',
3472
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3473
help='Default format, rich root variant. (needed for bzr-svn and bzr-git).',
3474
branch_format='bzrlib.branch.BzrBranchFormat6',
3475
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3478
# The current format that is made on 'bzr init'.
3479
format_registry.set_default('pack-0.92')