22
22
from unittest import TestSuite
24
import bzrlib.bzrdir as bzrdir
24
from bzrlib import bzrdir, check, delta, gpg, errors, xml5, ui, transactions, osutils
25
25
from bzrlib.decorators import needs_read_lock, needs_write_lock
26
import bzrlib.errors as errors
27
26
from bzrlib.errors import InvalidRevisionId
28
import bzrlib.gpg as gpg
29
27
from bzrlib.graph import Graph
30
28
from bzrlib.inter import InterObject
31
29
from bzrlib.inventory import Inventory
37
35
from bzrlib.revision import NULL_REVISION, Revision
38
36
from bzrlib.store.versioned import VersionedFileStore, WeaveStore
39
37
from bzrlib.store.text import TextStore
40
from bzrlib.symbol_versioning import *
38
from bzrlib.symbol_versioning import (deprecated_method,
41
41
from bzrlib.trace import mutter, note
42
42
from bzrlib.tree import RevisionTree, EmptyTree
43
43
from bzrlib.tsort import topo_sort
44
44
from bzrlib.testament import Testament
45
45
from bzrlib.tree import EmptyTree
46
from bzrlib.delta import compare_trees
48
46
from bzrlib.weave import WeaveFile
52
49
class Repository(object):
73
70
assert inv.revision_id is None or inv.revision_id == revid, \
74
71
"Mismatch between inventory revision" \
75
72
" id and insertion revid (%r, %r)" % (inv.revision_id, revid)
76
inv_text = bzrlib.xml5.serializer_v5.write_inventory_to_string(inv)
77
inv_sha1 = bzrlib.osutils.sha_string(inv_text)
73
inv_text = xml5.serializer_v5.write_inventory_to_string(inv)
74
inv_sha1 = osutils.sha_string(inv_text)
78
75
inv_vf = self.control_weaves.get_weave('inventory',
79
76
self.get_transaction())
80
self._inventory_add_lines(inv_vf, revid, parents, bzrlib.osutils.split_lines(inv_text))
77
self._inventory_add_lines(inv_vf, revid, parents, osutils.split_lines(inv_text))
83
80
def _inventory_add_lines(self, inv_vf, revid, parents, lines):
120
117
"""Return all the possible revisions that we could find."""
121
118
return self.get_inventory_weave().versions()
123
@deprecated_method(zero_nine)
124
120
def all_revision_ids(self):
125
121
"""Returns a list of all the revision ids in the repository.
227
223
For instance, if the repository is at URL/.bzr/repository,
228
224
Repository.open(URL) -> a Repository instance.
230
control = bzrlib.bzrdir.BzrDir.open(base)
226
control = bzrdir.BzrDir.open(base)
231
227
return control.open_repository()
233
229
def copy_content_into(self, destination, revision_id=None, basis=None):
278
274
result = a_bzrdir.create_repository()
279
275
# FIXME RBC 20060209 split out the repository type to avoid this check ?
280
276
elif isinstance(a_bzrdir._format,
281
(bzrlib.bzrdir.BzrDirFormat4,
282
bzrlib.bzrdir.BzrDirFormat5,
283
bzrlib.bzrdir.BzrDirFormat6)):
277
(bzrdir.BzrDirFormat4,
278
bzrdir.BzrDirFormat5,
279
bzrdir.BzrDirFormat6)):
284
280
result = a_bzrdir.open_repository()
286
282
result = self._format.initialize(a_bzrdir, shared=self.is_shared())
335
331
self._check_revision_parents(r, inv)
335
def get_deltas_for_revisions(self, revisions):
336
"""Produce a generator of revision deltas.
338
Note that the input is a sequence of REVISIONS, not revision_ids.
339
Trees will be held in memory until the generator exits.
340
Each delta is relative to the revision's lefthand predecessor.
342
required_trees = set()
343
for revision in revisions:
344
required_trees.add(revision.revision_id)
345
required_trees.update(revision.parent_ids[:1])
346
trees = dict((t.get_revision_id(), t) for
347
t in self.revision_trees(required_trees))
348
for revision in revisions:
349
if not revision.parent_ids:
350
old_tree = EmptyTree()
352
old_tree = trees[revision.parent_ids[0]]
353
yield delta.compare_trees(old_tree, trees[revision.revision_id])
338
356
def get_revision_delta(self, revision_id):
339
357
"""Return the delta for one revision.
341
359
The delta is relative to the left-hand predecessor of the
344
revision = self.get_revision(revision_id)
345
new_tree = self.revision_tree(revision_id)
346
if not revision.parent_ids:
347
old_tree = EmptyTree()
349
old_tree = self.revision_tree(revision.parent_ids[0])
350
return compare_trees(old_tree, new_tree)
362
r = self.get_revision(revision_id)
363
return list(self.get_deltas_for_revisions([r]))[0]
352
365
def _check_revision_parents(self, revision, inventory):
353
366
"""Private to Repository and Fetch.
431
444
:param revision_id: The expected revision id of the inventory.
432
445
:param xml: A serialised inventory.
434
return bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
447
return xml5.serializer_v5.read_inventory_from_string(xml)
437
450
def get_inventory_xml(self, revision_id):
441
454
iw = self.get_inventory_weave()
442
455
return iw.get_text(revision_id)
443
456
except IndexError:
444
raise bzrlib.errors.HistoryMissing(self, 'inventory', revision_id)
457
raise errors.HistoryMissing(self, 'inventory', revision_id)
447
460
def get_inventory_sha1(self, revision_id):
554
567
return RevisionTree(self, inv, revision_id)
570
def revision_trees(self, revision_ids):
571
"""Return Tree for a revision on this branch.
573
`revision_id` may not be None or 'null:'"""
574
assert None not in revision_ids
575
assert NULL_REVISION not in revision_ids
576
texts = self.get_inventory_weave().get_texts(revision_ids)
577
for text, revision_id in zip(texts, revision_ids):
578
inv = self.deserialise_inventory(revision_id, text)
579
yield RevisionTree(self, inv, revision_id)
557
582
def get_ancestry(self, revision_id):
558
583
"""Return a list of revision-ids integrated by a revision.
643
668
return self._check(revision_ids)
645
670
def _check(self, revision_ids):
646
result = bzrlib.check.Check(self)
671
result = check.Check(self)
920
945
reconciler.reconcile()
921
946
return reconciler
923
def revision_parents(self, revid):
924
return self._get_revision_vf().get_parents(rev_id)
948
def revision_parents(self, revision_id):
949
return self._get_revision_vf().get_parents(revision_id)
926
952
class RepositoryFormat(object):
927
953
"""A repository format.
963
989
except errors.NoSuchFile:
964
990
raise errors.NoRepositoryPresent(a_bzrdir)
966
raise errors.UnknownFormatError(format_string)
992
raise errors.UnknownFormatError(format=format_string)
968
994
def _get_control_store(self, repo_transport, control_files):
969
995
"""Return the control store for this repository."""
1091
1117
# Create an empty weave
1092
1118
sio = StringIO()
1093
bzrlib.weavefile.write_weave_v5(Weave(), sio)
1119
write_weave_v5(Weave(), sio)
1094
1120
empty_weave = sio.getvalue()
1096
1122
mutter('creating repository in %s.', a_bzrdir.transport.base)
1157
1183
def __init__(self):
1158
1184
super(RepositoryFormat4, self).__init__()
1159
self._matchingbzrdir = bzrlib.bzrdir.BzrDirFormat4()
1185
self._matchingbzrdir = bzrdir.BzrDirFormat4()
1161
1187
def get_format_description(self):
1162
1188
"""See RepositoryFormat.get_format_description()."""
1206
1232
def __init__(self):
1207
1233
super(RepositoryFormat5, self).__init__()
1208
self._matchingbzrdir = bzrlib.bzrdir.BzrDirFormat5()
1234
self._matchingbzrdir = bzrdir.BzrDirFormat5()
1210
1236
def get_format_description(self):
1211
1237
"""See RepositoryFormat.get_format_description()."""
1236
1262
def __init__(self):
1237
1263
super(RepositoryFormat6, self).__init__()
1238
self._matchingbzrdir = bzrlib.bzrdir.BzrDirFormat6()
1264
self._matchingbzrdir = bzrdir.BzrDirFormat6()
1240
1266
def get_format_description(self):
1241
1267
"""See RepositoryFormat.get_format_description()."""
1260
1286
def __init__(self):
1261
1287
super(MetaDirRepositoryFormat, self).__init__()
1262
self._matchingbzrdir = bzrlib.bzrdir.BzrDirMetaFormat1()
1288
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1264
1290
def _create_control_files(self, a_bzrdir):
1265
1291
"""Create the required files and the initial control_files object."""
1341
1367
# Create an empty weave
1342
1368
sio = StringIO()
1343
bzrlib.weavefile.write_weave_v5(Weave(), sio)
1369
write_weave_v5(Weave(), sio)
1344
1370
empty_weave = sio.getvalue()
1346
1372
mutter('creating repository in %s.', a_bzrdir.transport.base)
1451
1477
repo_transport = a_bzrdir.get_repository_transport(None)
1452
1478
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1453
1479
control_store = self._get_control_store(repo_transport, control_files)
1454
transaction = bzrlib.transactions.WriteTransaction()
1480
transaction = transactions.WriteTransaction()
1455
1481
# trigger a write of the inventory store.
1456
1482
control_store.get_weave_or_empty('inventory', transaction)
1457
1483
_revision_store = self._get_revision_store(repo_transport, control_files)
2089
2115
# TODO: Rather than invoking sha_strings here, _add_text_to_weave
2090
2116
# should return the SHA1 and size
2091
2117
self._add_text_to_weave(file_id, new_lines, file_parents.keys())
2092
return bzrlib.osutils.sha_strings(new_lines), \
2118
return osutils.sha_strings(new_lines), \
2093
2119
sum(map(len, new_lines))
2095
2121
def modified_link(self, file_id, file_parents, link_target):