~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bundle/bundle_data.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-02-03 10:06:19 UTC
  • mfrom: (4999.3.2 apport)
  • Revision ID: pqm@pqm.ubuntu.com-20100203100619-f76bo5y5bd5c14wk
(mbp) use apport to send bugs, not just store them

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
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
 
 
21
19
import base64
22
20
from cStringIO import StringIO
23
21
import os
27
25
    osutils,
28
26
    timestamp,
29
27
    )
 
28
import bzrlib.errors
30
29
from bzrlib.bundle import apply_bundle
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
 
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
42
36
from bzrlib.revision import Revision, NULL_REVISION
43
37
from bzrlib.testament import StrictTestament
44
38
from bzrlib.trace import mutter, warning
 
39
import bzrlib.transport
45
40
from bzrlib.tree import Tree
 
41
import bzrlib.urlutils
46
42
from bzrlib.xml5 import serializer_v5
47
43
 
48
44
 
210
206
 
211
207
        inv = bundle_tree.inventory
212
208
        self._validate_inventory(inv, revision_id)
213
 
        self._validate_revision(bundle_tree, revision_id)
 
209
        self._validate_revision(inv, revision_id)
214
210
 
215
211
        return bundle_tree
216
212
 
282
278
        if rev.revision_id != revision_id:
283
279
            raise AssertionError()
284
280
        if sha1 != rev.inventory_sha1:
285
 
            f = open(',,bogus-inv', 'wb')
286
 
            try:
287
 
                f.write(s)
288
 
            finally:
289
 
                f.close()
 
281
            open(',,bogus-inv', 'wb').write(s)
290
282
            warning('Inventory sha hash mismatch for revision %s. %s'
291
283
                    ' != %s' % (revision_id, sha1, rev.inventory_sha1))
292
284
 
293
 
    def _validate_revision(self, tree, revision_id):
 
285
    def _validate_revision(self, inventory, revision_id):
294
286
        """Make sure all revision entries match their checksum."""
295
287
 
296
 
        # This is a mapping from each revision id to its sha hash
 
288
        # This is a mapping from each revision id to it's sha hash
297
289
        rev_to_sha1 = {}
298
290
 
299
291
        rev = self.get_revision(revision_id)
302
294
            raise AssertionError()
303
295
        if not (rev.revision_id == revision_id):
304
296
            raise AssertionError()
305
 
        sha1 = self._testament_sha1(rev, tree)
 
297
        sha1 = self._testament_sha1(rev, inventory)
306
298
        if sha1 != rev_info.sha1:
307
299
            raise TestamentMismatch(rev.revision_id, rev_info.sha1, sha1)
308
300
        if rev.revision_id in rev_to_sha1:
335
327
                try:
336
328
                    name, value = info_item.split(':', 1)
337
329
                except ValueError:
338
 
                    raise ValueError('Value %r has no colon' % info_item)
 
330
                    raise 'Value %r has no colon' % info_item
339
331
                if name == 'last-changed':
340
332
                    last_changed = value
341
333
                elif name == 'executable':
466
458
 
467
459
 
468
460
class BundleTree(Tree):
469
 
 
470
461
    def __init__(self, base_tree, revision_id):
471
462
        self.base_tree = base_tree
472
463
        self._renamed = {} # Mapping from old_path => new_path
576
567
            return None
577
568
        return new_path
578
569
 
579
 
    def get_root_id(self):
580
 
        return self.path2id('')
581
 
 
582
570
    def path2id(self, path):
583
571
        """Return the id of the file present at path in the target tree."""
584
572
        file_id = self._new_id.get(path)
589
577
            return None
590
578
        if old_path in self.deleted:
591
579
            return None
592
 
        return self.base_tree.path2id(old_path)
 
580
        if getattr(self.base_tree, 'path2id', None) is not None:
 
581
            return self.base_tree.path2id(old_path)
 
582
        else:
 
583
            return self.base_tree.inventory.path2id(old_path)
593
584
 
594
585
    def id2path(self, file_id):
595
586
        """Return the new path in the target tree of the file with id file_id"""
