23
# TODO: remove unittest dependency; put that stuff inside the test suite
23
25
from copy import deepcopy
26
from cStringIO import StringIO
25
from cStringIO import StringIO
28
from stat import S_ISDIR
26
29
from unittest import TestSuite
39
42
from bzrlib.store.revision.text import TextRevisionStore
40
43
from bzrlib.store.text import TextStore
41
44
from bzrlib.store.versioned import WeaveStore
42
from bzrlib.symbol_versioning import *
43
45
from bzrlib.trace import mutter
44
46
from bzrlib.transactions import WriteTransaction
45
47
from bzrlib.transport import get_transport
93
95
if not allow_unsupported and not format.is_supported():
94
96
# see open_downlevel to open legacy branches.
95
raise errors.UnsupportedFormatError(
96
'sorry, format %s not supported' % format,
97
['use a different bzr version',
98
'or remove the .bzr directory'
99
' and "bzr init" again'])
97
raise errors.UnsupportedFormatError(format=format)
101
99
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
102
100
"""Clone this bzrdir and its contents to url verbatim.
303
301
that child class desires.
305
303
bzrdir = BzrDir.create(base)
306
return bzrdir.create_repository()
304
return bzrdir.create_repository(shared)
309
307
def create_standalone_workingtree(base):
374
372
Note that bzr dirs that do not support format strings will raise
375
373
IncompatibleFormat if the branch format they are given has
376
a format string, and vice verca.
374
a format string, and vice versa.
378
376
If branch_format is None, the transport is returned with no
379
377
checking. if it is not None, then the returned transport is
387
385
Note that bzr dirs that do not support format strings will raise
388
386
IncompatibleFormat if the repository format they are given has
389
a format string, and vice verca.
387
a format string, and vice versa.
391
389
If repository_format is None, the transport is returned with no
392
390
checking. if it is not None, then the returned transport is
400
398
Note that bzr dirs that do not support format strings will raise
401
399
IncompatibleFormat if the workingtree format they are given has
402
a format string, and vice verca.
400
a format string, and vice versa.
404
402
If workingtree_format is None, the transport is returned with no
405
403
checking. if it is not None, then the returned transport is
434
432
# this might be better on the BzrDirFormat class because it refers to
435
433
# all the possible bzrdir disk formats.
436
434
# This method is tested via the workingtree is_control_filename tests-
437
# it was extractd from WorkingTree.is_control_filename. If the methods
435
# it was extracted from WorkingTree.is_control_filename. If the methods
438
436
# contract is extended beyond the current trivial implementation please
439
437
# add new tests for it to the appropriate place.
440
438
return filename == '.bzr' or filename.startswith('.bzr/')
607
605
result.create_repository()
608
606
elif source_repository is not None and result_repo is None:
609
607
# have source, and want to make a new target repo
610
# we dont clone the repo because that preserves attributes
608
# we don't clone the repo because that preserves attributes
611
609
# like is_shared(), and we have not yet implemented a
612
610
# repository sprout().
613
611
result_repo = result.create_repository()
946
944
"""The known formats."""
946
_control_formats = []
947
"""The registered control formats - .bzr, ....
949
This is a list of BzrDirFormat objects.
948
952
_lock_file_name = 'branch-lock'
950
954
# _lock_class must be set in subclasses to the lock type, typ.
954
958
def find_format(klass, transport):
955
"""Return the format registered for URL."""
959
"""Return the format present at transport."""
960
for format in klass._control_formats:
962
return format.probe_transport(transport)
963
except errors.NotBranchError:
964
# this format does not find a control dir here.
966
raise errors.NotBranchError(path=transport.base)
969
def probe_transport(klass, transport):
970
"""Return the .bzrdir style transport present at URL."""
957
972
format_string = transport.get(".bzr/branch-format").read()
973
except errors.NoSuchFile:
974
raise errors.NotBranchError(path=transport.base)
958
977
return klass._formats[format_string]
959
except errors.NoSuchFile:
960
raise errors.NotBranchError(path=transport.base)
962
raise errors.UnknownFormatError(format_string)
979
raise errors.UnknownFormatError(format=format_string)
965
982
def get_default_format(klass):
980
997
This returns a bzrlib.bzrdir.Converter object.
982
999
This should return the best upgrader to step this format towards the
983
current default format. In the case of plugins we can/shouold provide
1000
current default format. In the case of plugins we can/should provide
984
1001
some means for them to extend the range of returnable converters.
986
:param format: Optional format to override the default foramt of the
1003
:param format: Optional format to override the default format of the
989
1006
raise NotImplementedError(self.get_converter)
999
1016
def initialize_on_transport(self, transport):
1000
1017
"""Initialize a new bzrdir in the base directory of a Transport."""
1001
# Since we don'transport have a .bzr directory, inherit the
1018
# Since we don't have a .bzr directory, inherit the
1002
1019
# mode from the root directory
1003
1020
temp_control = LockableFiles(transport, '', TransportLock)
1004
1021
temp_control._transport.mkdir('.bzr',
1005
# FIXME: RBC 20060121 dont peek under
1022
# FIXME: RBC 20060121 don't peek under
1007
1024
mode=temp_control._dir_mode)
1008
1025
file_mode = temp_control._file_mode
1056
def known_formats(klass):
1057
"""Return all the known formats.
1059
Concrete formats should override _known_formats.
1061
# There is double indirection here to make sure that control
1062
# formats used by more than one dir format will only be probed
1063
# once. This can otherwise be quite expensive for remote connections.
1065
for format in klass._control_formats:
1066
result.update(format._known_formats())
1070
def _known_formats(klass):
1071
"""Return the known format instances for this control format."""
1072
return set(klass._formats.values())
1038
1074
def open(self, transport, _found=False):
1039
1075
"""Return an instance of this format for the dir transport points at.
1058
1094
klass._formats[format.get_format_string()] = format
1097
def register_control_format(klass, format):
1098
"""Register a format that does not use '.bzrdir' for its control dir.
1100
TODO: This should be pulled up into a 'ControlDirFormat' base class
1101
which BzrDirFormat can inherit from, and renamed to register_format
1102
there. It has been done without that for now for simplicity of
1105
klass._control_formats.append(format)
1061
1108
def set_default_format(klass, format):
1062
1109
klass._default_format = format
1069
1116
assert klass._formats[format.get_format_string()] is format
1070
1117
del klass._formats[format.get_format_string()]
1120
def unregister_control_format(klass, format):
1121
klass._control_formats.remove(format)
1124
# register BzrDirFormat as a control format
1125
BzrDirFormat.register_control_format(BzrDirFormat)
1073
1128
class BzrDirFormat4(BzrDirFormat):
1074
1129
"""Bzr dir format 4.
1324
class ScratchDir(BzrDir6):
1325
"""Special test class: a bzrdir that cleans up itself..
1327
>>> d = ScratchDir()
1328
>>> base = d.transport.base
1331
>>> b.transport.__del__()
1336
def __init__(self, files=[], dirs=[], transport=None):
1337
"""Make a test branch.
1339
This creates a temporary directory and runs init-tree in it.
1341
If any files are listed, they are created in the working copy.
1343
if transport is None:
1344
transport = bzrlib.transport.local.ScratchTransport()
1345
# local import for scope restriction
1346
BzrDirFormat6().initialize(transport.base)
1347
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1348
self.create_repository()
1349
self.create_branch()
1350
self.create_workingtree()
1352
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1354
# BzrBranch creates a clone to .bzr and then forgets about the
1355
# original transport. A ScratchTransport() deletes itself and
1356
# everything underneath it when it goes away, so we need to
1357
# grab a local copy to prevent that from happening
1358
self._transport = transport
1361
self._transport.mkdir(d)
1364
self._transport.put(f, 'content of %s' % f)
1368
>>> orig = ScratchDir(files=["file1", "file2"])
1369
>>> os.listdir(orig.base)
1370
[u'.bzr', u'file1', u'file2']
1371
>>> clone = orig.clone()
1372
>>> if os.name != 'nt':
1373
... os.path.samefile(orig.base, clone.base)
1375
... orig.base == clone.base
1378
>>> os.listdir(clone.base)
1379
[u'.bzr', u'file1', u'file2']
1381
from shutil import copytree
1382
from bzrlib.osutils import mkdtemp
1385
copytree(self.base, base, symlinks=True)
1387
transport=bzrlib.transport.local.ScratchTransport(base))
1390
1379
class Converter(object):
1391
1380
"""Converts a disk format object from one format to another."""