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(), _mod_revision.NULL_REVISION)
600
610
inv = self.get_revision_inventory(revision_id)
601
611
return RevisionTree(self, inv, revision_id)
607
617
`revision_id` may not be None or 'null:'"""
608
618
assert None not in revision_ids
609
assert NULL_REVISION not in revision_ids
619
assert _mod_revision.NULL_REVISION not in revision_ids
610
620
texts = self.get_inventory_weave().get_texts(revision_ids)
611
621
for text, revision_id in zip(texts, revision_ids):
612
622
inv = self.deserialise_inventory(revision_id, text)
933
943
:return: a dictionary of revision_id->revision_parents_list.
935
945
# special case NULL_REVISION
936
if revision_id == NULL_REVISION:
946
if revision_id == _mod_revision.NULL_REVISION:
938
weave = self._get_revision_vf()
939
entire_graph = weave.get_graph()
948
a_weave = self._get_revision_vf()
949
entire_graph = a_weave.get_graph()
940
950
if revision_id is None:
941
return weave.get_graph()
942
elif revision_id not in weave:
951
return a_weave.get_graph()
952
elif revision_id not in a_weave:
943
953
raise errors.NoSuchRevision(self, revision_id)
945
955
# add what can be reached from revision_id
970
980
pending = set(revision_ids)
971
981
# special case NULL_REVISION
972
if NULL_REVISION in pending:
973
pending.remove(NULL_REVISION)
982
if _mod_revision.NULL_REVISION in pending:
983
pending.remove(_mod_revision.NULL_REVISION)
974
984
required = set(pending)
976
986
while len(pending):
1222
1232
TODO: when creating split out bzr branch formats, move this to a common
1223
1233
base for Format5, Format6. or something like that.
1225
from bzrlib.weavefile import write_weave_v5
1226
from bzrlib.weave import Weave
1229
1236
raise errors.IncompatibleFormat(self, a_bzrdir._format)
1245
1252
# FIXME: RBC 20060125 don't peek under the covers
1246
1253
# NB: no need to escape relative paths that are url safe.
1247
control_files = LockableFiles(a_bzrdir.transport, 'branch-lock',
1254
control_files = lockable_files.LockableFiles(a_bzrdir.transport,
1255
'branch-lock', lockable_files.TransportLock)
1249
1256
control_files.create_lock()
1250
1257
control_files.lock_write()
1251
1258
control_files._transport.mkdir_multi(dirs,
1415
1422
# FIXME: RBC 20060125 don't peek under the covers
1416
1423
# NB: no need to escape relative paths that are url safe.
1417
1424
repository_transport = a_bzrdir.get_repository_transport(self)
1418
control_files = LockableFiles(repository_transport, 'lock', LockDir)
1425
control_files = lockable_files.LockableFiles(repository_transport,
1426
'lock', lockdir.LockDir)
1419
1427
control_files.create_lock()
1420
1428
return control_files
1487
1495
: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
1498
# Create an empty weave
1494
1499
sio = StringIO()
1495
write_weave_v5(Weave(), sio)
1500
weavefile.write_weave_v5(weave.Weave(), sio)
1496
1501
empty_weave = sio.getvalue()
1498
1503
mutter('creating repository in %s.', a_bzrdir.transport.base)
1518
1523
repo_transport = _override_transport
1520
1525
repo_transport = a_bzrdir.get_repository_transport(None)
1521
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1526
control_files = lockable_files.LockableFiles(repo_transport,
1527
'lock', lockdir.LockDir)
1522
1528
text_store = self._get_text_store(repo_transport, control_files)
1523
1529
control_store = self._get_control_store(repo_transport, control_files)
1524
1530
_revision_store = self._get_revision_store(repo_transport, control_files)
1550
1556
repo_transport,
1551
1557
prefixed=False,
1552
1558
file_mode=control_files._file_mode,
1553
versionedfile_class=KnitVersionedFile,
1554
versionedfile_kwargs={'factory':KnitPlainFactory()},
1559
versionedfile_class=knit.KnitVersionedFile,
1560
versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1557
1563
def _get_revision_store(self, repo_transport, control_files):
1562
1568
file_mode=control_files._file_mode,
1563
1569
prefixed=False,
1565
versionedfile_class=KnitVersionedFile,
1566
versionedfile_kwargs={'delta':False, 'factory':KnitPlainFactory(),},
1571
versionedfile_class=knit.KnitVersionedFile,
1572
versionedfile_kwargs={'delta':False,
1573
'factory':knit.KnitPlainFactory(),
1569
1577
return KnitRevisionStore(versioned_file_store)
1571
1579
def _get_text_store(self, transport, control_files):
1572
1580
"""See RepositoryFormat._get_text_store()."""
1573
1581
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,
1584
versionedfile_class=knit.KnitVersionedFile,
1585
versionedfile_kwargs={
1586
'create_parent_dir':True,
1587
'delay_create':True,
1588
'dir_mode':control_files._dir_mode,
1584
1592
def initialize(self, a_bzrdir, shared=False):
1585
1593
"""Create a knit format 1 repository.
1597
1605
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1598
1606
repo_transport = a_bzrdir.get_repository_transport(None)
1599
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1607
control_files = lockable_files.LockableFiles(repo_transport,
1608
'lock', lockdir.LockDir)
1600
1609
control_store = self._get_control_store(repo_transport, control_files)
1601
1610
transaction = transactions.WriteTransaction()
1602
1611
# trigger a write of the inventory store.
1620
1629
repo_transport = _override_transport
1622
1631
repo_transport = a_bzrdir.get_repository_transport(None)
1623
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1632
control_files = lockable_files.LockableFiles(repo_transport,
1633
'lock', lockdir.LockDir)
1624
1634
text_store = self._get_text_store(repo_transport, control_files)
1625
1635
control_store = self._get_control_store(repo_transport, control_files)
1626
1636
_revision_store = self._get_revision_store(repo_transport, control_files)
1705
1715
repo_transport = _override_transport
1707
1717
repo_transport = a_bzrdir.get_repository_transport(None)
1708
control_files = LockableFiles(repo_transport, 'lock', LockDir)
1718
control_files = lockable_files.LockableFiles(repo_transport, 'lock',
1709
1720
text_store = self._get_text_store(repo_transport, control_files)
1710
1721
control_store = self._get_control_store(repo_transport, control_files)
1711
1722
_revision_store = self._get_revision_store(repo_transport, control_files)
1826
1837
if basis is not None:
1827
1838
self.target.fetch(basis, revision_id=revision_id)
1828
1839
# but don't bother fetching if we have the needed data now.
1829
if (revision_id not in (None, NULL_REVISION) and
1840
if (revision_id not in (None, _mod_revision.NULL_REVISION) and
1830
1841
self.target.has_revision(revision_id)):
1832
1843
self.target.fetch(self.source, revision_id=revision_id)
2070
2081
if basis is not None:
2071
2082
self.target.fetch(basis, revision_id=revision_id)
2072
2083
# but don't bother fetching if we have the needed data now.
2073
if (revision_id not in (None, NULL_REVISION) and
2084
if (revision_id not in (None, _mod_revision.NULL_REVISION) and
2074
2085
self.target.has_revision(revision_id)):
2076
2087
self.target.fetch(self.source, revision_id=revision_id)
2305
2316
:return: The revision id of the recorded revision.
2307
rev = Revision(timestamp=self._timestamp,
2318
rev = _mod_revision.Revision(
2319
timestamp=self._timestamp,
2308
2320
timezone=self._timezone,
2309
2321
committer=self._committer,
2310
2322
message=message,