/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Andrew Bennetts
  • Date: 2006-10-20 04:02:48 UTC
  • mfrom: (2091 +trunk)
  • mto: (2018.5.1 split-smart)
  • mto: This revision was merged to the branch mainline in revision 2435.
  • Revision ID: andrew.bennetts@canonical.com-20061020040248-80ca63c7e0a13298
Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
 
17
from cStringIO import StringIO
 
18
 
 
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
20
23
import re
21
24
import time
22
 
from unittest import TestSuite
 
25
import unittest
23
26
 
24
27
from bzrlib import (
25
 
    bzrdir, 
26
 
    check, 
27
 
    delta, 
28
 
    gpg, 
29
 
    errors, 
 
28
    bzrdir,
 
29
    check,
 
30
    delta,
 
31
    errors,
 
32
    gpg,
 
33
    graph,
 
34
    knit,
 
35
    lockable_files,
 
36
    lockdir,
30
37
    osutils,
 
38
    revision as _mod_revision,
 
39
    symbol_versioning,
31
40
    transactions,
32
 
    ui, 
33
 
    xml5, 
 
41
    ui,
 
42
    weave,
 
43
    weavefile,
 
44
    xml5,
34
45
    xml6,
35
46
    )
 
47
from bzrlib.osutils import (
 
48
    rand_bytes,
 
49
    compact_date, 
 
50
    local_time_offset,
 
51
    )
 
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
 
56
""")
 
57
 
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, 
45
 
                            local_time_offset)
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,
52
 
        zero_nine, 
 
61
from bzrlib.symbol_versioning import (
 
62
        deprecated_method,
 
63
        zero_nine,
53
64
        )
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
58
66
 
59
67
 
60
68
# Old formats display a warning, but only once
317
325
        or testing the revision graph.
318
326
        """
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,
 
329
                                           branch=self)
321
330
        return self._revision_store.get_revisions([revision_id],
322
331
                                                  self.get_transaction())[0]
323
332
    @needs_read_lock
426
435
        # revisions. We don't need to see all lines in the inventory because
427
436
        # only those added in an inventory in rev X can contain a revision=X
428
437
        # line.
429
 
        for line in w.iter_lines_added_or_present_in_versions(selected_revision_ids):
430
 
            start = line.find('file_id="')+9
431
 
            if start < 9: continue
432
 
            end = line.find('"', start)
433
 
            assert end>= 0
434
 
            file_id = _unescape_xml(line[start:end])
 
438
        pb = ui.ui_factory.nested_progress_bar()
 
439
        try:
 
440
            for line in w.iter_lines_added_or_present_in_versions(
 
441
                selected_revision_ids, pb=pb):
 
442
                start = line.find('file_id="')+9
 
443
                if start < 9: continue
 
444
                end = line.find('"', start)
 
445
                assert end>= 0
 
446
                file_id = _unescape_xml(line[start:end])
435
447
 
436
 
            start = line.find('revision="')+10
437
 
            if start < 10: continue
438
 
            end = line.find('"', start)
439
 
            assert end>= 0
440
 
            revision_id = _unescape_xml(line[start:end])
441
 
            if revision_id in selected_revision_ids:
442
 
                result.setdefault(file_id, set()).add(revision_id)
 
448
                start = line.find('revision="')+10
 
449
                if start < 10: continue
 
450
                end = line.find('"', start)
 
451
                assert end>= 0
 
452
                revision_id = _unescape_xml(line[start:end])
 
453
                if revision_id in selected_revision_ids:
 
454
                    result.setdefault(file_id, set()).add(revision_id)
 
455
        finally:
 
456
            pb.finished()
443
457
        return result
444
458
 
445
459
    @needs_read_lock
492
506
        :return: a dictionary of revision_id->revision_parents_list.
