~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: Brad Crittenden
  • Date: 2007-02-26 20:56:10 UTC
  • mfrom: (2300 +trunk)
  • mto: (2293.1.5 bzr.dev)
  • mto: This revision was merged to the branch mainline in revision 2311.
  • Revision ID: brad.crittenden@canonical.com-20070226205610-44oatbxrjjz3ajwy
merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
78
78
        )
79
79
 
80
80
    @needs_write_lock
81
 
    def add_inventory(self, revid, inv, parents):
82
 
        """Add the inventory inv to the repository as revid.
 
81
    def add_inventory(self, revision_id, inv, parents):
 
82
        """Add the inventory inv to the repository as revision_id.
83
83
        
84
 
        :param parents: The revision ids of the parents that revid
 
84
        :param parents: The revision ids of the parents that revision_id
85
85
                        is known to have and are in the repository already.
86
86
 
87
87
        returns the sha1 of the serialized inventory.
88
88
        """
89
 
        _mod_revision.check_not_reserved_id(revid)
90
 
        assert inv.revision_id is None or inv.revision_id == revid, \
 
89
        revision_id = osutils.safe_revision_id(revision_id)
 
90
        _mod_revision.check_not_reserved_id(revision_id)
 
91
        assert inv.revision_id is None or inv.revision_id == revision_id, \
91
92
            "Mismatch between inventory revision" \
92
 
            " id and insertion revid (%r, %r)" % (inv.revision_id, revid)
 
93
            " id and insertion revid (%r, %r)" % (inv.revision_id, revision_id)
93
94
        assert inv.root is not None
94
95
        inv_text = self.serialise_inventory(inv)
95
96
        inv_sha1 = osutils.sha_string(inv_text)
96
97
        inv_vf = self.control_weaves.get_weave('inventory',
97
98
                                               self.get_transaction())
98
 
        self._inventory_add_lines(inv_vf, revid, parents, osutils.split_lines(inv_text))
 
99
        self._inventory_add_lines(inv_vf, revision_id, parents,
 
100
                                  osutils.split_lines(inv_text))
99
101
        return inv_sha1
100
102
 
101
 
    def _inventory_add_lines(self, inv_vf, revid, parents, lines):
 
103
    def _inventory_add_lines(self, inv_vf, revision_id, parents, lines):
102
104
        final_parents = []
103
105
        for parent in parents:
104
106
            if parent in inv_vf:
105
107
                final_parents.append(parent)
106
108
 
107
 
        inv_vf.add_lines(revid, final_parents, lines)
 
109
        inv_vf.add_lines(revision_id, final_parents, lines)
108
110
 
109
111
    @needs_write_lock
110
 
    def add_revision(self, rev_id, rev, inv=None, config=None):
111
 
        """Add rev to the revision store as rev_id.
 
112
    def add_revision(self, revision_id, rev, inv=None, config=None):
 
113
        """Add rev to the revision store as revision_id.
112
114
 
113
 
        :param rev_id: the revision id to use.
 
115
        :param revision_id: the revision id to use.
114
116
        :param rev: The revision object.
115
117
        :param inv: The inventory for the revision. if None, it will be looked
116
118
                    up in the inventory storer
118
120
                       If supplied its signature_needed method will be used
119
121
                       to determine if a signature should be made.
120
122
        """
121
 
        _mod_revision.check_not_reserved_id(rev_id)
 
123
        revision_id = osutils.safe_revision_id(revision_id)
 
124
        # TODO: jam 20070210 Shouldn't we check rev.revision_id and
 
125
        #       rev.parent_ids?
 
126
        _mod_revision.check_not_reserved_id(revision_id)
122
127
        if config is not None and config.signature_needed():
123
128
            if inv is None:
124
 
                inv = self.get_inventory(rev_id)
 
129
                inv = self.get_inventory(revision_id)
125
130
            plaintext = Testament(rev, inv).as_short_text()
126
131
            self.store_revision_signature(
127
 
                gpg.GPGStrategy(config), plaintext, rev_id)
128
 
        if not rev_id in self.get_inventory_weave():
 
132
                gpg.GPGStrategy(config), plaintext, revision_id)
 
133
        if not revision_id in self.get_inventory_weave():
