1
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
# TODO: remove unittest dependency; put that stuff inside the test suite
25
# TODO: The Format probe_transport seems a bit redundant with just trying to
26
# open the bzrdir. -- mbp
28
# TODO: Can we move specific formats into separate modules to make this file
23
from copy import deepcopy
31
25
from cStringIO import StringIO
34
from bzrlib.lazy_import import lazy_import
35
lazy_import(globals(), """
36
from copy import deepcopy
37
from stat import S_ISDIR
26
from unittest import TestSuite
45
revision as _mod_revision,
29
import bzrlib.errors as errors
30
from bzrlib.lockable_files import LockableFiles, TransportLock
31
from bzrlib.lockdir import LockDir
32
from bzrlib.osutils import safe_unicode
50
33
from bzrlib.osutils import (
55
40
from bzrlib.store.revision.text import TextRevisionStore
56
41
from bzrlib.store.text import TextStore
57
42
from bzrlib.store.versioned import WeaveStore
43
from bzrlib.symbol_versioning import *
44
from bzrlib.trace import mutter
58
45
from bzrlib.transactions import WriteTransaction
59
from bzrlib.transport import get_transport
46
from bzrlib.transport import get_transport, urlunescape
47
from bzrlib.transport.local import LocalTransport
60
48
from bzrlib.weave import Weave
63
from bzrlib.trace import mutter
64
from bzrlib.transport.local import LocalTransport
49
from bzrlib.xml4 import serializer_v4
50
from bzrlib.xml5 import serializer_v5
67
53
class BzrDir(object):
98
84
"""Return true if this bzrdir is one whose format we can convert from."""
101
def check_conversion_target(self, target_format):
102
target_repo_format = target_format.repository_format
103
source_repo_format = self._format.repository_format
104
source_repo_format.check_conversion_target(target_repo_format)
107
88
def _check_supported(format, allow_unsupported):
108
89
"""Check whether format is a supported format.
112
93
if not allow_unsupported and not format.is_supported():
113
94
# see open_downlevel to open legacy branches.
114
raise errors.UnsupportedFormatError(format=format)
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'])
116
101
def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
117
102
"""Clone this bzrdir and its contents to url verbatim.
188
173
basis_repo = None
189
174
return basis_repo, basis_branch, basis_tree
191
# TODO: This should be given a Transport, and should chdir up; otherwise
192
# this will open a new connection.
193
176
def _make_tail(self, url):
194
head, tail = urlutils.split(url)
195
if tail and tail != '.':
196
t = get_transport(head)
177
segments = url.split('/')
178
if segments and segments[-1] not in ('', '.'):
179
parent = '/'.join(segments[:-1])
180
t = bzrlib.transport.get_transport(parent)
182
t.mkdir(segments[-1])
199
183
except errors.FileExists:
202
# TODO: Should take a Transport
204
187
def create(cls, base):
205
188
"""Create a new BzrDir at the url 'base'.
213
196
if cls is not BzrDir:
214
197
raise AssertionError("BzrDir.create always creates the default format, "
215
198
"not one of %r" % cls)
216
head, tail = urlutils.split(base)
217
if tail and tail != '.':
218
t = get_transport(head)
199
segments = base.split('/')
200
if segments and segments[-1] not in ('', '.'):
201
parent = '/'.join(segments[:-1])
202
t = bzrlib.transport.get_transport(parent)
204
t.mkdir(segments[-1])
221
205
except errors.FileExists:
223
207
return BzrDirFormat.get_default_format().initialize(safe_unicode(base))
347
331
raise NotImplementedError(self.create_workingtree)
349
def destroy_workingtree(self):
350
"""Destroy the working tree at this BzrDir.
352
Formats that do not support this may raise UnsupportedOperation.
354
raise NotImplementedError(self.destroy_workingtree)
356
def destroy_workingtree_metadata(self):
357
"""Destroy the control files for the working tree at this BzrDir.
359
The contents of working tree files are not affected.
360
Formats that do not support this may raise UnsupportedOperation.
362
raise NotImplementedError(self.destroy_workingtree_metadata)
364
333
def find_repository(self):
365
334
"""Find the repository that should be used for a_bzrdir.
375
344
next_transport = self.root_transport.clone('..')
377
# find the next containing bzrdir
379
347
found_bzrdir = BzrDir.open_containing_from_transport(
380
348
next_transport)[0]
381
349
except errors.NotBranchError:
383
350
raise errors.NoRepositoryPresent(self)
384
# does it have a repository ?
386
352
repository = found_bzrdir.open_repository()
387
353
except errors.NoRepositoryPresent:
388
354
next_transport = found_bzrdir.root_transport.clone('..')
389
if (found_bzrdir.root_transport.base == next_transport.base):
390
# top of the file system
394
356
if ((found_bzrdir.root_transport.base ==
395
357
self.root_transport.base) or repository.is_shared()):
396
358
return repository
404
366
Note that bzr dirs that do not support format strings will raise
405
367
IncompatibleFormat if the branch format they are given has
406
a format string, and vice versa.
368
a format string, and vice verca.
408
370
If branch_format is None, the transport is returned with no
409
371
checking. if it is not None, then the returned transport is
417
379
Note that bzr dirs that do not support format strings will raise
418
380
IncompatibleFormat if the repository format they are given has
419
a format string, and vice versa.
381
a format string, and vice verca.
421
383
If repository_format is None, the transport is returned with no
422
384
checking. if it is not None, then the returned transport is
430
392
Note that bzr dirs that do not support format strings will raise
431
393
IncompatibleFormat if the workingtree format they are given has
432
a format string, and vice versa.
394
a format string, and vice verca.
434
396
If workingtree_format is None, the transport is returned with no
435
397
checking. if it is not None, then the returned transport is
464
426
# this might be better on the BzrDirFormat class because it refers to
465
427
# all the possible bzrdir disk formats.
466
428
# This method is tested via the workingtree is_control_filename tests-
467
# it was extracted from WorkingTree.is_control_filename. If the methods
429
# it was extractd from WorkingTree.is_control_filename. If the methods
468
430
# contract is extended beyond the current trivial implementation please
469
431
# add new tests for it to the appropriate place.
470
432
return filename == '.bzr' or filename.startswith('.bzr/')
492
454
_unsupported is a private parameter to the BzrDir class.
494
456
t = get_transport(base)
495
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
498
def open_from_transport(transport, _unsupported=False):
499
"""Open a bzrdir within a particular directory.
501
:param transport: Transport containing the bzrdir.
502
:param _unsupported: private.
504
format = BzrDirFormat.find_format(transport)
457
mutter("trying to open %r with transport %r", base, t)
458
format = BzrDirFormat.find_format(t)
505
459
BzrDir._check_supported(format, _unsupported)
506
return format.open(transport, _found=True)
460
return format.open(t, _found=True)
508
462
def open_branch(self, unsupported=False):
509
463
"""Open the branch object at this BzrDir if one is present.
535
489
If there is one and it is either an unrecognised format or an unsupported
536
490
format, UnknownFormatError or UnsupportedFormatError are raised.
537
491
If there is one, it is returned, along with the unused portion of url.
539
:return: The BzrDir that contains the path, and a Unicode path
540
for the rest of the URL.
542
493
# this gets the normalised url back. I.e. '.' -> the full path.
543
494
url = a_transport.base
546
result = BzrDir.open_from_transport(a_transport)
547
return result, urlutils.unescape(a_transport.relpath(url))
497
format = BzrDirFormat.find_format(a_transport)
498
BzrDir._check_supported(format, False)
499
return format.open(a_transport), a_transport.relpath(url)
548
500
except errors.NotBranchError, e:
501
mutter('not a branch in: %r %s', a_transport.base, e)
550
502
new_t = a_transport.clone('..')
551
503
if new_t.base == a_transport.base:
552
504
# reached the root, whatever that may be
601
553
except errors.NoWorkingTree:
604
def cloning_metadir(self, basis=None):
605
"""Produce a metadir suitable for cloning with"""
606
def related_repository(bzrdir):
608
branch = bzrdir.open_branch()
609
return branch.repository
610
except errors.NotBranchError:
612
return bzrdir.open_repository()
613
result_format = self._format.__class__()
616
source_repository = related_repository(self)
617
except errors.NoRepositoryPresent:
620
source_repository = related_repository(self)
621
result_format.repository_format = source_repository._format
622
except errors.NoRepositoryPresent:
626
556
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
627
557
"""Create a copy of this bzrdir prepared for use as a new line of
666
595
result.create_repository()
667
596
elif source_repository is not None and result_repo is None:
668
597
# have source, and want to make a new target repo
669
# we don't clone the repo because that preserves attributes
598
# we dont clone the repo because that preserves attributes
670
599
# like is_shared(), and we have not yet implemented a
671
600
# repository sprout().
672
601
result_repo = result.create_repository()
676
605
# XXX FIXME RBC 20060214 need tests for this when the basis
678
607
result_repo.fetch(basis_repo, revision_id=revision_id)
679
if source_repository is not None:
680
result_repo.fetch(source_repository, revision_id=revision_id)
608
result_repo.fetch(source_repository, revision_id=revision_id)
681
609
if source_branch is not None:
682
610
source_branch.sprout(result, revision_id=revision_id)
684
612
result.create_branch()
685
# TODO: jam 20060426 we probably need a test in here in the
686
# case that the newly sprouted branch is a remote one
687
613
if result_repo is None or result_repo.make_working_trees():
688
wt = result.create_workingtree()
689
if wt.inventory.root is None:
691
wt.set_root_id(self.open_workingtree.get_root_id())
692
except errors.NoWorkingTree:
614
result.create_workingtree()
700
621
def __init__(self, _transport, _format):
701
622
"""See BzrDir.__init__."""
702
623
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
703
assert self._format._lock_class == lockable_files.TransportLock
624
assert self._format._lock_class == TransportLock
704
625
assert self._format._lock_file_name == 'branch-lock'
705
self._control_files = lockable_files.LockableFiles(
706
self.get_branch_transport(None),
626
self._control_files = LockableFiles(self.get_branch_transport(None),
707
627
self._format._lock_file_name,
708
628
self._format._lock_class)
753
673
# done on this format anyway. So - acceptable wart.
754
674
result = self.open_workingtree()
755
675
if revision_id is not None:
756
if revision_id == _mod_revision.NULL_REVISION:
757
result.set_parent_ids([])
759
result.set_parent_ids([revision_id])
676
result.set_last_revision(revision_id)
762
def destroy_workingtree(self):
763
"""See BzrDir.destroy_workingtree."""
764
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
766
def destroy_workingtree_metadata(self):
767
"""See BzrDir.destroy_workingtree_metadata."""
768
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
771
679
def get_branch_transport(self, branch_format):
772
680
"""See BzrDir.get_branch_transport()."""
773
681
if branch_format is None:
813
721
self._check_supported(format, unsupported)
814
722
return format.open(self, _found=True)
816
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
724
def sprout(self, url, revision_id=None, basis=None):
817
725
"""See BzrDir.sprout()."""
818
726
from bzrlib.workingtree import WorkingTreeFormat2
819
727
self._make_tail(url)
913
821
from bzrlib.workingtree import WorkingTreeFormat
914
822
return WorkingTreeFormat.get_default_format().initialize(self, revision_id)
916
def destroy_workingtree(self):
917
"""See BzrDir.destroy_workingtree."""
918
wt = self.open_workingtree()
919
repository = wt.branch.repository
920
empty = repository.revision_tree(bzrlib.revision.NULL_REVISION)
921
wt.revert([], old_tree=empty)
922
self.destroy_workingtree_metadata()
924
def destroy_workingtree_metadata(self):
925
self.transport.delete_tree('checkout')
927
824
def _get_mkdir_mode(self):
928
825
"""Figure out the mode to use when creating a bzrdir subdir."""
929
temp_control = lockable_files.LockableFiles(self.transport, '',
930
lockable_files.TransportLock)
826
temp_control = LockableFiles(self.transport, '', TransportLock)
931
827
return temp_control._dir_mode
933
829
def get_branch_transport(self, branch_format):
1050
940
def find_format(klass, transport):
1051
"""Return the format present at transport."""
1052
for format in klass._control_formats:
1054
return format.probe_transport(transport)
1055
except errors.NotBranchError:
1056
# this format does not find a control dir here.
1058
raise errors.NotBranchError(path=transport.base)
1061
def probe_transport(klass, transport):
1062
"""Return the .bzrdir style transport present at URL."""
941
"""Return the format registered for URL."""
1064
943
format_string = transport.get(".bzr/branch-format").read()
944
return klass._formats[format_string]
1065
945
except errors.NoSuchFile:
1066
946
raise errors.NotBranchError(path=transport.base)
1069
return klass._formats[format_string]
1070
947
except KeyError:
1071
raise errors.UnknownFormatError(format=format_string)
948
raise errors.UnknownFormatError(format_string)
1074
951
def get_default_format(klass):
1089
966
This returns a bzrlib.bzrdir.Converter object.
1091
968
This should return the best upgrader to step this format towards the
1092
current default format. In the case of plugins we can/should provide
969
current default format. In the case of plugins we can/shouold provide
1093
970
some means for them to extend the range of returnable converters.
1095
:param format: Optional format to override the default format of the
972
:param format: Optional format to override the default foramt of the
1098
975
raise NotImplementedError(self.get_converter)
1108
985
def initialize_on_transport(self, transport):
1109
986
"""Initialize a new bzrdir in the base directory of a Transport."""
1110
# Since we don't have a .bzr directory, inherit the
987
# Since we don'transport have a .bzr directory, inherit the
1111
988
# mode from the root directory
1112
temp_control = lockable_files.LockableFiles(transport,
1113
'', lockable_files.TransportLock)
989
temp_control = LockableFiles(transport, '', TransportLock)
1114
990
temp_control._transport.mkdir('.bzr',
1115
# FIXME: RBC 20060121 don't peek under
991
# FIXME: RBC 20060121 dont peek under
1117
993
mode=temp_control._dir_mode)
1118
994
file_mode = temp_control._file_mode
1125
1001
('branch-format', self.get_format_string()),
1127
1003
# NB: no need to escape relative paths that are url safe.
1128
control_files = lockable_files.LockableFiles(control,
1129
self._lock_file_name, self._lock_class)
1004
control_files = LockableFiles(control, self._lock_file_name,
1130
1006
control_files.create_lock()
1131
1007
control_files.lock_write()
1148
def same_model(self, target_format):
1149
return (self.repository_format.rich_root_data ==
1150
target_format.rich_root_data)
1153
def known_formats(klass):
1154
"""Return all the known formats.
1156
Concrete formats should override _known_formats.
1158
# There is double indirection here to make sure that control
1159
# formats used by more than one dir format will only be probed
1160
# once. This can otherwise be quite expensive for remote connections.
1162
for format in klass._control_formats:
1163
result.update(format._known_formats())
1167
def _known_formats(klass):
1168
"""Return the known format instances for this control format."""
1169
return set(klass._formats.values())
1171
1024
def open(self, transport, _found=False):
1172
1025
"""Return an instance of this format for the dir transport points at.
1174
1027
_found is a private parameter, do not use it.
1177
found_format = BzrDirFormat.find_format(transport)
1178
if not isinstance(found_format, self.__class__):
1179
raise AssertionError("%s was asked to open %s, but it seems to need "
1181
% (self, transport, found_format))
1030
assert isinstance(BzrDirFormat.find_format(transport),
1182
1032
return self._open(transport)
1184
1034
def _open(self, transport):
1194
1044
klass._formats[format.get_format_string()] = format
1197
def register_control_format(klass, format):
1198
"""Register a format that does not use '.bzrdir' for its control dir.
1200
TODO: This should be pulled up into a 'ControlDirFormat' base class
1201
which BzrDirFormat can inherit from, and renamed to register_format
1202
there. It has been done without that for now for simplicity of
1205
klass._control_formats.append(format)
1208
1047
def set_default_format(klass, format):
1209
1048
klass._default_format = format
1317
1148
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1318
1149
RepositoryFormat5().initialize(result, _internal=True)
1319
1150
if not _cloning:
1320
branch = BzrBranchFormat4().initialize(result)
1322
WorkingTreeFormat2().initialize(result)
1323
except errors.NotLocalUrl:
1324
# Even though we can't access the working tree, we need to
1325
# create its control files.
1326
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1151
BzrBranchFormat4().initialize(result)
1152
WorkingTreeFormat2().initialize(result)
1329
1155
def _open(self, transport):
1376
1202
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1377
1203
RepositoryFormat6().initialize(result, _internal=True)
1378
1204
if not _cloning:
1379
branch = BzrBranchFormat4().initialize(result)
1205
BzrBranchFormat4().initialize(result)
1381
1207
WorkingTreeFormat2().initialize(result)
1382
1208
except errors.NotLocalUrl:
1383
# Even though we can't access the working tree, we need to
1384
# create its control files.
1385
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1209
# emulate pre-check behaviour for working tree and silently
1388
1214
def _open(self, transport):
1310
class ScratchDir(BzrDir6):
1311
"""Special test class: a bzrdir that cleans up itself..
1313
>>> d = ScratchDir()
1314
>>> base = d.transport.base
1317
>>> b.transport.__del__()
1322
def __init__(self, files=[], dirs=[], transport=None):
1323
"""Make a test branch.
1325
This creates a temporary directory and runs init-tree in it.
1327
If any files are listed, they are created in the working copy.
1329
if transport is None:
1330
transport = bzrlib.transport.local.ScratchTransport()
1331
# local import for scope restriction
1332
BzrDirFormat6().initialize(transport.base)
1333
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1334
self.create_repository()
1335
self.create_branch()
1336
self.create_workingtree()
1338
super(ScratchDir, self).__init__(transport, BzrDirFormat6())
1340
# BzrBranch creates a clone to .bzr and then forgets about the
1341
# original transport. A ScratchTransport() deletes itself and
1342
# everything underneath it when it goes away, so we need to
1343
# grab a local copy to prevent that from happening
1344
self._transport = transport
1347
self._transport.mkdir(d)
1350
self._transport.put(f, 'content of %s' % f)
1354
>>> orig = ScratchDir(files=["file1", "file2"])
1355
>>> os.listdir(orig.base)
1356
[u'.bzr', u'file1', u'file2']
1357
>>> clone = orig.clone()
1358
>>> if os.name != 'nt':
1359
... os.path.samefile(orig.base, clone.base)
1361
... orig.base == clone.base
1364
>>> os.listdir(clone.base)
1365
[u'.bzr', u'file1', u'file2']
1367
from shutil import copytree
1368
from bzrlib.osutils import mkdtemp
1371
copytree(self.base, base, symlinks=True)
1373
transport=bzrlib.transport.local.ScratchTransport(base))
1484
1376
class Converter(object):
1485
1377
"""Converts a disk format object from one format to another."""
1571
1463
self.bzrdir.transport.delete_tree('text-store')
1573
1465
def _convert_working_inv(self):
1574
inv = xml4.serializer_v4.read_inventory(
1575
self.branch.control_files.get('inventory'))
1576
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
1466
inv = serializer_v4.read_inventory(self.branch.control_files.get('inventory'))
1467
new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1577
1468
# FIXME inventory is a working tree change.
1578
self.branch.control_files.put('inventory', StringIO(new_inv_xml))
1469
self.branch.control_files.put('inventory', new_inv_xml)
1580
1471
def _write_all_weaves(self):
1581
1472
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
1637
1528
def _load_old_inventory(self, rev_id):
1638
1529
assert rev_id not in self.converted_revs
1639
1530
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
1640
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
1641
inv.revision_id = rev_id
1531
inv = serializer_v4.read_inventory_from_string(old_inv_xml)
1642
1532
rev = self.revisions[rev_id]
1643
1533
if rev.inventory_sha1:
1644
1534
assert rev.inventory_sha1 == sha_string(old_inv_xml), \
1664
1554
def _store_new_weave(self, rev, inv, present_parents):
1665
1555
# the XML is now updated with text versions
1667
entries = inv.iter_entries()
1669
for path, ie in entries:
1670
assert getattr(ie, 'revision', None) is not None, \
1559
if ie.kind == 'root_directory':
1561
assert hasattr(ie, 'revision'), \
1671
1562
'no revision on {%s} in {%s}' % \
1672
1563
(file_id, rev.revision_id)
1673
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
1564
new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1674
1565
new_inv_sha1 = sha_string(new_inv_xml)
1675
1566
self.inv_weave.add_lines(rev.revision_id,
1676
1567
present_parents,
1685
1576
mutter('converting texts of revision {%s}',
1687
1578
parent_invs = map(self._load_updated_inventory, present_parents)
1688
entries = inv.iter_entries()
1690
for path, ie in entries:
1691
1581
self._convert_file_version(rev, ie, parent_invs)
1693
1583
def _convert_file_version(self, rev, ie, parent_invs):
1710
1602
for old_revision in previous_entries:
1711
1603
# if this fails, its a ghost ?
1712
assert old_revision in self.converted_revs, \
1713
"Revision {%s} not in converted_revs" % old_revision
1604
assert old_revision in self.converted_revs
1714
1605
self.snapshot_ie(previous_entries, ie, w, rev_id)
1716
1607
assert getattr(ie, 'revision', None) is not None
1781
1672
store_transport = self.bzrdir.transport.clone(store_name)
1782
1673
store = TransportStore(store_transport, prefixed=True)
1783
1674
for urlfilename in store_transport.list_dir('.'):
1784
filename = urlutils.unescape(urlfilename)
1675
filename = urlunescape(urlfilename)
1785
1676
if (filename.endswith(".weave") or
1786
1677
filename.endswith(".gz") or
1787
1678
filename.endswith(".sig")):
1851
1742
for entry in branch_files:
1852
1743
self.move_entry('branch', entry)
1745
self.step('Upgrading working tree')
1746
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1747
self.make_lock('checkout')
1748
self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1749
self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1854
1750
checkout_files = [('pending-merges', True),
1855
1751
('inventory', True),
1856
1752
('stat-cache', False)]
1857
# If a mandatory checkout file is not present, the branch does not have
1858
# a functional checkout. Do not create a checkout in the converted
1860
for name, mandatory in checkout_files:
1861
if mandatory and name not in bzrcontents:
1862
has_checkout = False
1866
if not has_checkout:
1867
self.pb.note('No working tree.')
1868
# If some checkout files are there, we may as well get rid of them.
1869
for name, mandatory in checkout_files:
1870
if name in bzrcontents:
1871
self.bzrdir.transport.delete(name)
1873
self.step('Upgrading working tree')
1874
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1875
self.make_lock('checkout')
1877
'checkout', bzrlib.workingtree.WorkingTreeFormat3())
1878
self.bzrdir.transport.delete_multi(
1879
self.garbage_inventories, self.pb)
1880
for entry in checkout_files:
1881
self.move_entry('checkout', entry)
1882
if last_revision is not None:
1883
self.bzrdir._control_files.put_utf8(
1884
'checkout/last-revision', last_revision)
1885
self.bzrdir._control_files.put_utf8(
1886
'branch-format', BzrDirMetaFormat1().get_format_string())
1753
for entry in checkout_files:
1754
self.move_entry('checkout', entry)
1755
if last_revision is not None:
1756
self.bzrdir._control_files.put_utf8('checkout/last-revision',
1758
self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
1887
1759
return BzrDir.open(self.bzrdir.root_transport.base)
1889
1761
def make_lock(self, name):
1890
1762
"""Make a lock for the new control dir name."""
1891
1763
self.step('Make %s lock' % name)
1892
ld = lockdir.LockDir(self.bzrdir.transport,
1894
file_modebits=self.file_mode,
1895
dir_modebits=self.dir_mode)
1764
ld = LockDir(self.bzrdir.transport,
1766
file_modebits=self.file_mode,
1767
dir_modebits=self.dir_mode)
1898
1770
def move_entry(self, new_dir, entry):