493
507
        """
494
508
        # special case NULL_REVISION
495
 
        if revision_id == NULL_REVISION:
 
509
        if revision_id == _mod_revision.NULL_REVISION:
496
510
            return {}
497
 
        weave = self.get_inventory_weave()
498
 
        all_revisions = self._eliminate_revisions_not_present(weave.versions())
499
 
        entire_graph = dict([(node, weave.get_parents(node)) for 
 
511
        a_weave = self.get_inventory_weave()
 
512
        all_revisions = self._eliminate_revisions_not_present(
 
513
                                a_weave.versions())
 
514
        entire_graph = dict([(node, a_weave.get_parents(node)) for 
500
515
                             node in all_revisions])
501
516
        if revision_id is None:
502
517
            return entire_graph
521
536
        :param revision_ids: an iterable of revisions to graph or None for all.
522
537
        :return: a Graph object with the graph reachable from revision_ids.
523
538
        """
524
 
        result = Graph()
 
539
        result = graph.Graph()
525
540
        if not revision_ids:
526
541
            pending = set(self.all_revision_ids())
527
542
            required = set([])
528
543
        else:
529
544
            pending = set(revision_ids)
530
545
            # special case NULL_REVISION
531
 
            if NULL_REVISION in pending:
532
 
                pending.remove(NULL_REVISION)
 
546
            if _mod_revision.NULL_REVISION in pending:
 
547
                pending.remove(_mod_revision.NULL_REVISION)
533
548
            required = set(pending)
534
549
        done = set([])
535
550
        while len(pending):
589
604
        """
590
605
        # TODO: refactor this to use an existing revision object
591
606
        # so we don't need to read it in twice.
592
 
        if revision_id is None or revision_id == NULL_REVISION:
593
 
            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)
594
610
        else:
595
611
            inv = self.get_revision_inventory(revision_id)
596
612
            return RevisionTree(self, inv, revision_id)
601
617
 
602
618
        `revision_id` may not be None or 'null:'"""
603
619
        assert None not in revision_ids
604
 
        assert NULL_REVISION not in revision_ids
 
620
        assert _mod_revision.NULL_REVISION not in revision_ids
605
621
        texts = self.get_inventory_weave().get_texts(revision_ids)
606
622
        for text, revision_id in zip(texts, revision_ids):
607
623
            inv = self.deserialise_inventory(revision_id, text)
709
725
        warning("Format %s for %s is deprecated - please use 'bzr upgrade' to get better performance"
710
726
                % (self._format, self.bzrdir.transport.base))
711
727
 
 
728
    def supports_rich_root(self):
 
729
        return self._format.rich_root_data
 
730
 
712
731
 
713
732
class AllInOneRepository(Repository):
714
733
    """Legacy support - the repository behaviour for all-in-one branches."""
777
796
            parent_trees[p_id] = repository.revision_tree(None)
778
797
 
779
798
    inv = revision_tree.inventory
780
 
    
 
799
    entries = inv.iter_entries()
781
800
    # backwards compatability hack: skip the root id.
782
 
    entries = inv.iter_entries()
783
 
    entries.next()
 
801
    if not repository.supports_rich_root():
 
802
        path, root = entries.next()
 
803
        if root.revision != rev.revision_id:
 
804
            raise errors.IncompatibleRevision(repr(repository))
784
805
    # Add the texts that are not already present
785
806
    for path, ie in entries:
