~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bundle/bundle_data.py

(vila) Fix bzrlib.tests.test_gpg.TestVerify.test_verify_revoked_signature
 with recent versions of gpg. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Read in a bundle stream, and process it into a BundleReader object."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
import base64
20
22
from cStringIO import StringIO
21
23
import os
25
27
    osutils,
26
28
    timestamp,
27
29
    )
28
 
import bzrlib.errors
29
30
from bzrlib.bundle import apply_bundle
30
 
from bzrlib.errors import (TestamentMismatch, BzrError,
31
 
                           MalformedHeader, MalformedPatches, NotABundle)
32
 
from bzrlib.inventory import (Inventory, InventoryEntry,
33
 
                              InventoryDirectory, InventoryFile,
34
 
                              InventoryLink)
35
 
from bzrlib.osutils import sha_file, sha_string, pathjoin
 
31
from bzrlib.errors import (
 
32
    TestamentMismatch,
 
33
    BzrError,
 
34
    )
 
35
from bzrlib.inventory import (
 
36
    Inventory,
 
37
    InventoryDirectory,
 
38
    InventoryFile,
 
39
    InventoryLink,
 
40
    )
 
41
from bzrlib.osutils import sha_string, pathjoin
36
42
from bzrlib.revision import Revision, NULL_REVISION
37
43
from bzrlib.testament import StrictTestament
38
44
from bzrlib.trace import mutter, warning
39
 
import bzrlib.transport
40
45
from bzrlib.tree import Tree
41
 
import bzrlib.urlutils
42
46
from bzrlib.xml5 import serializer_v5
43
47
 
44
48
 
206
210
 
207
211
        inv = bundle_tree.inventory
208
212
        self._validate_inventory(inv, revision_id)
209
 
        self._validate_revision(inv, revision_id)
 
213
        self._validate_revision(bundle_tree, revision_id)
210
214
 
211
215
        return bundle_tree
212
216
 
286
290
            warning('Inventory sha hash mismatch for revision %s. %s'
287
291
                    ' != %s' % (revision_id, sha1, rev.inventory_sha1))
288
292
 
289
 
    def _validate_revision(self, inventory, revision_id):
 
293
    def _validate_revision(self, tree, revision_id):
290
294
        """Make sure all revision entries match their checksum."""
291
295
 
292
 
        # This is a mapping from each revision id to it's sha hash
 
296
        # This is a mapping from each revision id to its sha hash
293
297
        rev_to_sha1 = {}
294
298
 
295
299
        rev = self.get_revision(revision_id)
298
302
            raise AssertionError()
299
303
        if not (rev.revision_id == revision_id):
300
304
            raise AssertionError()
301
 
        sha1 = self._testament_sha1(rev, inventory)
 
305
        sha1 = self._testament_sha1(rev, tree)
302
306
        if sha1 != rev_info.sha1:
303
307
            raise TestamentMismatch(rev.revision_id, rev_info.sha1, sha1)
304
308
        if rev.revision_id in rev_to_sha1:
462
466
 
463
467
 
464
468
class BundleTree(Tree):
 
469
 
465
470
    def __init__(self, base_tree, revision_id):
466
471
        self.base_tree = base_tree
467
472
        self._renamed = {} # Mapping from old_path => new_path
571
576
            return None
572
577
        return new_path
573
578
 
 
579
    def get_root_id(self):
 
580
        return self.path2id('')
 
581
 
574
582
    def path2id(self, path):
575
583
        """Return the id of the file present at path in the target tree."""
576
584
        file_id = self._new_id.get(path)
581
589
            return None
582
590
        if old_path in self.deleted:
583
591
            return None
584
 
        if getattr(self.base_tree, 'path2id', None) is not None:
585
 
            return self.base_tree.path2id(old_path)
586
 
        else:
587
 
            return self.base_tree.inventory.path2id(old_path)
 
592
        return self.base_tree.path2id(old_path)
588
593
 
589
594
    def id2path(self, file_id):
590
595
        """Return the new path in the target tree of the file with id file_id"""