129
134
            if inv is None:
130
 
                raise errors.WeaveRevisionNotPresent(rev_id,
 
135
                raise errors.WeaveRevisionNotPresent(revision_id,
131
136
                                                     self.get_inventory_weave())
132
137
            else:
133
138
                # yes, this is not suitable for adding with ghosts.
134
 
                self.add_inventory(rev_id, inv, rev.parent_ids)
 
139
                self.add_inventory(revision_id, inv, rev.parent_ids)
135
140
        self._revision_store.add_revision(rev, self.get_transaction())
136
141
 
137
142
    @needs_read_lock
159
164
        if self._revision_store.text_store.listable():
160
165
            return self._revision_store.all_revision_ids(self.get_transaction())
161
166
        result = self._all_possible_ids()
 
167
        # TODO: jam 20070210 Ensure that _all_possible_ids returns non-unicode
 
168
        #       ids. (It should, since _revision_store's API should change to
 
169
        #       return utf8 revision_ids)
162
170
        return self._eliminate_revisions_not_present(result)
163
171
 
164
172
    def break_lock(self):
287
295
 
288
296
        revision_id: only return revision ids included by revision_id.
289
297
        """
 
298
        revision_id = osutils.safe_revision_id(revision_id)
290
299
        return InterRepository.get(other, self).missing_revision_ids(revision_id)
291
300
 
292
301
    @staticmethod
305
314
        This is a destructive operation! Do not use it on existing 
306
315
        repositories.
307
316
        """
 
317
        revision_id = osutils.safe_revision_id(revision_id)
308
318
        return InterRepository.get(self, destination).copy_content(revision_id, basis)
309
319
 
310
320
    def fetch(self, source, revision_id=None, pb=None):
312
322
 
313
323
        If revision_id is None all content is copied.
314
324
        """
 
325
        revision_id = osutils.safe_revision_id(revision_id)
315
326
        return InterRepository.get(source, self).fetch(revision_id=revision_id,
316
327
                                                       pb=pb)
317
328
 
329
340
        :param revprops: Optional dictionary of revision properties.
330
341
        :param revision_id: Optional revision id.
331
342
        """
 
343
        revision_id = osutils.safe_revision_id(revision_id)
332
344
        return _CommitBuilder(self, parents, config, timestamp, timezone,
333
345
                              committer, revprops, revision_id)
334
346
 
360
372
    @needs_read_lock
361
373
    def has_revision(self, revision_id):
362
374
        """True if this repository has a copy of the revision."""
 
375
        revision_id = osutils.safe_revision_id(revision_id)
363
376
        return self._revision_store.has_revision_id(revision_id,
364
377
                                                    self.get_transaction())
365
378
 
375
388
        if not revision_id or not isinstance(revision_id, basestring):
376
389
            raise errors.InvalidRevisionId(revision_id=revision_id,
377
390
                                           branch=self)
378
 
        return self._revision_store.get_revisions([revision_id],
379
 
                                                  self.get_transaction())[0]
 
391
        return self.get_revisions([revision_id])[0]
 
392
 
380
393
    @needs_read_lock
381
394
    def get_revisions(self, revision_ids):
382
 
        return self._revision_store.get_revisions(revision_ids,
 
395
        revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
 
396
        revs = self._revision_store.get_revisions(revision_ids,
383
397
                                                  self.get_transaction())
 
398
        for rev in revs:
 
399
            assert not isinstance(rev.revision_id, unicode)
 
400
            for parent_id in rev.parent_ids:
 
401
                assert not isinstance(parent_id, unicode)
 
402
        return revs
384
403
 
385
404
    @needs_read_lock
386
405
    def get_revision_xml(self, revision_id):
387
 
        rev = self.get_revision(revision_id) 
 
406
        # TODO: jam 20070210 This shouldn't be necessary since get_revision
 
407
        #       would have already do it.
 
408
        # TODO: jam 20070210 Just use _serializer.write_revision_to_string()
 
409
        revision_id = osutils.safe_revision_id(revision_id)
 
410
        rev = self.get_revision(revision_id)
388
411
        rev_tmp = StringIO()
389
412
        # the current serializer..
390
413
        self._revision_store._serializer.write_revision(rev, rev_tmp)
394
417
    @needs_read_lock
395
418
    def get_revision(self, revision_id):
396
419
        """Return the Revision object for a named revision"""
 
420
        # TODO: jam 20070210 get_revision_reconcile should do this for us
 
421
        revision_id = osutils.safe_revision_id(revision_id)
397
422
        r = self.get_revision_reconcile(revision_id)
398
423
        # weave corruption can lead to absent revision markers that should be
399
424
        # present.
455
480
 
456
481
    @needs_write_lock
457
482
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
 
483
        revision_id = osutils.safe_revision_id(revision_id)
458
484
        signature = gpg_strategy.sign(plaintext)
459
485
        self._revision_store.add_revision_signature_text(revision_id,
460
486
                                                         signature,
471
497
        assert self._serializer.support_altered_by_hack, \
472
498
            ("fileids_altered_by_revision_ids only supported for branches " 
473
499
             "which store inventory as unnested xml, not on %r" % self)
474
 
        selected_revision_ids = set(revision_ids)
 
500
        selected_revision_ids = set(osutils.safe_revision_id(r)
 
501
                                    for r in revision_ids)
475
502
        w = self.get_inventory_weave()
476
503
        result = {}
477
504
 
541
568
    @needs_read_lock
542
569
    def get_inventory(self, revision_id):
543
570
        """Get Inventory object by hash."""
 
571
        # TODO: jam 20070210 Technically we don't need to sanitize, since all
 
572
        #       called functions must sanitize.
 
573
        revision_id = osutils.safe_revision_id(revision_id)
544
574
        return self.deserialise_inventory(
545
575
            revision_id, self.get_inventory_xml(revision_id))
546
576
 
550
580
        :param revision_id: The expected revision id of the inventory.
551
581
        :param xml: A serialised inventory.
552
582
        """
 
583
        revision_id = osutils.safe_revision_id(revision_id)
553
584
        result = self._serializer.read_inventory_from_string(xml)
554
585
        result.root.revision = revision_id
555
586
        return result
560
591
    @needs_read_lock
561
592
    def get_inventory_xml(self, revision_id):
562
593
        """Get inventory XML as a file object."""
 
594
        revision_id = osutils.safe_revision_id(revision_id)
563
595
        try:
564
 
            assert isinstance(revision_id, basestring), type(revision_id)
 
596
            assert isinstance(revision_id, str), type(revision_id)
565
597
            iw = self.get_inventory_weave()
566
598
            return iw.get_text(revision_id)
567
599
        except IndexError:
571
603
    def get_inventory_sha1(self, revision_id):
572
604
        """Return the sha1 hash of the inventory entry
573
605
        """
 
606
        # TODO: jam 20070210 Shouldn't this be deprecated / removed?
 
607
        revision_id = osutils.safe_revision_id(revision_id)
574
608
        return self.get_revision(revision_id).inventory_sha1
575
609
 
576
610
    @needs_read_lock
585
619
        # special case NULL_REVISION
586
620
        if revision_id == _mod_revision.NULL_REVISION:
587
621
            return {}
 
622
        revision_id = osutils.safe_revision_id(revision_id)
588
623
        a_weave = self.get_inventory_weave()
589
624
        all_revisions = self._eliminate_revisions_not_present(
590
625
                                a_weave.versions())
618
653
            pending = set(self.all_revision_ids())
619
654
            required = set([])
620
655
        else:
621
 
            pending = set(revision_ids)
 
656
            pending = set(osutils.safe_revision_id(r) for r in revision_ids)
622
657
            # special case NULL_REVISION
623
658
            if _mod_revision.NULL_REVISION in pending:
624
659
                pending.remove(_mod_revision.NULL_REVISION)
657
692
        :param revision_id: The revision id to start with.  All its lefthand
658
693
            ancestors will be traversed.
659
694
        """
 
695
        revision_id = osutils.safe_revision_id(revision_id)
660
696
        if revision_id in (None, _mod_revision.NULL_REVISION):
661
697
            return
662
698
        next_id = revision_id
710
746
            return RevisionTree(self, Inventory(root_id=None), 
711
747
                                _mod_revision.NULL_REVISION)
712
748
        else:
 
749
            revision_id = osutils.safe_revision_id(revision_id)
713
750
            inv = self.get_revision_inventory(revision_id)
714
751
            return RevisionTree(self, inv, revision_id)
715
752
 
737
774
        """
738
775
        if revision_id is None:
739
776
            return [None]
 
777
        revision_id = osutils.safe_revision_id(revision_id)
740
778
        if not self.has_revision(revision_id):
741
779
            raise errors.NoSuchRevision(self, revision_id)
742
780
        w = self.get_inventory_weave()
751
789
        - it writes to stdout, it assumes that that is valid etc. Fix
752
790
        by creating a new more flexible convenience function.
753
791
        """
 
792
        revision_id = osutils.safe_revision_id(revision_id)
754
793
        tree = self.revision_tree(revision_id)
755
794
        # use inventory as it was in that revision
756
795
        file_id = tree.inventory.path2id(file)
764
803
    def get_transaction(self):
765
804
        return self.control_files.get_transaction()
766
805
 
767
 
    def revision_parents(self, revid):
768
 
        return self.get_inventory_weave().parent_names(revid)
 
806
    def revision_parents(self, revision_id):
 
807
        revision_id = osutils.safe_revision_id(revision_id)
 
808
        return self.get_inventory_weave().parent_names(revision_id)
769
809
 
770
810
    @needs_write_lock
771
811
    def set_make_working_trees(self, new_value):
785
825
 
786
826
    @needs_write_lock
787
827
    def sign_revision(self, revision_id, gpg_strategy):
 
828
        revision_id = osutils.safe_revision_id(revision_id)
788
829
        plaintext = Testament.from_revision(self, revision_id).as_short_text()
789
830
        self.store_revision_signature(gpg_strategy, plaintext, revision_id)
790
831
 
791
832
    @needs_read_lock
792
833
    def has_signature_for_revision_id(self, revision_id):
793
834
        """Query for a revision signature for revision_id in the repository."""
 
835
        revision_id = osutils.safe_revision_id(revision_id)
794
836
        return self._revision_store.has_signature(revision_id,
795
837
                                                  self.get_transaction())
796
838
 
797
839
    @needs_read_lock
798
840
    def get_signature_text(self, revision_id):
799
841
        """Return the text for a signature."""
 
842
        revision_id = osutils.safe_revision_id(revision_id)
800
843
        return self._revision_store.get_signature_text(revision_id,
801
844
                                                       self.get_transaction())
802
845
 
812
855
        if not revision_ids:
813
856
            raise ValueError("revision_ids must be non-empty in %s.check" 
814
857
                    % (self,))
 
858
        revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
815
859
        return self._check(revision_ids)
816
860
 
817
861
    def _check(self, revision_ids):
840
884
                    revision_id.encode('ascii')
841
885
                except UnicodeEncodeError:
842
886
                    raise errors.NonAsciiRevisionId(method, self)
 
887
            else:
 
888
                try:
 
889
                    revision_id.decode('ascii')
 
890
                except UnicodeDecodeError:
 
891
                    raise errors.NonAsciiRevisionId(method, self)
843
892
 
844
893
 
845
894
 
1253
1302
        # generic, possibly worst case, slow code path.
1254
1303
        target_ids = set(self.target.all_revision_ids())
1255
1304
        if revision_id is not None:
 
1305
            # TODO: jam 20070210 InterRepository is internal enough that it
 
1306
            #       should assume revision_ids are already utf-8
 
1307
            revision_id = osutils.safe_revision_id(revision_id)
1256
1308
            source_ids = self.source.get_ancestry(revision_id)
1257
1309
            assert source_ids[0] is None
1258
1310
            source_ids.pop(0)
1302
1354
            self.target.set_make_working_trees(self.source.make_working_trees())
1303
1355
        except NotImplementedError:
1304
1356
            pass
 
1357
        # TODO: jam 20070210 This is fairly internal, so we should probably
 
1358
        #       just assert that revision_id is not unicode.
 
1359
        revision_id = osutils.safe_revision_id(revision_id)
1305
1360
        # grab the basis available data
1306
1361
        if basis is not None:
1307
1362
            self.target.fetch(basis, revision_id=revision_id)
1318
1373
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1319
1374
               self.source, self.source._format, self.target, 
1320
1375
               self.target._format)
 
1376
        # TODO: jam 20070210 This should be an assert, not a translate
 
1377
        revision_id = osutils.safe_revision_id(revision_id)
1321
1378
        f = GenericRepoFetcher(to_repository=self.target,
1322
1379
                               from_repository=self.source,
1323
1380
                               last_revision=revision_id,
1360
1417
    def copy_content(self, revision_id=None, basis=None):
1361
1418
        """See InterRepository.copy_content()."""
1362
1419
        # weave specific optimised path:
 
1420
        # TODO: jam 20070210 Internal, should be an assert, not translate
 
1421
        revision_id = osutils.safe_revision_id(revision_id)
1363
1422
        if basis is not None:
1364
1423
            # copy the basis in, then fetch remaining data.
1365
1424
            basis.copy_content_into(self.target, revision_id)
1402
1461
        from bzrlib.fetch import GenericRepoFetcher
1403
1462
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1404
1463
               self.source, self.source._format, self.target, self.target._format)
 
1464
        # TODO: jam 20070210 This should be an assert, not a translate
 
1465
        revision_id = osutils.safe_revision_id(revision_id)
1405
1466
        f = GenericRepoFetcher(to_repository=self.target,
1406
1467
                               from_repository=self.source,
1407
1468
                               last_revision=revision_id,
1479
1540
        from bzrlib.fetch import KnitRepoFetcher
1480
1541
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1481
1542
               self.source, self.source._format, self.target, self.target._format)
 
1543
        # TODO: jam 20070210 This should be an assert, not a translate
 
1544
        revision_id = osutils.safe_revision_id(revision_id)
1482
1545
        f = KnitRepoFetcher(to_repository=self.target,
1483
1546
                            from_repository=self.source,
1484
1547
                            last_revision=revision_id,
1537
1600
    def fetch(self, revision_id=None, pb=None):
1538
1601
        """See InterRepository.fetch()."""
1539
1602
        from bzrlib.fetch import Model1toKnit2Fetcher
 
1603
        # TODO: jam 20070210 This should be an assert, not a translate
 
1604
        revision_id = osutils.safe_revision_id(revision_id)
1540
1605
        f = Model1toKnit2Fetcher(to_repository=self.target,
1541
1606
                                 from_repository=self.source,
1542
1607
                                 last_revision=revision_id,
1558
1623
            self.target.set_make_working_trees(self.source.make_working_trees())
1559
1624
        except NotImplementedError:
1560
1625
            pass
 
1626
        # TODO: jam 20070210 Internal, assert, don't translate
 
1627
        revision_id = osutils.safe_revision_id(revision_id)
1561
1628
        # grab the basis available data
1562
1629
        if basis is not None:
1563
1630
            self.target.fetch(basis, revision_id=revision_id)
1593
1660
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1594
1661
               self.source, self.source._format, self.target, 
1595
1662
               self.target._format)
 
1663
        # TODO: jam 20070210 This should be an assert, not a translate
 
1664
        revision_id = osutils.safe_revision_id(revision_id)
1596
1665
        f = Knit1to2Fetcher(to_repository=self.target,
1597
1666
                            from_repository=self.source,
1598
1667
                            last_revision=revision_id,
1780
1849
            self._committer = committer
1781
1850
 
1782
1851
        self.new_inventory = Inventory(None)
1783
 
        self._new_revision_id = revision_id
 
1852
        self._new_revision_id = osutils.safe_revision_id(revision_id)
1784
1853
        self.parents = parents
1785
1854
        self.repository = repository
1786
1855
 
2012
2081
 
2013
2082
 
2014
2083
def _unescaper(match, _map=_unescape_map):
2015
 
    return _map[match.group(1)]
 
2084
    code = match.group(1)
 
2085
    try:
 
2086
        return _map[code]
 
2087
    except KeyError:
 
2088
        if not code.startswith('#'):
 
2089
            raise
 
2090
        return unichr(int(code[1:])).encode('utf8')
2016
2091
 
2017
2092
 
2018
2093
_unescape_re = None