786
807
        w = repository.weave_store.get_weave_or_empty(ie.file_id,
923
944
        :return: a dictionary of revision_id->revision_parents_list.
924
945
        """
925
946
        # special case NULL_REVISION
926
 
        if revision_id == NULL_REVISION:
 
947
        if revision_id == _mod_revision.NULL_REVISION:
927
948
            return {}
928
 
        weave = self._get_revision_vf()
929
 
        entire_graph = weave.get_graph()
 
949
        a_weave = self._get_revision_vf()
 
950
        entire_graph = a_weave.get_graph()
930
951
        if revision_id is None:
931
 
            return weave.get_graph()
932
 
        elif revision_id not in weave:
 
952
            return a_weave.get_graph()
 
953
        elif revision_id not in a_weave:
933
954
            raise errors.NoSuchRevision(self, revision_id)
934
955
        else:
935
956
            # add what can be reached from revision_id
937
958
            pending = set([revision_id])
938
959
            while len(pending) > 0:
939
960
                node = pending.pop()
940
 
                result[node] = weave.get_parents(node)
 
961
                result[node] = a_weave.get_parents(node)
941
962
                for revision_id in result[node]:
942
963
                    if revision_id not in result:
943
964
                        pending.add(revision_id)
950
971
        :param revision_ids: an iterable of revisions to graph or None for all.
951
972
        :return: a Graph object with the graph reachable from revision_ids.
952
973
        """
953
 
        result = Graph()
 
974
        result = graph.Graph()
954
975
        vf = self._get_revision_vf()
955
976
        versions = set(vf.versions())
956
977
        if not revision_ids:
959
980
        else:
960
981
            pending = set(revision_ids)
961
982
            # special case NULL_REVISION
962
 
            if NULL_REVISION in pending:
963
 
                pending.remove(NULL_REVISION)
 
983
            if _mod_revision.NULL_REVISION in pending:
 
984
                pending.remove(_mod_revision.NULL_REVISION)
964
985
            required = set(pending)
965
986
        done = set([])
966
987
        while len(pending):
1145
1166
                                  transport,
1146
1167
                                  control_files,
1147
1168
                                  prefixed=True,
1148
 
                                  versionedfile_class=WeaveFile,
 
1169
                                  versionedfile_class=weave.WeaveFile,
1149
1170
                                  versionedfile_kwargs={},
1150
1171
                                  escaped=False):
1151
1172
        weave_transport = control_files._transport.clone(name)
1214
1235
        TODO: when creating split out bzr branch formats, move this to a common
1215
1236
        base for Format5, Format6. or something like that.
1216
1237
        """
1217
 
        from bzrlib.weavefile import write_weave_v5
1218
 
        from bzrlib.weave import Weave
1219
 
 
1220
1238
        if shared:
1221
1239
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
1222
1240
 
1226
1244
        
1227
1245
        # Create an empty weave
1228
1246
        sio = StringIO()
1229
 
        write_weave_v5(Weave(), sio)
 
1247
        weavefile.write_weave_v5(weave.Weave(), sio)
1230
1248
        empty_weave = sio.getvalue()
1231
1249
 
1232
1250
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1236
1254
        
1237
1255
        # FIXME: RBC 20060125 don't peek under the covers
1238
1256
        # NB: no need to escape relative paths that are url safe.
1239
 
        control_files = LockableFiles(a_bzrdir.transport, 'branch-lock',
1240
 
                                      TransportLock)
 
1257
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
 
1258
                                'branch-lock', lockable_files.TransportLock)
1241
1259
        control_files.create_lock()
1242
1260
        control_files.lock_write()
1243
1261
        control_files._transport.mkdir_multi(dirs,
1407
1425
        # FIXME: RBC 20060125 don't peek under the covers
1408
1426
        # NB: no need to escape relative paths that are url safe.
1409
1427
        repository_transport = a_bzrdir.get_repository_transport(self)
1410
 
        control_files = LockableFiles(repository_transport, 'lock', LockDir)
 
1428
        control_files = lockable_files.LockableFiles(repository_transport,
 
1429
                                'lock', lockdir.LockDir)
1411
1430
        control_files.create_lock()
1412
1431
        return control_files
1413
1432
 
1479
1498
        :param shared: If true the repository will be initialized as a shared
1480
1499
                       repository.
1481
1500
        """
1482
 
        from bzrlib.weavefile import write_weave_v5
1483
 
        from bzrlib.weave import Weave
1484
 
 
1485
1501
        # Create an empty weave
1486
1502
        sio = StringIO()
1487
 
        write_weave_v5(Weave(), sio)
 
