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
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
25
31
from copy import deepcopy
26
32
from cStringIO import StringIO
86
93
"""Return true if this bzrdir is one whose format we can convert from."""
96
def check_conversion_target(self, target_format):
97
target_repo_format = target_format.repository_format
98
source_repo_format = self._format.repository_format
99
source_repo_format.check_conversion_target(target_repo_format)
90
102
def _check_supported(format, allow_unsupported):
91
103
"""Check whether format is a supported format.
292
304
This will use the current default BzrDirFormat, and use whatever
293
305
repository format that that uses for bzrdirformat.create_repository.
295
;param shared: Create a shared repository rather than a standalone
307
:param shared: Create a shared repository rather than a standalone
297
309
The Repository object is returned.
313
325
repository format that that uses for bzrdirformat.create_workingtree,
314
326
create_branch and create_repository.
316
The WorkingTree object is returned.
328
:return: The WorkingTree object.
318
330
t = get_transport(safe_unicode(base))
319
331
if not isinstance(t, LocalTransport):
460
472
_unsupported is a private parameter to the BzrDir class.
462
474
t = get_transport(base)
463
mutter("trying to open %r with transport %r", base, t)
464
format = BzrDirFormat.find_format(t)
475
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
478
def open_from_transport(transport, _unsupported=False):
479
"""Open a bzrdir within a particular directory.
481
:param transport: Transport containing the bzrdir.
482
:param _unsupported: private.
484
format = BzrDirFormat.find_format(transport)
465
485
BzrDir._check_supported(format, _unsupported)
466
return format.open(t, _found=True)
486
return format.open(transport, _found=True)
468
488
def open_branch(self, unsupported=False):
469
489
"""Open the branch object at this BzrDir if one is present.
503
523
url = a_transport.base
506
format = BzrDirFormat.find_format(a_transport)
507
BzrDir._check_supported(format, False)
508
return format.open(a_transport), urlutils.unescape(a_transport.relpath(url))
526
result = BzrDir.open_from_transport(a_transport)
527
return result, urlutils.unescape(a_transport.relpath(url))
509
528
except errors.NotBranchError, e:
510
## mutter('not a branch in: %r %s', a_transport.base, e)
512
530
new_t = a_transport.clone('..')
513
531
if new_t.base == a_transport.base:
563
581
except errors.NoWorkingTree:
584
def cloning_metadir(self, basis=None):
585
"""Produce a metadir suitable for cloning with"""
586
def related_repository(bzrdir):
588
branch = bzrdir.open_branch()
589
return branch.repository
590
except errors.NotBranchError:
592
return bzrdir.open_repository()
593
result_format = self._format.__class__()
596
source_repository = related_repository(self)
597
except errors.NoRepositoryPresent:
600
source_repository = related_repository(self)
601
result_format.repository_format = source_repository._format
602
except errors.NoRepositoryPresent:
566
606
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
567
607
"""Create a copy of this bzrdir prepared for use as a new line of
578
618
itself to download less data.
580
620
self._make_tail(url)
581
result = self._format.initialize(url)
621
cloning_format = self.cloning_metadir(basis)
622
result = cloning_format.initialize(url)
582
623
basis_repo, basis_branch, basis_tree = self._get_basis_components(basis)
584
625
source_branch = self.open_branch()
615
656
# XXX FIXME RBC 20060214 need tests for this when the basis
617
658
result_repo.fetch(basis_repo, revision_id=revision_id)
618
result_repo.fetch(source_repository, revision_id=revision_id)
659
if source_repository is not None:
660
result_repo.fetch(source_repository, revision_id=revision_id)
619
661
if source_branch is not None:
620
662
source_branch.sprout(result, revision_id=revision_id)
685
727
# done on this format anyway. So - acceptable wart.
686
728
result = self.open_workingtree()
687
729
if revision_id is not None:
688
result.set_last_revision(revision_id)
730
if revision_id == bzrlib.revision.NULL_REVISION:
731
result.set_parent_ids([])
733
result.set_parent_ids([revision_id])
691
736
def get_branch_transport(self, branch_format):
733
778
self._check_supported(format, unsupported)
734
779
return format.open(self, _found=True)
736
def sprout(self, url, revision_id=None, basis=None):
781
def sprout(self, url, revision_id=None, basis=None, force_new_repo=False):
737
782
"""See BzrDir.sprout()."""
738
783
from bzrlib.workingtree import WorkingTreeFormat2
739
784
self._make_tail(url)
1173
1222
def __return_repository_format(self):
1174
1223
"""Circular import protection."""
1175
1224
from bzrlib.repository import RepositoryFormat4
1176
return RepositoryFormat4(self)
1225
return RepositoryFormat4()
1177
1226
repository_format = property(__return_repository_format)
1217
1266
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1218
1267
RepositoryFormat5().initialize(result, _internal=True)
1219
1268
if not _cloning:
1220
BzrBranchFormat4().initialize(result)
1221
WorkingTreeFormat2().initialize(result)
1269
branch = BzrBranchFormat4().initialize(result)
1271
WorkingTreeFormat2().initialize(result)
1272
except errors.NotLocalUrl:
1273
# Even though we can't access the working tree, we need to
1274
# create its control files.
1275
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1224
1278
def _open(self, transport):
1228
1282
def __return_repository_format(self):
1229
1283
"""Circular import protection."""
1230
1284
from bzrlib.repository import RepositoryFormat5
1231
return RepositoryFormat5(self)
1285
return RepositoryFormat5()
1232
1286
repository_format = property(__return_repository_format)
1271
1325
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1272
1326
RepositoryFormat6().initialize(result, _internal=True)
1273
1327
if not _cloning:
1274
BzrBranchFormat4().initialize(result)
1328
branch = BzrBranchFormat4().initialize(result)
1276
1330
WorkingTreeFormat2().initialize(result)
1277
1331
except errors.NotLocalUrl:
1278
# emulate pre-check behaviour for working tree and silently
1332
# Even though we can't access the working tree, we need to
1333
# create its control files.
1334
WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
1283
1337
def _open(self, transport):
1287
1341
def __return_repository_format(self):
1288
1342
"""Circular import protection."""
1289
1343
from bzrlib.repository import RepositoryFormat6
1290
return RepositoryFormat6(self)
1344
return RepositoryFormat6()
1291
1345
repository_format = property(__return_repository_format)
1469
1523
inv = serializer_v4.read_inventory(self.branch.control_files.get('inventory'))
1470
1524
new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1471
1525
# FIXME inventory is a working tree change.
1472
self.branch.control_files.put('inventory', new_inv_xml)
1526
self.branch.control_files.put('inventory', StringIO(new_inv_xml))
1474
1528
def _write_all_weaves(self):
1475
1529
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
1557
1612
def _store_new_weave(self, rev, inv, present_parents):
1558
1613
# the XML is now updated with text versions
1562
if ie.kind == 'root_directory':
1564
assert hasattr(ie, 'revision'), \
1615
entries = inv.iter_entries()
1617
for path, ie in entries:
1618
assert getattr(ie, 'revision', None) is not None, \
1565
1619
'no revision on {%s} in {%s}' % \
1566
1620
(file_id, rev.revision_id)
1567
1621
new_inv_xml = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
1579
1633
mutter('converting texts of revision {%s}',
1581
1635
parent_invs = map(self._load_updated_inventory, present_parents)
1636
entries = inv.iter_entries()
1638
for path, ie in entries:
1584
1639
self._convert_file_version(rev, ie, parent_invs)
1586
1641
def _convert_file_version(self, rev, ie, parent_invs):
1745
1798
for entry in branch_files:
1746
1799
self.move_entry('branch', entry)
1748
self.step('Upgrading working tree')
1749
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1750
self.make_lock('checkout')
1751
self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1752
self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1753
1801
checkout_files = [('pending-merges', True),
1754
1802
('inventory', True),
1755
1803
('stat-cache', False)]
1756
for entry in checkout_files:
1757
self.move_entry('checkout', entry)
1758
if last_revision is not None:
1759
self.bzrdir._control_files.put_utf8('checkout/last-revision',
1761
self.bzrdir._control_files.put_utf8('branch-format', BzrDirMetaFormat1().get_format_string())
1804
# If a mandatory checkout file is not present, the branch does not have
1805
# a functional checkout. Do not create a checkout in the converted
1807
for name, mandatory in checkout_files:
1808
if mandatory and name not in bzrcontents:
1809
has_checkout = False
1813
if not has_checkout:
1814
self.pb.note('No working tree.')
1815
# If some checkout files are there, we may as well get rid of them.
1816
for name, mandatory in checkout_files:
1817
if name in bzrcontents:
1818
self.bzrdir.transport.delete(name)
1820
self.step('Upgrading working tree')
1821
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1822
self.make_lock('checkout')
1824
'checkout', bzrlib.workingtree.WorkingTreeFormat3())
1825
self.bzrdir.transport.delete_multi(
1826
self.garbage_inventories, self.pb)
1827
for entry in checkout_files:
1828
self.move_entry('checkout', entry)
1829
if last_revision is not None:
1830
self.bzrdir._control_files.put_utf8(
1831
'checkout/last-revision', last_revision)
1832
self.bzrdir._control_files.put_utf8(
1833
'branch-format', BzrDirMetaFormat1().get_format_string())
1762
1834
return BzrDir.open(self.bzrdir.root_transport.base)
1764
1836
def make_lock(self, name):