620
625
        """
621
626
        base_id = self.old_contents_id(file_id)
622
627
        if (base_id is not None and
623
 
            base_id != self.base_tree.inventory.root.file_id):
 
628
            base_id != self.base_tree.get_root_id()):
624
629
            patch_original = self.base_tree.get_file(base_id)
625
630
        else:
626
631
            patch_original = None
627
632
        file_patch = self.patches.get(self.id2path(file_id))
628
633
        if file_patch is None:
629
634
            if (patch_original is None and
630
 
                self.get_kind(file_id) == 'directory'):
 
635
                self.kind(file_id) == 'directory'):
631
636
                return StringIO()
632
637
            if patch_original is None:
633
638
                raise AssertionError("None: %s" % file_id)
638
643
                'Malformed patch for %s, %r' % (file_id, file_patch))
639
644
        return patched_file(file_patch, patch_original)
640
645
 
641
 
    def get_symlink_target(self, file_id):
642
 
        new_path = self.id2path(file_id)
 
646
    def get_symlink_target(self, file_id, path=None):
 
647
        if path is None:
 
648
            path = self.id2path(file_id)
643
649
        try:
644
 
            return self._targets[new_path]
 
650
            return self._targets[path]
645
651
        except KeyError:
646
652
            return self.base_tree.get_symlink_target(file_id)
647
653
 
648
 
    def get_kind(self, file_id):
 
654
    def kind(self, file_id):
649
655
        if file_id in self._kinds:
650
656
            return self._kinds[file_id]
651
 
        return self.base_tree.inventory[file_id].kind
 
657
        return self.base_tree.kind(file_id)
 
658
 
 
659
    def get_file_revision(self, file_id):
 
660
        path = self.id2path(file_id)
 
661
        if path in self._last_changed:
 
662
            return self._last_changed[path]
 
663
        else:
 
664
            return self.base_tree.get_file_revision(file_id)
652
665
 
653
666
    def is_executable(self, file_id):
654
667
        path = self.id2path(file_id)
655
668
        if path in self._executable:
656
669
            return self._executable[path]
657
670
        else:
658
 
            return self.base_tree.inventory[file_id].executable
 
671
            return self.base_tree.is_executable(file_id)
659
672
 
660
673
    def get_last_changed(self, file_id):
661
674
        path = self.id2path(file_id)
662
675
        if path in self._last_changed:
663
676
            return self._last_changed[path]
664
 
        return self.base_tree.inventory[file_id].revision
 
677
        return self.base_tree.get_file_revision(file_id)
665
678
 
666
679
    def get_size_and_sha1(self, file_id):
667
680
        """Return the size and sha1 hash of the given file id.
674
687
        if new_path not in self.patches:
675
688
            # If the entry does not have a patch, then the
676
689
            # contents must be the same as in the base_tree
677
 
            ie = self.base_tree.inventory[file_id]
678
 
            if ie.text_size is None:
679
 
                return ie.text_size, ie.text_sha1
680
 
            return int(ie.text_size), ie.text_sha1
 
690
            text_size = self.base_tree.get_file_size(file_id)
 
691
            text_sha1 = self.base_tree.get_file_sha1(file_id)
 
692
            return text_size, text_sha1
681
693
        fileobj = self.get_file(file_id)
682
694
        content = fileobj.read()
683
695
        return len(content), sha_string(content)
688
700
        This need to be called before ever accessing self.inventory
689
701
        """
690
702
        from os.path import dirname, basename
691
 
        base_inv = self.base_tree.inventory
692
703
        inv = Inventory(None, self.revision_id)
693
704
 
694
705
        def add_entry(file_id):
701
712
                parent_path = dirname(path)
702
713
                parent_id = self.path2id(parent_path)
703
714
 
704
 
            kind = self.get_kind(file_id)
 
715
            kind = self.kind(file_id)
705
716
            revision_id = self.get_last_changed(file_id)
706
717
 
707
718
            name = basename(path)
712
723
                ie.executable = self.is_executable(file_id)
713
724
            elif kind == 'symlink':
714
725
                ie = InventoryLink(file_id, name, parent_id)
715
 
                ie.symlink_target = self.get_symlink_target(file_id)
 
726
                ie.symlink_target = self.get_symlink_target(file_id, path)
716
727
            ie.revision = revision_id
717
728
 
718
729
            if kind == 'file':
735
746
    # at that instant
736
747
    inventory = property(_get_inventory)
737
748
 
738
 
    def __iter__(self):
739
 
        for path, entry in self.inventory.iter_entries():
740
 
            yield entry.file_id
 
749
    root_inventory = property(_get_inventory)
 
750
 
 
751
    def all_file_ids(self):
 
752
        return set(
 
753
            [entry.file_id for path, entry in self.inventory.iter_entries()])
 
754
 
 
755
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
756
        # The only files returned by this are those from the version
 
757
        inv = self.inventory
 
758
        if from_dir is None:
 
759
            from_dir_id = None
 
760
        else:
 
761
            from_dir_id = inv.path2id(from_dir)
 
762
            if from_dir_id is None:
 
763
                # Directory not versioned
 
764
                return
 
765
        entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
 
766
        if inv.root is not None and not include_root and from_dir is None:
 
767
            # skip the root for compatability with the current apis.
 
768
            entries.next()
 
769
        for path, entry in entries:
 
770
            yield path, 'V', entry.kind, entry.file_id, entry
741
771
 
742
772
    def sorted_path_id(self):
743
773
        paths = []
744
774
        for result in self._new_id.iteritems():
745
775
            paths.append(result)
746
 
        for id in self.base_tree:
 
776
        for id in self.base_tree.all_file_ids():
747
777
            path = self.id2path(id)
748
778
            if path is None:
749
779
                continue