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
17
from cStringIO import StringIO
19
from bzrlib.lazy_import import lazy_import
20
lazy_import(globals(), """
17
21
from binascii import hexlify
18
22
from copy import deepcopy
19
from cStringIO import StringIO
22
from unittest import TestSuite
24
27
from bzrlib import (
38
revision as _mod_revision,
47
from bzrlib.osutils import (
52
from bzrlib.revisiontree import RevisionTree
53
from bzrlib.store.versioned import VersionedFileStore
54
from bzrlib.store.text import TextStore
55
from bzrlib.testament import Testament
36
58
from bzrlib.decorators import needs_read_lock, needs_write_lock
37
from bzrlib.errors import InvalidRevisionId
38
from bzrlib.graph import Graph
39
59
from bzrlib.inter import InterObject
40
60
from bzrlib.inventory import Inventory, InventoryDirectory, ROOT_ID
41
from bzrlib.knit import KnitVersionedFile, KnitPlainFactory
42
from bzrlib.lockable_files import LockableFiles, TransportLock
43
from bzrlib.lockdir import LockDir
44
from bzrlib.osutils import (safe_unicode, rand_bytes, compact_date,
46
from bzrlib.revision import NULL_REVISION, Revision
47
from bzrlib.revisiontree import RevisionTree
48
from bzrlib.store.versioned import VersionedFileStore, WeaveStore
49
from bzrlib.store.text import TextStore
50
from bzrlib import symbol_versioning
51
from bzrlib.symbol_versioning import (deprecated_method,
61
from bzrlib.symbol_versioning import (
54
from bzrlib.testament import Testament
55
65
from bzrlib.trace import mutter, note, warning
56
from bzrlib.tsort import topo_sort
57
from bzrlib.weave import WeaveFile
60
68
# Old formats display a warning, but only once
317
325
or testing the revision graph.
319
327
if not revision_id or not isinstance(revision_id, basestring):
320
raise InvalidRevisionId(revision_id=revision_id, branch=self)
328
raise errors.InvalidRevisionId(revision_id=revision_id,
321
330
return self._revision_store.get_revisions([revision_id],
322
331
self.get_transaction())[0]
497
506
:return: a dictionary of revision_id->revision_parents_list.
499
508
# special case NULL_REVISION
500
if revision_id == NULL_REVISION:
509
if revision_id == _mod_revision.NULL_REVISION:
502
weave = self.get_inventory_weave()
503
all_revisions = self._eliminate_revisions_not_present(weave.versions())
504
entire_graph = dict([(node, weave.get_parents(node)) for
511
a_weave = self.get_inventory_weave()
512
all_revisions = self._eliminate_revisions_not_present(
514
entire_graph = dict([(node, a_weave.get_parents(node)) for
505
515
node in all_revisions])
506
516
if revision_id is None:
507
517
return entire_graph
526
536
:param revision_ids: an iterable of revisions to graph or None for all.
527
537
:return: a Graph object with the graph reachable from revision_ids.
539
result = graph.Graph()
530
540
if not revision_ids:
531
541
pending = set(self.all_revision_ids())
532
542
required = set([])
534
544
pending = set(revision_ids)
535
545
# special case NULL_REVISION
536
if NULL_REVISION in pending:
537
pending.remove(NULL_REVISION)
546
if _mod_revision.NULL_REVISION in pending:
547
pending.remove(_mod_revision.NULL_REVISION)
538
548
required = set(pending)
540
550
while len(pending):
595
605
# TODO: refactor this to use an existing revision object
596
606
# so we don't need to read it in twice.
597
if revision_id is None or revision_id == NULL_REVISION:
598
return RevisionTree(self, Inventory(), NULL_REVISION)
607
if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
608
return RevisionTree(self, Inventory(root_id=None),
609
_mod_revision.NULL_REVISION)
600
611
inv = self.get_revision_inventory(revision_id)
601
612
return RevisionTree(self, inv, revision_id)
607
618
`revision_id` may not be None or 'null:'"""
608
619
assert None not in revision_ids
609
assert NULL_REVISION not in revision_ids
620
assert _mod_revision.NULL_REVISION not in revision_ids
610
621
texts = self.get_inventory_weave().get_texts(revision_ids)
611
622
for text, revision_id in zip(texts, revision_ids):
612
623
inv = self.deserialise_inventory(revision_id, text)
933
944
:return: a dictionary of revision_id->revision_parents_list.
935
946
# special case NULL_REVISION
936
if revision_id == NULL_REVISION:
947
if revision_id == _mod_revision.NULL_REVISION:
938
weave = self._get_revision_vf()
939
entire_graph = weave.get_graph()
949
a_weave = self._get_revision_vf()
950
entire_graph = a_weave.get_graph()
940
951
if revision_id is None:
941
return weave.get_graph()
942
elif revision_id not in weave:
952
return a_weave.get_graph()
953
elif revision_id not in a_weave:
943
954
raise errors.NoSuchRevision(self, revision_id)
945
956
# add what can be reached from revision_id
970
981
pending = set(revision_ids)
971
982
# special case NULL_REVISION
972
if NULL_REVISION in pending:
973
pending.remove(NULL_REVISION)
983
if _mod_revision.NULL_REVISION in pending:
984
pending.remove(_mod_revision.NULL_REVISION)
974
985
required = set(pending)
976
987
while len(pending):
1222
1233
TODO: when creating split out bzr branch formats, move this to a common
1223
1234
base for Format5, Format6. or something like that.
1225
from bzrlib.weavefile import write_weave_v5
1226
from bzrlib.weave import Weave
1229
1237
raise errors.IncompatibleFormat(self, a_bzrdir._format)
1245
1253
# FIXME: RBC 20060125 don't peek under the covers
1246
1254
# NB: no need to escape relative paths that are url safe.
1247
control_files = LockableFiles(a_bzrdir.transport, 'branch-lock',
1255
control_files = lockable_files.LockableFiles(a_bzrdir.transport,
1256
'branch-lock', lockable_files.TransportLock)
1249
1257
control_files.create_lock()
1250
1258
control_files.lock_write()
1251
1259
control_files._transport.mkdir_multi(dirs,
1415
1423
# FIXME: RBC 20060125 don't peek under the covers
1416
1424
# NB: no need to escape relative paths that are url safe.
1417
1425
repository_transport = a_bzrdir.get_repository_transport(self)
1418
control_files = LockableFiles(repository_transport, 'lock', LockDir)
1426
control_files = lockable_files.LockableFiles(repository_transport,
1427
'lock', lockdir.LockDir)
1419
1428
control_files.create_lock()
1420
1429
return control_files
1487
1496
:param shared: If true the repository will be initialized as a shared
1490
from bzrlib.weavefile import write_weave_v5
1491
from bzrlib.weave import Weave
1493
1499
# Create an empty weave
1494
1500
sio = StringIO()
1495
write_weave_v5(Weave(), sio)
1501
weavefile.write_weave_v5(weave.Weave(), sio)
1496
1502
empty_weave = sio.getvalue()
1498
1504
mutter('creating repository in %s.', a_bzrdir.transport.base)
1518
1524
repo_transport = _override_transport
1520
1526
repo_transport = a_bzrdir.get_repository_transport(None)
1521
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1527
control_files = lockable_files.LockableFiles(repo_transport,
1528
'lock', lockdir.LockDir)
1522
1529
text_store = self._get_text_store(repo_transport, control_files)
1523
1530
control_store = self._get_control_store(repo_transport, control_files)
1524
1531
_revision_store = self._get_revision_store(repo_transport, control_files)
1550
1557
repo_transport,
1551
1558
prefixed=False,
1552
1559
file_mode=control_files._file_mode,
1553
versionedfile_class=KnitVersionedFile,
1554
versionedfile_kwargs={'factory':KnitPlainFactory()},
1560
versionedfile_class=knit.KnitVersionedFile,
1561
versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1557
1564
def _get_revision_store(self, repo_transport, control_files):
1562
1569
file_mode=control_files._file_mode,
1563
1570
prefixed=False,
1565
versionedfile_class=KnitVersionedFile,
1566
versionedfile_kwargs={'delta':False, 'factory':KnitPlainFactory(),},
1572
versionedfile_class=knit.KnitVersionedFile,
1573
versionedfile_kwargs={'delta':False,
1574
'factory':knit.KnitPlainFactory(),
1569
1578
return KnitRevisionStore(versioned_file_store)
1571
1580
def _get_text_store(self, transport, control_files):
1572
1581
"""See RepositoryFormat._get_text_store()."""
1573
1582
return self._get_versioned_file_store('knits',
1576
versionedfile_class=KnitVersionedFile,
1577
versionedfile_kwargs={
1578
'create_parent_dir':True,
1579
'delay_create':True,
1580
'dir_mode':control_files._dir_mode,
1585
versionedfile_class=knit.KnitVersionedFile,
1586
versionedfile_kwargs={
1587
'create_parent_dir':True,
1588
'delay_create':True,
1589
'dir_mode':control_files._dir_mode,
1584
1593
def initialize(self, a_bzrdir, shared=False):
1585
1594
"""Create a knit format 1 repository.
1597
1606
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1598
1607
repo_transport = a_bzrdir.get_repository_transport(None)
1599
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1608
control_files = lockable_files.LockableFiles(repo_transport,
1609
'lock', lockdir.LockDir)
1600
1610
control_store = self._get_control_store(repo_transport, control_files)
1601
1611
transaction = transactions.WriteTransaction()
1602
1612
# trigger a write of the inventory store.
1620
1630
repo_transport = _override_transport
1622
1632
repo_transport = a_bzrdir.get_repository_transport(None)
1623
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1633
control_files = lockable_files.LockableFiles(repo_transport,
1634
'lock', lockdir.LockDir)
1624
1635
text_store = self._get_text_store(repo_transport, control_files)
1625
1636
control_store = self._get_control_store(repo_transport, control_files)
1626
1637
_revision_store = self._get_revision_store(repo_transport, control_files)
1705
1716
repo_transport = _override_transport
1707
1718
repo_transport = a_bzrdir.get_repository_transport(None)
1708
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1719
control_files = lockable_files.LockableFiles(repo_transport, 'lock',
1709
1721
text_store = self._get_text_store(repo_transport, control_files)
1710
1722
control_store = self._get_control_store(repo_transport, control_files)
1711
1723
_revision_store = self._get_revision_store(repo_transport, control_files)
1826
1838
if basis is not None:
1827
1839
self.target.fetch(basis, revision_id=revision_id)
1828
1840
# but don't bother fetching if we have the needed data now.
1829
if (revision_id not in (None, NULL_REVISION) and
1841
if (revision_id not in (None, _mod_revision.NULL_REVISION) and
1830
1842
self.target.has_revision(revision_id)):
1832
1844
self.target.fetch(self.source, revision_id=revision_id)
2070
2082
if basis is not None:
2071
2083
self.target.fetch(basis, revision_id=revision_id)
2072
2084
# but don't bother fetching if we have the needed data now.
2073
if (revision_id not in (None, NULL_REVISION) and
2085
if (revision_id not in (None, _mod_revision.NULL_REVISION) and
2074
2086
self.target.has_revision(revision_id)):
2076
2088
self.target.fetch(self.source, revision_id=revision_id)
2305
2317
:return: The revision id of the recorded revision.
2307
rev = Revision(timestamp=self._timestamp,
2319
rev = _mod_revision.Revision(
2320
timestamp=self._timestamp,
2308
2321
timezone=self._timezone,
2309
2322
committer=self._committer,
2310
2323
message=message,