869
869
return not self.control_files._transport.has('no-working-trees')
872
class KnitRepository(MetaDirRepository):
873
"""Knit format repository."""
875
def _warn_if_deprecated(self):
876
# This class isn't deprecated
879
def _inventory_add_lines(self, inv_vf, revid, parents, lines):
880
inv_vf.add_lines_with_ghosts(revid, parents, lines)
883
def _all_revision_ids(self):
884
"""See Repository.all_revision_ids()."""
885
# Knits get the revision graph from the index of the revision knit, so
886
# it's always possible even if they're on an unlistable transport.
887
return self._revision_store.all_revision_ids(self.get_transaction())
889
def fileid_involved_between_revs(self, from_revid, to_revid):
890
"""Find file_id(s) which are involved in the changes between revisions.
892
This determines the set of revisions which are involved, and then
893
finds all file ids affected by those revisions.
895
vf = self._get_revision_vf()
896
from_set = set(vf.get_ancestry(from_revid))
897
to_set = set(vf.get_ancestry(to_revid))
898
changed = to_set.difference(from_set)
899
return self._fileid_involved_by_set(changed)
901
def fileid_involved(self, last_revid=None):
902
"""Find all file_ids modified in the ancestry of last_revid.
904
:param last_revid: If None, last_revision() will be used.
907
changed = set(self.all_revision_ids())
909
changed = set(self.get_ancestry(last_revid))
912
return self._fileid_involved_by_set(changed)
915
def get_ancestry(self, revision_id):
916
"""Return a list of revision-ids integrated by a revision.
918
This is topologically sorted.
920
if revision_id is None:
922
vf = self._get_revision_vf()
924
return [None] + vf.get_ancestry(revision_id)
925
except errors.RevisionNotPresent:
926
raise errors.NoSuchRevision(self, revision_id)
929
def get_revision(self, revision_id):
930
"""Return the Revision object for a named revision"""
931
return self.get_revision_reconcile(revision_id)
934
def get_revision_graph(self, revision_id=None):
935
"""Return a dictionary containing the revision graph.
937
:param revision_id: The revision_id to get a graph from. If None, then
938
the entire revision graph is returned. This is a deprecated mode of
939
operation and will be removed in the future.
940
:return: a dictionary of revision_id->revision_parents_list.
942
# special case NULL_REVISION
943
if revision_id == _mod_revision.NULL_REVISION:
945
a_weave = self._get_revision_vf()
946
entire_graph = a_weave.get_graph()
947
if revision_id is None:
948
return a_weave.get_graph()
949
elif revision_id not in a_weave:
950
raise errors.NoSuchRevision(self, revision_id)
952
# add what can be reached from revision_id
954
pending = set([revision_id])
955
while len(pending) > 0:
957
result[node] = a_weave.get_parents(node)
958
for revision_id in result[node]:
959
if revision_id not in result:
960
pending.add(revision_id)
964
def get_revision_graph_with_ghosts(self, revision_ids=None):
965
"""Return a graph of the revisions with ghosts marked as applicable.
967
:param revision_ids: an iterable of revisions to graph or None for all.
968
:return: a Graph object with the graph reachable from revision_ids.
970
result = graph.Graph()
971
vf = self._get_revision_vf()
972
versions = set(vf.versions())
974
pending = set(self.all_revision_ids())
977
pending = set(revision_ids)
978
# special case NULL_REVISION
979
if _mod_revision.NULL_REVISION in pending:
980
pending.remove(_mod_revision.NULL_REVISION)
981
required = set(pending)
984
revision_id = pending.pop()
985
if not revision_id in versions:
986
if revision_id in required:
987
raise errors.NoSuchRevision(self, revision_id)
989
result.add_ghost(revision_id)
990
# mark it as done so we don't try for it again.
991
done.add(revision_id)
993
parent_ids = vf.get_parents_with_ghosts(revision_id)
994
for parent_id in parent_ids:
995
# is this queued or done ?
996
if (parent_id not in pending and
997
parent_id not in done):
999
pending.add(parent_id)
1000
result.add_node(revision_id, parent_ids)
1001
done.add(revision_id)
1004
def _get_revision_vf(self):
1005
""":return: a versioned file containing the revisions."""
1006
vf = self._revision_store.get_revision_file(self.get_transaction())
1010
def reconcile(self, other=None, thorough=False):
1011
"""Reconcile this repository."""
1012
from bzrlib.reconcile import KnitReconciler
1013
reconciler = KnitReconciler(self, thorough=thorough)
1014
reconciler.reconcile()
1017
def revision_parents(self, revision_id):
1018
return self._get_revision_vf().get_parents(revision_id)
1021
872
class RepositoryFormatRegistry(registry.Registry):
1022
873
"""Registry of RepositoryFormats.
1224
1077
control_files.unlock()
1227
class RepositoryFormatKnit(MetaDirRepositoryFormat):
1228
"""Bzr repository knit format (generalized).
1230
This repository format has:
1231
- knits for file texts and inventory
1232
- hash subdirectory based stores.
1233
- knits for revisions and signatures
1234
- TextStores for revisions and signatures.
1235
- a format marker of its own
1236
- an optional 'shared-storage' flag
1237
- an optional 'no-working-trees' flag
1241
def _get_control_store(self, repo_transport, control_files):
1242
"""Return the control store for this repository."""
1243
return VersionedFileStore(
1246
file_mode=control_files._file_mode,
1247
versionedfile_class=knit.KnitVersionedFile,
1248
versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1251
def _get_revision_store(self, repo_transport, control_files):
1252
"""See RepositoryFormat._get_revision_store()."""
1253
from bzrlib.store.revision.knit import KnitRevisionStore
1254
versioned_file_store = VersionedFileStore(
1256
file_mode=control_files._file_mode,
1259
versionedfile_class=knit.KnitVersionedFile,
1260
versionedfile_kwargs={'delta':False,
1261
'factory':knit.KnitPlainFactory(),
1265
return KnitRevisionStore(versioned_file_store)
1267
def _get_text_store(self, transport, control_files):
1268
"""See RepositoryFormat._get_text_store()."""
1269
return self._get_versioned_file_store('knits',
1272
versionedfile_class=knit.KnitVersionedFile,
1273
versionedfile_kwargs={
1274
'create_parent_dir':True,
1275
'delay_create':True,
1276
'dir_mode':control_files._dir_mode,
1280
def initialize(self, a_bzrdir, shared=False):
1281
"""Create a knit format 1 repository.
1283
:param a_bzrdir: bzrdir to contain the new repository; must already
1285
:param shared: If true the repository will be initialized as a shared
1288
mutter('creating repository in %s.', a_bzrdir.transport.base)
1289
dirs = ['revision-store', 'knits']
1291
utf8_files = [('format', self.get_format_string())]
1293
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1294
repo_transport = a_bzrdir.get_repository_transport(None)
1295
control_files = lockable_files.LockableFiles(repo_transport,
1296
'lock', lockdir.LockDir)
1297
control_store = self._get_control_store(repo_transport, control_files)
1298
transaction = transactions.WriteTransaction()
1299
# trigger a write of the inventory store.
1300
control_store.get_weave_or_empty('inventory', transaction)
1301
_revision_store = self._get_revision_store(repo_transport, control_files)
1302
# the revision id here is irrelevant: it will not be stored, and cannot
1304
_revision_store.has_revision_id('A', transaction)
1305
_revision_store.get_signature_file(transaction)
1306
return self.open(a_bzrdir=a_bzrdir, _found=True)
1308
def open(self, a_bzrdir, _found=False, _override_transport=None):
1309
"""See RepositoryFormat.open().
1311
:param _override_transport: INTERNAL USE ONLY. Allows opening the
1312
repository at a slightly different url
1313
than normal. I.e. during 'upgrade'.
1316
format = RepositoryFormat.find_format(a_bzrdir)
1317
assert format.__class__ == self.__class__
1318
if _override_transport is not None:
1319
repo_transport = _override_transport
1321
repo_transport = a_bzrdir.get_repository_transport(None)
1322
control_files = lockable_files.LockableFiles(repo_transport,
1323
'lock', lockdir.LockDir)
1324
text_store = self._get_text_store(repo_transport, control_files)
1325
control_store = self._get_control_store(repo_transport, control_files)
1326
_revision_store = self._get_revision_store(repo_transport, control_files)
1327
return KnitRepository(_format=self,
1329
control_files=control_files,
1330
_revision_store=_revision_store,
1331
control_store=control_store,
1332
text_store=text_store)
1335
class RepositoryFormatKnit1(RepositoryFormatKnit):
1336
"""Bzr repository knit format 1.
1338
This repository format has:
1339
- knits for file texts and inventory
1340
- hash subdirectory based stores.
1341
- knits for revisions and signatures
1342
- TextStores for revisions and signatures.
1343
- a format marker of its own
1344
- an optional 'shared-storage' flag
1345
- an optional 'no-working-trees' flag
1348
This format was introduced in bzr 0.8.
1350
def get_format_string(self):
1351
"""See RepositoryFormat.get_format_string()."""
1352
return "Bazaar-NG Knit Repository Format 1"
1354
def get_format_description(self):
1355
"""See RepositoryFormat.get_format_description()."""
1356
return "Knit repository format 1"
1358
def check_conversion_target(self, target_format):
1362
1080
# formats which have no format string are not discoverable
1363
1081
# and not independently creatable, so are not registered. They're
1364
1082
# all in bzrlib.repofmt.weaverepo now.
1713
1447
#result.append((InterRepository,
1714
1448
# RepositoryFormat6(),
1715
1449
# RepositoryFormatKnit1()))
1716
for optimiser in InterRepository._optimisers:
1717
if optimiser._matching_repo_format is not None:
1718
result.append((optimiser,
1719
optimiser._matching_repo_format,
1720
optimiser._matching_repo_format
1450
for optimiser_class in InterRepository._optimisers:
1451
format_to_test = optimiser_class._get_matching_repo_format()
1452
if format_to_test is not None:
1453
result.append((optimiser_class,
1454
format_to_test, format_to_test))
1722
1455
# if there are specific combinations we want to use, we can add them
1724
1457
result.append((InterModel1and2,
1725
1458
weaverepo.RepositoryFormat5(),
1726
1459
knitrepo.RepositoryFormatKnit2()))
1727
result.append((InterKnit1and2, RepositoryFormatKnit1(),
1460
result.append((InterKnit1and2,
1461
knitrepo.RepositoryFormatKnit1(),
1728
1462
knitrepo.RepositoryFormatKnit2()))