625
616
        """
626
617
        base_id = self.old_contents_id(file_id)
627
618
        if (base_id is not None and
628
 
            base_id != self.base_tree.get_root_id()):
 
619
            base_id != self.base_tree.inventory.root.file_id):
629
620
            patch_original = self.base_tree.get_file(base_id)
630
621
        else:
631
622
            patch_original = None
632
623
        file_patch = self.patches.get(self.id2path(file_id))
633
624
        if file_patch is None:
634
625
            if (patch_original is None and
635
 
                self.kind(file_id) == 'directory'):
 
626
                self.get_kind(file_id) == 'directory'):
636
627
                return StringIO()
637
628
            if patch_original is None:
638
629
                raise AssertionError("None: %s" % file_id)
643
634
                'Malformed patch for %s, %r' % (file_id, file_patch))
644
635
        return patched_file(file_patch, patch_original)
645
636
 
646
 
    def get_symlink_target(self, file_id, path=None):
647
 
        if path is None:
648
 
            path = self.id2path(file_id)
 
637
    def get_symlink_target(self, file_id):
 
638
        new_path = self.id2path(file_id)
649
639
        try:
650
 
            return self._targets[path]
 
640
            return self._targets[new_path]
651
641
        except KeyError:
652
642
            return self.base_tree.get_symlink_target(file_id)
653
643
 
654
 
    def kind(self, file_id):
 
644
    def get_kind(self, file_id):
655
645
        if file_id in self._kinds:
656
646
            return self._kinds[file_id]
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)
 
647
        return self.base_tree.inventory[file_id].kind
665
648
 
666
649
    def is_executable(self, file_id):
667
650
        path = self.id2path(file_id)
668
651
        if path in self._executable:
669
652
            return self._executable[path]
670
653
        else:
671
 
            return self.base_tree.is_executable(file_id)
 
654
            return self.base_tree.inventory[file_id].executable
672
655
 
673
656
    def get_last_changed(self, file_id):
674
657
        path = self.id2path(file_id)
675
658
        if path in self._last_changed:
676
659
            return self._last_changed[path]
677
 
        return self.base_tree.get_file_revision(file_id)
 
660
        return self.base_tree.inventory[file_id].revision
678
661
 
679
662
    def get_size_and_sha1(self, file_id):
680
663
        """Return the size and sha1 hash of the given file id.
714
697
                parent_path = dirname(path)
715
698
                parent_id = self.path2id(parent_path)
716
699
 
717
 
            kind = self.kind(file_id)
 
700
            kind = self.get_kind(file_id)
718
701
            revision_id = self.get_last_changed(file_id)
719
702
 
720
703
            name = basename(path)
725
708
                ie.executable = self.is_executable(file_id)
726
709
            elif kind == 'symlink':
727
710
                ie = InventoryLink(file_id, name, parent_id)
728
 
                ie.symlink_target = self.get_symlink_target(file_id, path)
 
711
                ie.symlink_target = self.get_symlink_target(file_id)
729
712
            ie.revision = revision_id
730
713
 
731
 
            if kind == 'file':
 
714
            if kind in ('directory', 'symlink'):
 
715
                ie.text_size, ie.text_sha1 = None, None
 
716
            else:
732
717
                ie.text_size, ie.text_sha1 = self.get_size_and_sha1(file_id)
733
 
                if ie.text_size is None:
734
 
                    raise BzrError(
735
 
                        'Got a text_size of None for file_id %r' % file_id)
 
718
            if (ie.text_size is None) and (kind == 'file'):
 
719
                raise BzrError('Got a text_size of None for file_id %r' % file_id)
736
720
            inv.add(ie)
737
721
 
738
722
        sorted_entries = self.sorted_path_id()
752
736
        for path, entry in self.inventory.iter_entries():
753
737
            yield entry.file_id
754
738
 
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
771
 
 
772
739
    def sorted_path_id(self):
773
740
        paths = []
774
741
        for result in self._new_id.iteritems():
775
742
            paths.append(result)
776
 
        for id in self.base_tree.all_file_ids():
 
743
        for id in self.base_tree:
777
744
            path = self.id2path(id)
778
745
            if path is None:
779
746
                continue