1001
class BzrDirPreSplitOut(BzrDir):
1002
"""A common class for the all-in-one formats."""
1004
def __init__(self, _transport, _format):
1005
"""See BzrDir.__init__."""
1006
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1007
self._control_files = lockable_files.LockableFiles(
1008
self.get_branch_transport(None),
1009
self._format._lock_file_name,
1010
self._format._lock_class)
1012
def break_lock(self):
1013
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1014
raise NotImplementedError(self.break_lock)
1016
def cloning_metadir(self, require_stacking=False):
1017
"""Produce a metadir suitable for cloning with."""
1018
if require_stacking:
1019
return controldir.format_registry.make_bzrdir('1.6')
1020
return self._format.__class__()
1022
def clone(self, url, revision_id=None, force_new_repo=False,
1023
preserve_stacking=False):
1024
"""See BzrDir.clone().
1026
force_new_repo has no effect, since this family of formats always
1027
require a new repository.
1028
preserve_stacking has no effect, since no source branch using this
1029
family of formats can be stacked, so there is no stacking to preserve.
1031
self._make_tail(url)
1032
result = self._format._initialize_for_clone(url)
1033
self.open_repository().clone(result, revision_id=revision_id)
1034
from_branch = self.open_branch()
1035
from_branch.clone(result, revision_id=revision_id)
1037
tree = self.open_workingtree()
1038
except errors.NotLocalUrl:
1039
# make a new one, this format always has to have one.
1040
result._init_workingtree()
1045
def create_branch(self, name=None):
1046
"""See BzrDir.create_branch."""
1047
return self._format.get_branch_format().initialize(self, name=name)
1049
def destroy_branch(self, name=None):
1050
"""See BzrDir.destroy_branch."""
1051
raise errors.UnsupportedOperation(self.destroy_branch, self)
1053
def create_repository(self, shared=False):
1054
"""See BzrDir.create_repository."""
1056
raise errors.IncompatibleFormat('shared repository', self._format)
1057
return self.open_repository()
1059
def destroy_repository(self):
1060
"""See BzrDir.destroy_repository."""
1061
raise errors.UnsupportedOperation(self.destroy_repository, self)
1063
def create_workingtree(self, revision_id=None, from_branch=None,
1064
accelerator_tree=None, hardlink=False):
1065
"""See BzrDir.create_workingtree."""
1066
# The workingtree is sometimes created when the bzrdir is created,
1067
# but not when cloning.
1069
# this looks buggy but is not -really-
1070
# because this format creates the workingtree when the bzrdir is
1072
# clone and sprout will have set the revision_id
1073
# and that will have set it for us, its only
1074
# specific uses of create_workingtree in isolation
1075
# that can do wonky stuff here, and that only
1076
# happens for creating checkouts, which cannot be
1077
# done on this format anyway. So - acceptable wart.
1079
warning("can't support hardlinked working trees in %r"
1082
result = self.open_workingtree(recommend_upgrade=False)
1083
except errors.NoSuchFile:
1084
result = self._init_workingtree()
1085
if revision_id is not None:
1086
if revision_id == _mod_revision.NULL_REVISION:
1087
result.set_parent_ids([])
1089
result.set_parent_ids([revision_id])
1092
def _init_workingtree(self):
1093
from bzrlib.workingtree import WorkingTreeFormat2
1095
return WorkingTreeFormat2().initialize(self)
1096
except errors.NotLocalUrl:
1097
# Even though we can't access the working tree, we need to
1098
# create its control files.
1099
return WorkingTreeFormat2()._stub_initialize_on_transport(
1100
self.transport, self._control_files._file_mode)
1102
def destroy_workingtree(self):
1103
"""See BzrDir.destroy_workingtree."""
1104
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1106
def destroy_workingtree_metadata(self):
1107
"""See BzrDir.destroy_workingtree_metadata."""
1108
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1111
def get_branch_transport(self, branch_format, name=None):
1112
"""See BzrDir.get_branch_transport()."""
1113
if name is not None:
1114
raise errors.NoColocatedBranchSupport(self)
1115
if branch_format is None:
1116
return self.transport
1118
branch_format.get_format_string()
1119
except NotImplementedError:
1120
return self.transport
1121
raise errors.IncompatibleFormat(branch_format, self._format)
1123
def get_repository_transport(self, repository_format):
1124
"""See BzrDir.get_repository_transport()."""
1125
if repository_format is None:
1126
return self.transport
1128
repository_format.get_format_string()
1129
except NotImplementedError:
1130
return self.transport
1131
raise errors.IncompatibleFormat(repository_format, self._format)
1133
def get_workingtree_transport(self, workingtree_format):
1134
"""See BzrDir.get_workingtree_transport()."""
1135
if workingtree_format is None:
1136
return self.transport
1138
workingtree_format.get_format_string()
1139
except NotImplementedError:
1140
return self.transport
1141
raise errors.IncompatibleFormat(workingtree_format, self._format)
1143
def needs_format_conversion(self, format=None):
1144
"""See BzrDir.needs_format_conversion()."""
1145
# if the format is not the same as the system default,
1146
# an upgrade is needed.
1148
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1149
% 'needs_format_conversion(format=None)')
1150
format = BzrDirFormat.get_default_format()
1151
return not isinstance(self._format, format.__class__)
1153
def open_branch(self, name=None, unsupported=False,
1154
ignore_fallbacks=False):
1155
"""See BzrDir.open_branch."""
1156
from bzrlib.branch import BzrBranchFormat4
1157
format = BzrBranchFormat4()
1158
self._check_supported(format, unsupported)
1159
return format.open(self, name, _found=True)
1161
def sprout(self, url, revision_id=None, force_new_repo=False,
1162
possible_transports=None, accelerator_tree=None,
1163
hardlink=False, stacked=False, create_tree_if_local=True,
1164
source_branch=None):
1165
"""See BzrDir.sprout()."""
1166
if source_branch is not None:
1167
my_branch = self.open_branch()
1168
if source_branch.base != my_branch.base:
1169
raise AssertionError(
1170
"source branch %r is not within %r with branch %r" %
1171
(source_branch, self, my_branch))
1173
raise errors.UnstackableBranchFormat(
1174
self._format, self.root_transport.base)
1175
if not create_tree_if_local:
1176
raise errors.MustHaveWorkingTree(
1177
self._format, self.root_transport.base)
1178
from bzrlib.workingtree import WorkingTreeFormat2
1179
self._make_tail(url)
1180
result = self._format._initialize_for_clone(url)
1182
self.open_repository().clone(result, revision_id=revision_id)
1183
except errors.NoRepositoryPresent:
1186
self.open_branch().sprout(result, revision_id=revision_id)
1187
except errors.NotBranchError:
1190
# we always want a working tree
1191
WorkingTreeFormat2().initialize(result,
1192
accelerator_tree=accelerator_tree,
1197
class BzrDir4(BzrDirPreSplitOut):
1198
"""A .bzr version 4 control object.
1200
This is a deprecated format and may be removed after sept 2006.
1203
def create_repository(self, shared=False):
1204
"""See BzrDir.create_repository."""
1205
return self._format.repository_format.initialize(self, shared)
1207
def needs_format_conversion(self, format=None):
1208
"""Format 4 dirs are always in need of conversion."""
1210
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1211
% 'needs_format_conversion(format=None)')
1214
def open_repository(self):
1215
"""See BzrDir.open_repository."""
1216
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1217
return RepositoryFormat4().open(self, _found=True)
1220
class BzrDir5(BzrDirPreSplitOut):
1221
"""A .bzr version 5 control object.
1223
This is a deprecated format and may be removed after sept 2006.
1226
def has_workingtree(self):
1227
"""See BzrDir.has_workingtree."""
1230
def open_repository(self):
1231
"""See BzrDir.open_repository."""
1232
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1233
return RepositoryFormat5().open(self, _found=True)
1235
def open_workingtree(self, _unsupported=False,
1236
recommend_upgrade=True):
1237
"""See BzrDir.create_workingtree."""
1238
from bzrlib.workingtree import WorkingTreeFormat2
1239
wt_format = WorkingTreeFormat2()
1240
# we don't warn here about upgrades; that ought to be handled for the
1242
return wt_format.open(self, _found=True)
1245
class BzrDir6(BzrDirPreSplitOut):
1246
"""A .bzr version 6 control object.
1248
This is a deprecated format and may be removed after sept 2006.
1251
def has_workingtree(self):
1252
"""See BzrDir.has_workingtree."""
1255
def open_repository(self):
1256
"""See BzrDir.open_repository."""
1257
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1258
return RepositoryFormat6().open(self, _found=True)
1260
def open_workingtree(self, _unsupported=False,
1261
recommend_upgrade=True):
1262
"""See BzrDir.create_workingtree."""
1263
# we don't warn here about upgrades; that ought to be handled for the
1265
from bzrlib.workingtree import WorkingTreeFormat2
1266
return WorkingTreeFormat2().open(self, _found=True)
1269
980
class BzrDirMeta1(BzrDir):
1270
981
"""A .bzr meta version 1 control object.
1738
1453
def unregister_format(klass, format):
1739
1454
BzrProber.unregister_bzrdir_format(format)
1740
1455
controldir.ControlDirFormat.unregister_format(format)
1741
network_format_registry.remove(format.get_format_string())
1744
class BzrDirFormat4(BzrDirFormat):
1745
"""Bzr dir format 4.
1747
This format is a combined format for working tree, branch and repository.
1749
- Format 1 working trees [always]
1750
- Format 4 branches [always]
1751
- Format 4 repositories [always]
1753
This format is deprecated: it indexes texts using a text it which is
1754
removed in format 5; write support for this format has been removed.
1757
_lock_class = lockable_files.TransportLock
1759
def get_format_string(self):
1760
"""See BzrDirFormat.get_format_string()."""
1761
return "Bazaar-NG branch, format 0.0.4\n"
1763
def get_format_description(self):
1764
"""See BzrDirFormat.get_format_description()."""
1765
return "All-in-one format 4"
1767
def get_converter(self, format=None):
1768
"""See BzrDirFormat.get_converter()."""
1769
# there is one and only one upgrade path here.
1770
return ConvertBzrDir4To5()
1772
def initialize_on_transport(self, transport):
1773
"""Format 4 branches cannot be created."""
1774
raise errors.UninitializableFormat(self)
1776
def is_supported(self):
1777
"""Format 4 is not supported.
1779
It is not supported because the model changed from 4 to 5 and the
1780
conversion logic is expensive - so doing it on the fly was not
1785
def network_name(self):
1786
return self.get_format_string()
1788
def _open(self, transport):
1789
"""See BzrDirFormat._open."""
1790
return BzrDir4(transport, self)
1792
def __return_repository_format(self):
1793
"""Circular import protection."""
1794
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1795
return RepositoryFormat4()
1796
repository_format = property(__return_repository_format)
1799
class BzrDirFormatAllInOne(BzrDirFormat):
1800
"""Common class for formats before meta-dirs."""
1802
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1803
create_prefix=False, force_new_repo=False, stacked_on=None,
1804
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1806
"""See BzrDirFormat.initialize_on_transport_ex."""
1807
require_stacking = (stacked_on is not None)
1808
# Format 5 cannot stack, but we've been asked to - actually init
1810
if require_stacking:
1811
format = BzrDirMetaFormat1()
1812
return format.initialize_on_transport_ex(transport,
1813
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1814
force_new_repo=force_new_repo, stacked_on=stacked_on,
1815
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1816
make_working_trees=make_working_trees, shared_repo=shared_repo)
1817
return BzrDirFormat.initialize_on_transport_ex(self, transport,
1818
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1819
force_new_repo=force_new_repo, stacked_on=stacked_on,
1820
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1821
make_working_trees=make_working_trees, shared_repo=shared_repo)
1824
class BzrDirFormat5(BzrDirFormatAllInOne):
1825
"""Bzr control format 5.
1827
This format is a combined format for working tree, branch and repository.
1829
- Format 2 working trees [always]
1830
- Format 4 branches [always]
1831
- Format 5 repositories [always]
1832
Unhashed stores in the repository.
1835
_lock_class = lockable_files.TransportLock
1837
def get_format_string(self):
1838
"""See BzrDirFormat.get_format_string()."""
1839
return "Bazaar-NG branch, format 5\n"
1841
def get_branch_format(self):
1842
from bzrlib import branch
1843
return branch.BzrBranchFormat4()
1845
def get_format_description(self):
1846
"""See BzrDirFormat.get_format_description()."""
1847
return "All-in-one format 5"
1849
def get_converter(self, format=None):
1850
"""See BzrDirFormat.get_converter()."""
1851
# there is one and only one upgrade path here.
1852
return ConvertBzrDir5To6()
1854
def _initialize_for_clone(self, url):
1855
return self.initialize_on_transport(get_transport(url), _cloning=True)
1857
def initialize_on_transport(self, transport, _cloning=False):
1858
"""Format 5 dirs always have working tree, branch and repository.
1860
Except when they are being cloned.
1862
from bzrlib.branch import BzrBranchFormat4
1863
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1864
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1865
RepositoryFormat5().initialize(result, _internal=True)
1867
branch = BzrBranchFormat4().initialize(result)
1868
result._init_workingtree()
1871
def network_name(self):
1872
return self.get_format_string()
1874
def _open(self, transport):
1875
"""See BzrDirFormat._open."""
1876
return BzrDir5(transport, self)
1878
def __return_repository_format(self):
1879
"""Circular import protection."""
1880
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1881
return RepositoryFormat5()
1882
repository_format = property(__return_repository_format)
1885
class BzrDirFormat6(BzrDirFormatAllInOne):
1886
"""Bzr control format 6.
1888
This format is a combined format for working tree, branch and repository.
1890
- Format 2 working trees [always]
1891
- Format 4 branches [always]
1892
- Format 6 repositories [always]
1895
_lock_class = lockable_files.TransportLock
1897
def get_format_string(self):
1898
"""See BzrDirFormat.get_format_string()."""
1899
return "Bazaar-NG branch, format 6\n"
1901
def get_format_description(self):
1902
"""See BzrDirFormat.get_format_description()."""
1903
return "All-in-one format 6"
1905
def get_branch_format(self):
1906
from bzrlib import branch
1907
return branch.BzrBranchFormat4()
1909
def get_converter(self, format=None):
1910
"""See BzrDirFormat.get_converter()."""
1911
# there is one and only one upgrade path here.
1912
return ConvertBzrDir6ToMeta()
1914
def _initialize_for_clone(self, url):
1915
return self.initialize_on_transport(get_transport(url), _cloning=True)
1917
def initialize_on_transport(self, transport, _cloning=False):
1918
"""Format 6 dirs always have working tree, branch and repository.
1920
Except when they are being cloned.
1922
from bzrlib.branch import BzrBranchFormat4
1923
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1924
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1925
RepositoryFormat6().initialize(result, _internal=True)
1927
branch = BzrBranchFormat4().initialize(result)
1928
result._init_workingtree()
1931
def network_name(self):
1932
return self.get_format_string()
1934
def _open(self, transport):
1935
"""See BzrDirFormat._open."""
1936
return BzrDir6(transport, self)
1938
def __return_repository_format(self):
1939
"""Circular import protection."""
1940
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1941
return RepositoryFormat6()
1942
repository_format = property(__return_repository_format)
1456
controldir.network_format_registry.remove(format.get_format_string())
1945
1459
class BzrDirMetaFormat1(BzrDirFormat):
2181
1683
self.pb.update(message, self.count, self.total)
2184
class ConvertBzrDir4To5(Converter):
2185
"""Converts format 4 bzr dirs to format 5."""
2188
super(ConvertBzrDir4To5, self).__init__()
2189
self.converted_revs = set()
2190
self.absent_revisions = set()
2194
def convert(self, to_convert, pb):
2195
"""See Converter.convert()."""
2196
self.bzrdir = to_convert
2198
warnings.warn("pb parameter to convert() is deprecated")
2199
self.pb = ui.ui_factory.nested_progress_bar()
2201
ui.ui_factory.note('starting upgrade from format 4 to 5')
2202
if isinstance(self.bzrdir.transport, local.LocalTransport):
2203
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2204
self._convert_to_weaves()
2205
return BzrDir.open(self.bzrdir.user_url)
2209
def _convert_to_weaves(self):
2210
ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
2213
stat = self.bzrdir.transport.stat('weaves')
2214
if not S_ISDIR(stat.st_mode):
2215
self.bzrdir.transport.delete('weaves')
2216
self.bzrdir.transport.mkdir('weaves')
2217
except errors.NoSuchFile:
2218
self.bzrdir.transport.mkdir('weaves')
2219
# deliberately not a WeaveFile as we want to build it up slowly.
2220
self.inv_weave = Weave('inventory')
2221
# holds in-memory weaves for all files
2222
self.text_weaves = {}
2223
self.bzrdir.transport.delete('branch-format')
2224
self.branch = self.bzrdir.open_branch()
2225
self._convert_working_inv()
2226
rev_history = self.branch.revision_history()
2227
# to_read is a stack holding the revisions we still need to process;
2228
# appending to it adds new highest-priority revisions
2229
self.known_revisions = set(rev_history)
2230
self.to_read = rev_history[-1:]
2232
rev_id = self.to_read.pop()
2233
if (rev_id not in self.revisions
2234
and rev_id not in self.absent_revisions):
2235
self._load_one_rev(rev_id)
2237
to_import = self._make_order()
2238
for i, rev_id in enumerate(to_import):
2239
self.pb.update('converting revision', i, len(to_import))
2240
self._convert_one_rev(rev_id)
2242
self._write_all_weaves()
2243
self._write_all_revs()
2244
ui.ui_factory.note('upgraded to weaves:')
2245
ui.ui_factory.note(' %6d revisions and inventories' % len(self.revisions))
2246
ui.ui_factory.note(' %6d revisions not present' % len(self.absent_revisions))
2247
ui.ui_factory.note(' %6d texts' % self.text_count)
2248
self._cleanup_spare_files_after_format4()
2249
self.branch._transport.put_bytes(
2251
BzrDirFormat5().get_format_string(),
2252
mode=self.bzrdir._get_file_mode())
2254
def _cleanup_spare_files_after_format4(self):
2255
# FIXME working tree upgrade foo.
2256
for n in 'merged-patches', 'pending-merged-patches':
2258
## assert os.path.getsize(p) == 0
2259
self.bzrdir.transport.delete(n)
2260
except errors.NoSuchFile:
2262
self.bzrdir.transport.delete_tree('inventory-store')
2263
self.bzrdir.transport.delete_tree('text-store')
2265
def _convert_working_inv(self):
2266
inv = xml4.serializer_v4.read_inventory(
2267
self.branch._transport.get('inventory'))
2268
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2269
self.branch._transport.put_bytes('inventory', new_inv_xml,
2270
mode=self.bzrdir._get_file_mode())
2272
def _write_all_weaves(self):
2273
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2274
weave_transport = self.bzrdir.transport.clone('weaves')
2275
weaves = WeaveStore(weave_transport, prefixed=False)
2276
transaction = WriteTransaction()
2280
for file_id, file_weave in self.text_weaves.items():
2281
self.pb.update('writing weave', i, len(self.text_weaves))
2282
weaves._put_weave(file_id, file_weave, transaction)
2284
self.pb.update('inventory', 0, 1)
2285
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2286
self.pb.update('inventory', 1, 1)
2290
def _write_all_revs(self):
2291
"""Write all revisions out in new form."""
2292
self.bzrdir.transport.delete_tree('revision-store')
2293
self.bzrdir.transport.mkdir('revision-store')
2294
revision_transport = self.bzrdir.transport.clone('revision-store')
2296
from bzrlib.xml5 import serializer_v5
2297
from bzrlib.repofmt.weaverepo import RevisionTextStore
2298
revision_store = RevisionTextStore(revision_transport,
2299
serializer_v5, False, versionedfile.PrefixMapper(),
2300
lambda:True, lambda:True)
2302
for i, rev_id in enumerate(self.converted_revs):
2303
self.pb.update('write revision', i, len(self.converted_revs))
2304
text = serializer_v5.write_revision_to_string(
2305
self.revisions[rev_id])
2307
revision_store.add_lines(key, None, osutils.split_lines(text))
2311
def _load_one_rev(self, rev_id):
2312
"""Load a revision object into memory.
2314
Any parents not either loaded or abandoned get queued to be
2316
self.pb.update('loading revision',
2317
len(self.revisions),
2318
len(self.known_revisions))
2319
if not self.branch.repository.has_revision(rev_id):
2321
ui.ui_factory.note('revision {%s} not present in branch; '
2322
'will be converted as a ghost' %
2324
self.absent_revisions.add(rev_id)
2326
rev = self.branch.repository.get_revision(rev_id)
2327
for parent_id in rev.parent_ids:
2328
self.known_revisions.add(parent_id)
2329
self.to_read.append(parent_id)
2330
self.revisions[rev_id] = rev
2332
def _load_old_inventory(self, rev_id):
2333
f = self.branch.repository.inventory_store.get(rev_id)
2335
old_inv_xml = f.read()
2338
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2339
inv.revision_id = rev_id
2340
rev = self.revisions[rev_id]
2343
def _load_updated_inventory(self, rev_id):
2344
inv_xml = self.inv_weave.get_text(rev_id)
2345
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2348
def _convert_one_rev(self, rev_id):
2349
"""Convert revision and all referenced objects to new format."""
2350
rev = self.revisions[rev_id]
2351
inv = self._load_old_inventory(rev_id)
2352
present_parents = [p for p in rev.parent_ids
2353
if p not in self.absent_revisions]
2354
self._convert_revision_contents(rev, inv, present_parents)
2355
self._store_new_inv(rev, inv, present_parents)
2356
self.converted_revs.add(rev_id)
2358
def _store_new_inv(self, rev, inv, present_parents):
2359
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2360
new_inv_sha1 = sha_string(new_inv_xml)
2361
self.inv_weave.add_lines(rev.revision_id,
2363
new_inv_xml.splitlines(True))
2364
rev.inventory_sha1 = new_inv_sha1
2366
def _convert_revision_contents(self, rev, inv, present_parents):
2367
"""Convert all the files within a revision.
2369
Also upgrade the inventory to refer to the text revision ids."""
2370
rev_id = rev.revision_id
2371
mutter('converting texts of revision {%s}',
2373
parent_invs = map(self._load_updated_inventory, present_parents)
2374
entries = inv.iter_entries()
2376
for path, ie in entries:
2377
self._convert_file_version(rev, ie, parent_invs)
2379
def _convert_file_version(self, rev, ie, parent_invs):
2380
"""Convert one version of one file.
2382
The file needs to be added into the weave if it is a merge
2383
of >=2 parents or if it's changed from its parent.
2385
file_id = ie.file_id
2386
rev_id = rev.revision_id
2387
w = self.text_weaves.get(file_id)
2390
self.text_weaves[file_id] = w
2391
text_changed = False
2392
parent_candiate_entries = ie.parent_candidates(parent_invs)
2393
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2394
# XXX: Note that this is unordered - and this is tolerable because
2395
# the previous code was also unordered.
2396
previous_entries = dict((head, parent_candiate_entries[head]) for head
2398
self.snapshot_ie(previous_entries, ie, w, rev_id)
2400
def get_parent_map(self, revision_ids):
2401
"""See graph.StackedParentsProvider.get_parent_map"""
2402
return dict((revision_id, self.revisions[revision_id])
2403
for revision_id in revision_ids
2404
if revision_id in self.revisions)
2406
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2407
# TODO: convert this logic, which is ~= snapshot to
2408
# a call to:. This needs the path figured out. rather than a work_tree
2409
# a v4 revision_tree can be given, or something that looks enough like
2410
# one to give the file content to the entry if it needs it.
2411
# and we need something that looks like a weave store for snapshot to
2413
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2414
if len(previous_revisions) == 1:
2415
previous_ie = previous_revisions.values()[0]
2416
if ie._unchanged(previous_ie):
2417
ie.revision = previous_ie.revision
2420
f = self.branch.repository._text_store.get(ie.text_id)
2422
file_lines = f.readlines()
2425
w.add_lines(rev_id, previous_revisions, file_lines)
2426
self.text_count += 1
2428
w.add_lines(rev_id, previous_revisions, [])
2429
ie.revision = rev_id
2431
def _make_order(self):
2432
"""Return a suitable order for importing revisions.
2434
The order must be such that an revision is imported after all
2435
its (present) parents.
2437
todo = set(self.revisions.keys())
2438
done = self.absent_revisions.copy()
2441
# scan through looking for a revision whose parents
2443
for rev_id in sorted(list(todo)):
2444
rev = self.revisions[rev_id]
2445
parent_ids = set(rev.parent_ids)
2446
if parent_ids.issubset(done):
2447
# can take this one now
2448
order.append(rev_id)
2454
class ConvertBzrDir5To6(Converter):
2455
"""Converts format 5 bzr dirs to format 6."""
2457
def convert(self, to_convert, pb):
2458
"""See Converter.convert()."""
2459
self.bzrdir = to_convert
2460
pb = ui.ui_factory.nested_progress_bar()
2462
ui.ui_factory.note('starting upgrade from format 5 to 6')
2463
self._convert_to_prefixed()
2464
return BzrDir.open(self.bzrdir.user_url)
2468
def _convert_to_prefixed(self):
2469
from bzrlib.store import TransportStore
2470
self.bzrdir.transport.delete('branch-format')
2471
for store_name in ["weaves", "revision-store"]:
2472
ui.ui_factory.note("adding prefixes to %s" % store_name)
2473
store_transport = self.bzrdir.transport.clone(store_name)
2474
store = TransportStore(store_transport, prefixed=True)
2475
for urlfilename in store_transport.list_dir('.'):
2476
filename = urlutils.unescape(urlfilename)
2477
if (filename.endswith(".weave") or
2478
filename.endswith(".gz") or
2479
filename.endswith(".sig")):
2480
file_id, suffix = os.path.splitext(filename)
2484
new_name = store._mapper.map((file_id,)) + suffix
2485
# FIXME keep track of the dirs made RBC 20060121
2487
store_transport.move(filename, new_name)
2488
except errors.NoSuchFile: # catches missing dirs strangely enough
2489
store_transport.mkdir(osutils.dirname(new_name))
2490
store_transport.move(filename, new_name)
2491
self.bzrdir.transport.put_bytes(
2493
BzrDirFormat6().get_format_string(),
2494
mode=self.bzrdir._get_file_mode())
2497
class ConvertBzrDir6ToMeta(Converter):
2498
"""Converts format 6 bzr dirs to metadirs."""
2500
def convert(self, to_convert, pb):
2501
"""See Converter.convert()."""
2502
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2503
from bzrlib.branch import BzrBranchFormat5
2504
self.bzrdir = to_convert
2505
self.pb = ui.ui_factory.nested_progress_bar()
2507
self.total = 20 # the steps we know about
2508
self.garbage_inventories = []
2509
self.dir_mode = self.bzrdir._get_dir_mode()
2510
self.file_mode = self.bzrdir._get_file_mode()
2512
ui.ui_factory.note('starting upgrade from format 6 to metadir')
2513
self.bzrdir.transport.put_bytes(
2515
"Converting to format 6",
2516
mode=self.file_mode)
2517
# its faster to move specific files around than to open and use the apis...
2518
# first off, nuke ancestry.weave, it was never used.
2520
self.step('Removing ancestry.weave')
2521
self.bzrdir.transport.delete('ancestry.weave')
2522
except errors.NoSuchFile:
2524
# find out whats there
2525
self.step('Finding branch files')
2526
last_revision = self.bzrdir.open_branch().last_revision()
2527
bzrcontents = self.bzrdir.transport.list_dir('.')
2528
for name in bzrcontents:
2529
if name.startswith('basis-inventory.'):
2530
self.garbage_inventories.append(name)
2531
# create new directories for repository, working tree and branch
2532
repository_names = [('inventory.weave', True),
2533
('revision-store', True),
2535
self.step('Upgrading repository ')
2536
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2537
self.make_lock('repository')
2538
# we hard code the formats here because we are converting into
2539
# the meta format. The meta format upgrader can take this to a
2540
# future format within each component.
2541
self.put_format('repository', RepositoryFormat7())
2542
for entry in repository_names:
2543
self.move_entry('repository', entry)
2545
self.step('Upgrading branch ')
2546
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2547
self.make_lock('branch')
2548
self.put_format('branch', BzrBranchFormat5())
2549
branch_files = [('revision-history', True),
2550
('branch-name', True),
2552
for entry in branch_files:
2553
self.move_entry('branch', entry)
2555
checkout_files = [('pending-merges', True),
2556
('inventory', True),
2557
('stat-cache', False)]
2558
# If a mandatory checkout file is not present, the branch does not have
2559
# a functional checkout. Do not create a checkout in the converted
2561
for name, mandatory in checkout_files:
2562
if mandatory and name not in bzrcontents:
2563
has_checkout = False
2567
if not has_checkout:
2568
ui.ui_factory.note('No working tree.')
2569
# If some checkout files are there, we may as well get rid of them.
2570
for name, mandatory in checkout_files:
2571
if name in bzrcontents:
2572
self.bzrdir.transport.delete(name)
2574
from bzrlib.workingtree import WorkingTreeFormat3
2575
self.step('Upgrading working tree')
2576
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2577
self.make_lock('checkout')
2579
'checkout', WorkingTreeFormat3())
2580
self.bzrdir.transport.delete_multi(
2581
self.garbage_inventories, self.pb)
2582
for entry in checkout_files:
2583
self.move_entry('checkout', entry)
2584
if last_revision is not None:
2585
self.bzrdir.transport.put_bytes(
2586
'checkout/last-revision', last_revision)
2587
self.bzrdir.transport.put_bytes(
2589
BzrDirMetaFormat1().get_format_string(),
2590
mode=self.file_mode)
2592
return BzrDir.open(self.bzrdir.user_url)
2594
def make_lock(self, name):
2595
"""Make a lock for the new control dir name."""
2596
self.step('Make %s lock' % name)
2597
ld = lockdir.LockDir(self.bzrdir.transport,
2599
file_modebits=self.file_mode,
2600
dir_modebits=self.dir_mode)
2603
def move_entry(self, new_dir, entry):
2604
"""Move then entry name into new_dir."""
2606
mandatory = entry[1]
2607
self.step('Moving %s' % name)
2609
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2610
except errors.NoSuchFile:
2614
def put_format(self, dirname, format):
2615
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2616
format.get_format_string(),
2620
1686
class ConvertMetaToMeta(Converter):
2621
1687
"""Converts the components of metadirs."""