1503
        weavefile.write_weave_v5(weave.Weave(), sio)
1488
1504
        empty_weave = sio.getvalue()
1489
1505
 
1490
1506
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1510
1526
            repo_transport = _override_transport
1511
1527
        else:
1512
1528
            repo_transport = a_bzrdir.get_repository_transport(None)
1513
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1529
        control_files = lockable_files.LockableFiles(repo_transport,
 
1530
                                'lock', lockdir.LockDir)
1514
1531
        text_store = self._get_text_store(repo_transport, control_files)
1515
1532
        control_store = self._get_control_store(repo_transport, control_files)
1516
1533
        _revision_store = self._get_revision_store(repo_transport, control_files)
1542
1559
            repo_transport,
1543
1560
            prefixed=False,
1544
1561
            file_mode=control_files._file_mode,
1545
 
            versionedfile_class=KnitVersionedFile,
1546
 
            versionedfile_kwargs={'factory':KnitPlainFactory()},
 
1562
            versionedfile_class=knit.KnitVersionedFile,
 
1563
            versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1547
1564
            )
1548
1565
 
1549
1566
    def _get_revision_store(self, repo_transport, control_files):
1554
1571
            file_mode=control_files._file_mode,
1555
1572
            prefixed=False,
1556
1573
            precious=True,
1557
 
            versionedfile_class=KnitVersionedFile,
1558
 
            versionedfile_kwargs={'delta':False, 'factory':KnitPlainFactory(),},
 
1574
            versionedfile_class=knit.KnitVersionedFile,
 
1575
            versionedfile_kwargs={'delta':False,
 
1576
                                  'factory':knit.KnitPlainFactory(),
 
1577
                                 },
1559
1578
            escaped=True,
1560
1579
            )
1561
1580
        return KnitRevisionStore(versioned_file_store)
1563
1582
    def _get_text_store(self, transport, control_files):
1564
1583
        """See RepositoryFormat._get_text_store()."""
1565
1584
        return self._get_versioned_file_store('knits',
1566
 
                                              transport,
1567
 
                                              control_files,
1568
 
                                              versionedfile_class=KnitVersionedFile,
1569
 
                                              versionedfile_kwargs={
1570
 
                                                  'create_parent_dir':True,
1571
 
                                                  'delay_create':True,
1572
 
                                                  'dir_mode':control_files._dir_mode,
1573
 
                                              },
1574
 
                                              escaped=True)
 
1585
                                  transport,
 
1586
                                  control_files,
 
1587
                                  versionedfile_class=knit.KnitVersionedFile,
 
1588
                                  versionedfile_kwargs={
 
1589
                                      'create_parent_dir':True,
 
1590
                                      'delay_create':True,
 
1591
                                      'dir_mode':control_files._dir_mode,
 
1592
                                  },
 
1593
                                  escaped=True)
1575
1594
 
1576
1595
    def initialize(self, a_bzrdir, shared=False):
