153
157
format.get_format_description(),
156
def clone(self, url, revision_id=None, force_new_repo=False):
160
def clone(self, url, revision_id=None, force_new_repo=False,
161
preserve_stacking=False):
157
162
"""Clone this bzrdir and its contents to url verbatim.
159
If url's last component does not exist, it will be created.
161
if revision_id is not None, then the clone operation may tune
164
:param url: The url create the clone at. If url's last component does
165
not exist, it will be created.
166
:param revision_id: The tip revision-id to use for any branch or
167
working tree. If not None, then the clone operation may tune
162
168
itself to download less data.
163
:param force_new_repo: Do not use a shared repository for the target
169
:param force_new_repo: Do not use a shared repository for the target
164
170
even if one is available.
171
:param preserve_stacking: When cloning a stacked branch, stack the
172
new branch on top of the other branch's stacked-on branch.
166
174
return self.clone_on_transport(get_transport(url),
167
175
revision_id=revision_id,
168
force_new_repo=force_new_repo)
176
force_new_repo=force_new_repo,
177
preserve_stacking=preserve_stacking)
170
179
def clone_on_transport(self, transport, revision_id=None,
171
force_new_repo=False):
180
force_new_repo=False, preserve_stacking=False):
172
181
"""Clone this bzrdir and its contents to transport verbatim.
174
If the target directory does not exist, it will be created.
176
if revision_id is not None, then the clone operation may tune
183
:param transport: The transport for the location to produce the clone
184
at. If the target directory does not exist, it will be created.
185
:param revision_id: The tip revision-id to use for any branch or
186
working tree. If not None, then the clone operation may tune
177
187
itself to download less data.
178
:param force_new_repo: Do not use a shared repository for the target
188
:param force_new_repo: Do not use a shared repository for the target,
179
189
even if one is available.
190
:param preserve_stacking: When cloning a stacked branch, stack the
191
new branch on top of the other branch's stacked-on branch.
181
193
transport.ensure_base()
182
194
result = self.cloning_metadir().initialize_on_transport(transport)
183
195
repository_policy = None
185
198
local_repo = self.find_repository()
186
199
except errors.NoRepositoryPresent:
187
200
local_repo = None
202
local_branch = self.open_branch()
203
except errors.NotBranchError:
206
# enable fallbacks when branch is not a branch reference
207
if local_branch.repository.has_same_location(local_repo):
208
local_repo = local_branch.repository
209
if preserve_stacking:
211
stack_on = local_branch.get_stacked_on_url()
212
except (errors.UnstackableBranchFormat,
213
errors.UnstackableRepositoryFormat,
189
218
# may need to copy content in
190
219
repository_policy = result.determine_repository_policy(
220
force_new_repo, stack_on)
192
221
make_working_trees = local_repo.make_working_trees()
193
222
result_repo = repository_policy.acquire_repository(
194
223
make_working_trees, local_repo.is_shared())
195
224
result_repo.fetch(local_repo, revision_id=revision_id)
196
227
# 1 if there is a branch present
197
228
# make sure its content is available in the target repository
200
local_branch = self.open_branch()
201
except errors.NotBranchError:
230
if local_branch is not None:
204
231
result_branch = local_branch.clone(result, revision_id=revision_id)
205
232
if repository_policy is not None:
206
233
repository_policy.configure_branch(result_branch)
208
result_repo = result.find_repository()
209
except errors.NoRepositoryPresent:
211
234
if result_repo is None or result_repo.make_working_trees():
213
236
self.open_workingtree().clone(result)
350
372
bzrdir._find_or_create_repository(force_new_repo)
351
373
return bzrdir.create_branch()
353
def determine_repository_policy(self, force_new_repo=False):
375
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
376
stack_on_pwd=None, require_stacking=False):
354
377
"""Return an object representing a policy to use.
356
379
This controls whether a new repository is created, or a shared
357
380
repository used instead.
382
If stack_on is supplied, will not seek a containing shared repo.
383
:param force_new_repo: If True, require a new repository to be created.
384
:param stack_on: If supplied, the location to stack on. If not
385
supplied, a default_stack_on location may be used.
386
:param stack_on_pwd: If stack_on is relative, the location it is
359
389
def repository_policy(found_bzrdir):
392
config = found_bzrdir.get_config()
394
if config is not None:
395
stack_on = config.get_default_stack_on()
396
if stack_on is not None:
397
stack_on_pwd = found_bzrdir.root_transport.base
399
note('Using default stacking branch %s at %s', stack_on,
361
401
# does it have a repository ?
363
403
repository = found_bzrdir.open_repository()
373
413
return None, False
375
return UseExistingRepository(repository), True
415
return UseExistingRepository(repository, stack_on,
416
stack_on_pwd, require_stacking=require_stacking), True
377
return CreateRepository(self), True
418
return CreateRepository(self, stack_on, stack_on_pwd,
419
require_stacking=require_stacking), True
379
421
if not force_new_repo:
380
policy = self._find_containing(repository_policy)
381
if policy is not None:
383
return CreateRepository(self)
423
policy = self._find_containing(repository_policy)
424
if policy is not None:
428
return UseExistingRepository(self.open_repository(),
429
stack_on, stack_on_pwd,
430
require_stacking=require_stacking)
431
except errors.NoRepositoryPresent:
433
return CreateRepository(self, stack_on, stack_on_pwd,
434
require_stacking=require_stacking)
385
436
def _find_or_create_repository(self, force_new_repo):
386
437
"""Create a new repository if needed, returning the repository."""
582
633
guaranteed to point to an existing directory ready for use.
584
635
raise NotImplementedError(self.get_branch_transport)
637
def _find_creation_modes(self):
638
"""Determine the appropriate modes for files and directories.
640
They're always set to be consistent with the base directory,
641
assuming that this transport allows setting modes.
643
# TODO: Do we need or want an option (maybe a config setting) to turn
644
# this off or override it for particular locations? -- mbp 20080512
645
if self._mode_check_done:
647
self._mode_check_done = True
649
st = self.transport.stat('.')
650
except errors.TransportNotPossible:
651
self._dir_mode = None
652
self._file_mode = None
654
# Check the directory mode, but also make sure the created
655
# directories and files are read-write for this user. This is
656
# mostly a workaround for filesystems which lie about being able to
657
# write to a directory (cygwin & win32)
658
self._dir_mode = (st.st_mode & 07777) | 00700
659
# Remove the sticky and execute bits for files
660
self._file_mode = self._dir_mode & ~07111
662
def _get_file_mode(self):
663
"""Return Unix mode for newly created files, or None.
665
if not self._mode_check_done:
666
self._find_creation_modes()
667
return self._file_mode
669
def _get_dir_mode(self):
670
"""Return Unix mode for newly created directories, or None.
672
if not self._mode_check_done:
673
self._find_creation_modes()
674
return self._dir_mode
586
676
def get_repository_transport(self, repository_format):
587
677
"""Get the transport for use by repository format in this BzrDir.
803
899
tree, branch = bzrdir._get_tree_branch()
804
900
return tree, branch, relpath
903
def open_containing_tree_branch_or_repository(klass, location):
904
"""Return the working tree, branch and repo contained by a location.
906
Returns (tree, branch, repository, relpath).
907
If there is no tree containing the location, tree will be None.
908
If there is no branch containing the location, branch will be None.
909
If there is no repository containing the location, repository will be
911
relpath is the portion of the path that is contained by the innermost
914
If no tree, branch or repository is found, a NotBranchError is raised.
916
bzrdir, relpath = klass.open_containing(location)
918
tree, branch = bzrdir._get_tree_branch()
919
except errors.NotBranchError:
921
repo = bzrdir.find_repository()
922
return None, None, repo, relpath
923
except (errors.NoRepositoryPresent):
924
raise errors.NotBranchError(location)
925
return tree, branch, branch.repository, relpath
806
927
def open_repository(self, _unsupported=False):
807
928
"""Open the repository object at this BzrDir if one is present.
934
1057
source_branch = self.open_branch()
935
1058
source_repository = source_branch.repository
1060
stacked_branch_url = self.root_transport.base
1062
# if a stacked branch wasn't requested, we don't create one
1063
# even if the origin was stacked
1064
stacked_branch_url = None
936
1065
except errors.NotBranchError:
937
1066
source_branch = None
939
1068
source_repository = self.open_repository()
940
1069
except errors.NoRepositoryPresent:
941
1070
source_repository = None
946
result_repo = result.find_repository()
947
except errors.NoRepositoryPresent:
949
if source_repository is None and result_repo is not None:
951
elif source_repository is None and result_repo is None:
952
# no repo available, make a new one
953
result.create_repository()
954
elif source_repository is not None and result_repo is None:
955
# have source, and want to make a new target repo
956
result_repo = source_repository.sprout(result,
957
revision_id=revision_id)
959
# fetch needed content into target.
960
if source_repository is not None:
962
# source_repository.copy_content_into(result_repo,
963
# revision_id=revision_id)
964
# so we can override the copy method
965
result_repo.fetch(source_repository, revision_id=revision_id)
1071
stacked_branch_url = None
1072
repository_policy = result.determine_repository_policy(
1073
force_new_repo, stacked_branch_url, require_stacking=stacked)
1074
result_repo = repository_policy.acquire_repository()
1075
if source_repository is not None:
1076
result_repo.fetch(source_repository, revision_id=revision_id)
1078
# Create/update the result branch
966
1079
if source_branch is not None:
967
source_branch.sprout(result, revision_id=revision_id)
1080
result_branch = source_branch.sprout(result,
1081
revision_id=revision_id)
969
result.create_branch()
1083
result_branch = result.create_branch()
1084
repository_policy.configure_branch(result_branch)
1086
# Create/update the result working tree
970
1087
if isinstance(target_transport, LocalTransport) and (
971
1088
result_repo is None or result_repo.make_working_trees()):
972
1089
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1028
1144
"""Produce a metadir suitable for cloning with."""
1029
1145
return self._format.__class__()
1031
def clone(self, url, revision_id=None, force_new_repo=False):
1032
"""See BzrDir.clone()."""
1147
def clone(self, url, revision_id=None, force_new_repo=False,
1148
preserve_stacking=False):
1149
"""See BzrDir.clone().
1151
force_new_repo has no effect, since this family of formats always
1152
require a new repository.
1153
preserve_stacking has no effect, since no source branch using this
1154
family of formats can be stacked, so there is no stacking to preserve.
1033
1156
from bzrlib.workingtree import WorkingTreeFormat2
1034
1157
self._make_tail(url)
1035
1158
result = self._format._initialize_for_clone(url)
1506
1635
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1507
1636
file_mode = temp_control._file_mode
1508
1637
del temp_control
1509
mutter('created control directory in ' + transport.base)
1510
control = transport.clone('.bzr')
1511
utf8_files = [('README',
1638
bzrdir_transport = transport.clone('.bzr')
1639
utf8_files = [('README',
1512
1640
"This is a Bazaar control directory.\n"
1513
1641
"Do not change any files in this directory.\n"
1514
1642
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1515
1643
('branch-format', self.get_format_string()),
1517
1645
# NB: no need to escape relative paths that are url safe.
1518
control_files = lockable_files.LockableFiles(control,
1519
self._lock_file_name, self._lock_class)
1646
control_files = lockable_files.LockableFiles(bzrdir_transport,
1647
self._lock_file_name, self._lock_class)
1520
1648
control_files.create_lock()
1521
1649
control_files.lock_write()
1523
for file, content in utf8_files:
1524
control_files.put_utf8(file, content)
1651
for (filename, content) in utf8_files:
1652
bzrdir_transport.put_bytes(filename, content,
1526
1655
control_files.unlock()
1527
1656
return self.open(transport, _found=True)
1983
2115
def _convert_working_inv(self):
1984
2116
inv = xml4.serializer_v4.read_inventory(
1985
self.branch.control_files.get('inventory'))
2117
self.branch._transport.get('inventory'))
1986
2118
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
1987
# FIXME inventory is a working tree change.
1988
self.branch.control_files.put('inventory', StringIO(new_inv_xml))
2119
self.branch._transport.put_bytes('inventory', new_inv_xml,
2120
mode=self.bzrdir._get_file_mode())
1990
2122
def _write_all_weaves(self):
1991
2123
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2011
2143
self.bzrdir.transport.mkdir('revision-store')
2012
2144
revision_transport = self.bzrdir.transport.clone('revision-store')
2013
2145
# TODO permissions
2014
_revision_store = TextRevisionStore(TextStore(revision_transport,
2146
from bzrlib.xml5 import serializer_v5
2147
from bzrlib.repofmt.weaverepo import RevisionTextStore
2148
revision_store = RevisionTextStore(revision_transport,
2149
serializer_v5, False, versionedfile.PrefixMapper(),
2150
lambda:True, lambda:True)
2018
transaction = WriteTransaction()
2019
2152
for i, rev_id in enumerate(self.converted_revs):
2020
2153
self.pb.update('write revision', i, len(self.converted_revs))
2021
_revision_store.add_revision(self.revisions[rev_id], transaction)
2154
text = serializer_v5.write_revision_to_string(
2155
self.revisions[rev_id])
2157
revision_store.add_lines(key, None, osutils.split_lines(text))
2023
2159
self.pb.clear()
2188
2323
if (filename.endswith(".weave") or
2189
2324
filename.endswith(".gz") or
2190
2325
filename.endswith(".sig")):
2191
file_id = os.path.splitext(filename)[0]
2326
file_id, suffix = os.path.splitext(filename)
2193
2328
file_id = filename
2194
prefix_dir = store.hash_prefix(file_id)
2330
new_name = store._mapper.map((file_id,)) + suffix
2195
2331
# FIXME keep track of the dirs made RBC 20060121
2197
store_transport.move(filename, prefix_dir + '/' + filename)
2333
store_transport.move(filename, new_name)
2198
2334
except errors.NoSuchFile: # catches missing dirs strangely enough
2199
store_transport.mkdir(prefix_dir)
2200
store_transport.move(filename, prefix_dir + '/' + filename)
2201
self.bzrdir._control_files.put_utf8('branch-format', BzrDirFormat6().get_format_string())
2335
store_transport.mkdir(osutils.dirname(new_name))
2336
store_transport.move(filename, new_name)
2337
self.bzrdir.transport.put_bytes(
2339
BzrDirFormat6().get_format_string(),
2340
mode=self.bzrdir._get_file_mode())
2204
2343
class ConvertBzrDir6ToMeta(Converter):
2286
2428
for entry in checkout_files:
2287
2429
self.move_entry('checkout', entry)
2288
2430
if last_revision is not None:
2289
self.bzrdir._control_files.put_utf8(
2431
self.bzrdir.transport.put_bytes(
2290
2432
'checkout/last-revision', last_revision)
2291
self.bzrdir._control_files.put_utf8(
2292
'branch-format', BzrDirMetaFormat1().get_format_string())
2433
self.bzrdir.transport.put_bytes(
2435
BzrDirMetaFormat1().get_format_string(),
2436
mode=self.file_mode)
2293
2437
return BzrDir.open(self.bzrdir.root_transport.base)
2295
2439
def make_lock(self, name):
2351
2497
# TODO: conversions of Branch and Tree should be done by
2352
# InterXFormat lookups
2498
# InterXFormat lookups/some sort of registry.
2353
2499
# Avoid circular imports
2354
2500
from bzrlib import branch as _mod_branch
2355
if (branch._format.__class__ is _mod_branch.BzrBranchFormat5 and
2356
self.target_format.get_branch_format().__class__ is
2357
_mod_branch.BzrBranchFormat6):
2358
branch_converter = _mod_branch.Converter5to6()
2501
old = branch._format.__class__
2502
new = self.target_format.get_branch_format().__class__
2504
if (old == _mod_branch.BzrBranchFormat5 and
2505
new in (_mod_branch.BzrBranchFormat6,
2506
_mod_branch.BzrBranchFormat7)):
2507
branch_converter = _mod_branch.Converter5to6()
2508
elif (old == _mod_branch.BzrBranchFormat6 and
2509
new == _mod_branch.BzrBranchFormat7):
2510
branch_converter = _mod_branch.Converter6to7()
2512
raise errors.BadConversionTarget("No converter", new)
2359
2513
branch_converter.convert(branch)
2514
branch = self.bzrdir.open_branch()
2515
old = branch._format.__class__
2361
2517
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2362
2518
except (errors.NoWorkingTree, errors.NotLocalUrl):
2389
2545
medium = transport.get_smart_medium()
2390
2546
except (NotImplementedError, AttributeError,
2391
errors.TransportNotPossible, errors.NoSmartMedium):
2547
errors.TransportNotPossible, errors.NoSmartMedium,
2548
errors.SmartProtocolError):
2392
2549
# no smart server, so not a branch for this format type.
2393
2550
raise errors.NotBranchError(path=transport.base)
2395
2552
# Decline to open it if the server doesn't support our required
2396
# version (2) so that the VFS-based transport will do it.
2398
server_version = medium.protocol_version()
2399
except errors.SmartProtocolError:
2400
# Apparently there's no usable smart server there, even though
2401
# the medium supports the smart protocol.
2402
raise errors.NotBranchError(path=transport.base)
2403
if server_version != 2:
2404
raise errors.NotBranchError(path=transport.base)
2553
# version (3) so that the VFS-based transport will do it.
2554
if medium.should_probe():
2556
server_version = medium.protocol_version()
2557
except errors.SmartProtocolError:
2558
# Apparently there's no usable smart server there, even though
2559
# the medium supports the smart protocol.
2560
raise errors.NotBranchError(path=transport.base)
2561
if server_version != '2':
2562
raise errors.NotBranchError(path=transport.base)
2407
2565
def initialize_on_transport(self, transport):
2608
2766
for a branch that is being created. The most basic policy decision is
2609
2767
whether to create a new repository or use an existing one.
2769
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2772
:param stack_on: A location to stack on
2773
:param stack_on_pwd: If stack_on is relative, the location it is
2775
:param require_stacking: If True, it is a failure to not stack.
2777
self._stack_on = stack_on
2778
self._stack_on_pwd = stack_on_pwd
2779
self._require_stacking = require_stacking
2612
2781
def configure_branch(self, branch):
2613
2782
"""Apply any configuration data from this policy to the branch.
2615
Default implementation does nothing.
2784
Default implementation sets repository stacking.
2786
if self._stack_on is None:
2788
if self._stack_on_pwd is None:
2789
stack_on = self._stack_on
2792
stack_on = urlutils.rebase_url(self._stack_on,
2794
branch.bzrdir.root_transport.base)
2795
except errors.InvalidRebaseURLs:
2796
stack_on = self._get_full_stack_on()
2798
branch.set_stacked_on_url(stack_on)
2799
except errors.UnstackableBranchFormat:
2800
if self._require_stacking:
2803
def _get_full_stack_on(self):
2804
"""Get a fully-qualified URL for the stack_on location."""
2805
if self._stack_on is None:
2807
if self._stack_on_pwd is None:
2808
return self._stack_on
2810
return urlutils.join(self._stack_on_pwd, self._stack_on)
2812
def _add_fallback(self, repository):
2813
"""Add a fallback to the supplied repository, if stacking is set."""
2814
stack_on = self._get_full_stack_on()
2815
if stack_on is None:
2817
stacked_dir = BzrDir.open(stack_on)
2819
stacked_repo = stacked_dir.open_branch().repository
2820
except errors.NotBranchError:
2821
stacked_repo = stacked_dir.open_repository()
2823
repository.add_fallback_repository(stacked_repo)
2824
except errors.UnstackableRepositoryFormat:
2825
if self._require_stacking:
2619
2828
def acquire_repository(self, make_working_trees=None, shared=False):
2620
2829
"""Acquire a repository for this bzrdir.
2632
2841
class CreateRepository(RepositoryAcquisitionPolicy):
2633
2842
"""A policy of creating a new repository"""
2635
def __init__(self, bzrdir):
2636
RepositoryAcquisitionPolicy.__init__(self)
2844
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
2845
require_stacking=False):
2848
:param bzrdir: The bzrdir to create the repository on.
2849
:param stack_on: A location to stack on
2850
:param stack_on_pwd: If stack_on is relative, the location it is
2853
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2637
2855
self._bzrdir = bzrdir
2639
2857
def acquire_repository(self, make_working_trees=None, shared=False):
2650
2869
class UseExistingRepository(RepositoryAcquisitionPolicy):
2651
2870
"""A policy of reusing an existing repository"""
2653
def __init__(self, repository):
2654
RepositoryAcquisitionPolicy.__init__(self)
2872
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
2873
require_stacking=False):
2876
:param repository: The repository to use.
2877
:param stack_on: A location to stack on
2878
:param stack_on_pwd: If stack_on is relative, the location it is
2881
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2655
2883
self._repository = repository
2657
2885
def acquire_repository(self, make_working_trees=None, shared=False):
2747
2976
# The following two formats should always just be aliases.
2748
2977
format_registry.register_metadir('development',
2749
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0',
2978
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment1',
2750
2979
help='Current development format. Can convert data to and from pack-0.92 '
2751
2980
'(and anything compatible with pack-0.92) format repositories. '
2752
'Repositories in this format can only be read by bzr.dev. '
2981
'Repositories and branches in this format can only be read by bzr.dev. '
2754
2983
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2756
branch_format='bzrlib.branch.BzrBranchFormat6',
2985
branch_format='bzrlib.branch.BzrBranchFormat7',
2757
2986
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2758
2987
experimental=True,
2761
2990
format_registry.register_metadir('development-subtree',
2762
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment0Subtree',
2991
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment1Subtree',
2763
2992
help='Current development format, subtree variant. Can convert data to and '
2764
'from pack-0.92 (and anything compatible with pack-0.92) format '
2765
'repositories. Repositories in this format can only be read by '
2766
'bzr.dev. Please read '
2993
'from pack-0.92-subtree (and anything compatible with '
2994
'pack-0.92-subtree) format repositories. Repositories and branches in '
2995
'this format can only be read by bzr.dev. Please read '
2767
2996
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
2769
branch_format='bzrlib.branch.BzrBranchFormat6',
2998
branch_format='bzrlib.branch.BzrBranchFormat7',
2770
2999
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2771
3000
experimental=True,
2795
3024
experimental=True,
3026
format_registry.register_metadir('development1',
3027
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment1',
3028
help='A branch and pack based repository that supports stacking. '
3030
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3032
branch_format='bzrlib.branch.BzrBranchFormat7',
3033
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3037
format_registry.register_metadir('development1-subtree',
3038
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment1Subtree',
3039
help='A branch and pack based repository that supports stacking. '
3041
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3043
branch_format='bzrlib.branch.BzrBranchFormat7',
3044
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3048
# The current format that is made on 'bzr init'.
2797
3049
format_registry.set_default('pack-0.92')