1577
1596
        """Create a knit format 1 repository.
1588
1607
        
1589
1608
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1590
1609
        repo_transport = a_bzrdir.get_repository_transport(None)
1591
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1610
        control_files = lockable_files.LockableFiles(repo_transport,
 
1611
                                'lock', lockdir.LockDir)
1592
1612
        control_store = self._get_control_store(repo_transport, control_files)
1593
1613
        transaction = transactions.WriteTransaction()
1594
1614
        # trigger a write of the inventory store.
1612
1632
            repo_transport = _override_transport
1613
1633
        else:
1614
1634
            repo_transport = a_bzrdir.get_repository_transport(None)
1615
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1635
        control_files = lockable_files.LockableFiles(repo_transport,
 
1636
                                'lock', lockdir.LockDir)
1616
1637
        text_store = self._get_text_store(repo_transport, control_files)
1617
1638
        control_store = self._get_control_store(repo_transport, control_files)
1618
1639
        _revision_store = self._get_revision_store(repo_transport, control_files)
1697
1718
            repo_transport = _override_transport
1698
1719
        else:
1699
1720
            repo_transport = a_bzrdir.get_repository_transport(None)
1700
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1721
        control_files = lockable_files.LockableFiles(repo_transport, 'lock',
 
1722
                                                     lockdir.LockDir)
1701
1723
        text_store = self._get_text_store(repo_transport, control_files)
1702
1724
        control_store = self._get_control_store(repo_transport, control_files)
1703
1725
        _revision_store = self._get_revision_store(repo_transport, control_files)
1818
1840
        if basis is not None:
1819
1841
            self.target.fetch(basis, revision_id=revision_id)
1820
1842
        # but don't bother fetching if we have the needed data now.
1821
 
        if (revision_id not in (None, NULL_REVISION) and 
 
1843
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
1822
1844
            self.target.has_revision(revision_id)):
1823
1845
            return
1824
1846
        self.target.fetch(self.source, revision_id=revision_id)
2062
2084
        if basis is not None:
2063
2085
            self.target.fetch(basis, revision_id=revision_id)
2064
2086
        # but don't bother fetching if we have the needed data now.
2065
 
        if (revision_id not in (None, NULL_REVISION) and 
 
2087
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
2066
2088
            self.target.has_revision(revision_id)):
2067
2089
            return
2068
2090
        self.target.fetch(self.source, revision_id=revision_id)
2117
2139
        self._formats = formats
2118
2140
    
2119
2141
    def adapt(self, test):
2120
 
        result = TestSuite()
 
2142
        result = unittest.TestSuite()
2121
2143
        for repository_format, bzrdir_format in self._formats:
2122
2144
            new_test = deepcopy(test)
2123
2145
            new_test.transport_server = self._transport_server
2147
2169
        self._formats = formats
2148
2170
    
2149
2171
    def adapt(self, test):
2150
 
        result = TestSuite()
 
2172
        result = unittest.TestSuite()
2151
2173
        for interrepo_class, repository_format, repository_format_to in self._formats:
2152
2174
            new_test = deepcopy(test)
2153
2175
            new_test.transport_server = self._transport_server
2296
2318
 
2297
2319
        :return: The revision id of the recorded revision.
2298
2320
        """
2299
 
        rev = Revision(timestamp=self._timestamp,
 
2321
        rev = _mod_revision.Revision(
 
2322
                       timestamp=self._timestamp,
2300
2323
                       timezone=self._timezone,
2301
2324
                       committer=self._committer,
2302
2325
                       message=message,
2308
2331
            self.new_inventory, self._config)
2309
2332
        return self._new_revision_id
2310
2333
 
 
2334
    def revision_tree(self):
 
2335
        """Return the tree that was just committed.
 
2336
 
 
2337
        After calling commit() this can be called to get a RevisionTree
 
2338
        representing the newly committed tree. This is preferred to
 
2339
        calling Repository.revision_tree() because that may require
 
2340
        deserializing the inventory, while we already have a copy in
 
2341
        memory.
 
2342
        """
 
2343
        return RevisionTree(self.repository, self.new_inventory,
 
2344
                            self._new_revision_id)
 
2345
 
2311
2346
    def finish_inventory(self):
2312
2347
        """Tell the builder that the inventory is finished."""
2313
2348
        if self.new_inventory.root is None:
2369
2404
 
2370
2405
        # In this revision format, root entries have no knit or weave
2371
2406
        if ie is self.new_inventory.root:
2372
 
            if len(parent_invs):
2373
 
                ie.revision = parent_invs[0].root.revision
2374
 
            else:
2375
 
                ie.revision = None
 
2407
            # When serializing out to disk and back in
 
2408
            # root.revision is always _new_revision_id
 
2409
            ie.revision = self._new_revision_id
2376
2410
            return
2377
2411
        previous_entries = ie.find_previous_heads(
2378
2412
            parent_invs,