19
19
from __future__ import absolute_import
22
from cStringIO import StringIO
30
from . import apply_bundle
31
from ..errors import (
30
from bzrlib.bundle import apply_bundle
31
from bzrlib.errors import (
35
from ..bzr.inventory import (
35
from bzrlib.inventory import (
37
37
InventoryDirectory,
41
from ..osutils import sha_string, pathjoin
42
from ..revision import Revision, NULL_REVISION
43
from ..sixish import (
47
from ..testament import StrictTestament
48
from ..trace import mutter, warning
49
from ..tree import Tree
50
from ..bzr.xml5 import serializer_v5
41
from bzrlib.osutils import sha_string, pathjoin
42
from bzrlib.revision import Revision, NULL_REVISION
43
from bzrlib.testament import StrictTestament
44
from bzrlib.trace import mutter, warning
45
from bzrlib.tree import Tree
46
from bzrlib.xml5 import serializer_v5
53
49
class RevisionInfo(object):
623
623
in the text-store, so that the file contents would
627
file_id = self.path2id(path)
628
626
base_id = self.old_contents_id(file_id)
629
627
if (base_id is not None and
630
628
base_id != self.base_tree.get_root_id()):
631
old_path = self.old_path(path)
632
patch_original = self.base_tree.get_file(
629
patch_original = self.base_tree.get_file(base_id)
635
631
patch_original = None
636
file_patch = self.patches.get(path)
632
file_patch = self.patches.get(self.id2path(file_id))
637
633
if file_patch is None:
638
634
if (patch_original is None and
639
self.kind(path, file_id) == 'directory'):
635
self.kind(file_id) == 'directory'):
641
637
if patch_original is None:
642
638
raise AssertionError("None: %s" % file_id)
643
639
return patch_original
647
643
'Malformed patch for %s, %r' % (file_id, file_patch))
648
644
return patched_file(file_patch, patch_original)
650
def get_symlink_target(self, path, file_id=None):
646
def get_symlink_target(self, file_id, path=None):
648
path = self.id2path(file_id)
652
650
return self._targets[path]
654
old_path = self.old_path(path)
655
return self.base_tree.get_symlink_target(old_path, file_id)
657
def kind(self, path, file_id=None):
659
return self._kinds[path]
661
old_path = self.old_path(path)
662
return self.base_tree.kind(old_path, file_id)
664
def get_file_revision(self, path, file_id=None):
652
return self.base_tree.get_symlink_target(file_id)
654
def kind(self, file_id):
655
if file_id in self._kinds:
656
return self._kinds[file_id]
657
return self.base_tree.kind(file_id)
659
def get_file_revision(self, file_id):
660
path = self.id2path(file_id)
665
661
if path in self._last_changed:
666
662
return self._last_changed[path]
668
old_path = self.old_path(path)
669
return self.base_tree.get_file_revision(old_path, file_id)
664
return self.base_tree.get_file_revision(file_id)
671
def is_executable(self, path, file_id=None):
666
def is_executable(self, file_id):
667
path = self.id2path(file_id)
672
668
if path in self._executable:
673
669
return self._executable[path]
675
old_path = self.old_path(path)
676
return self.base_tree.is_executable(old_path, file_id)
671
return self.base_tree.is_executable(file_id)
678
def get_last_changed(self, path, file_id=None):
673
def get_last_changed(self, file_id):
674
path = self.id2path(file_id)
679
675
if path in self._last_changed:
680
676
return self._last_changed[path]
681
old_path = self.old_path(path)
682
return self.base_tree.get_file_revision(old_path, file_id)
677
return self.base_tree.get_file_revision(file_id)
684
def get_size_and_sha1(self, new_path, file_id=None):
679
def get_size_and_sha1(self, file_id):
685
680
"""Return the size and sha1 hash of the given file id.
686
681
If the file was not locally modified, this is extracted
687
682
from the base_tree. Rather than re-reading the file.
684
new_path = self.id2path(file_id)
689
685
if new_path is None:
690
686
return None, None
691
687
if new_path not in self.patches:
692
688
# If the entry does not have a patch, then the
693
689
# contents must be the same as in the base_tree
694
base_path = self.old_path(new_path)
695
text_size = self.base_tree.get_file_size(base_path, file_id)
696
text_sha1 = self.base_tree.get_file_sha1(base_path, file_id)
690
text_size = self.base_tree.get_file_size(file_id)
691
text_sha1 = self.base_tree.get_file_sha1(file_id)
697
692
return text_size, text_sha1
698
fileobj = self.get_file(new_path, file_id)
693
fileobj = self.get_file(file_id)
699
694
content = fileobj.read()
700
695
return len(content), sha_string(content)
707
702
from os.path import dirname, basename
708
703
inv = Inventory(None, self.revision_id)
710
def add_entry(path, file_id):
705
def add_entry(file_id):
706
path = self.id2path(file_id)
714
712
parent_path = dirname(path)
715
713
parent_id = self.path2id(parent_path)
717
kind = self.kind(path, file_id)
718
revision_id = self.get_last_changed(path, file_id)
715
kind = self.kind(file_id)
716
revision_id = self.get_last_changed(file_id)
720
718
name = basename(path)
721
719
if kind == 'directory':
722
720
ie = InventoryDirectory(file_id, name, parent_id)
723
721
elif kind == 'file':
724
722
ie = InventoryFile(file_id, name, parent_id)
725
ie.executable = self.is_executable(path, file_id)
723
ie.executable = self.is_executable(file_id)
726
724
elif kind == 'symlink':
727
725
ie = InventoryLink(file_id, name, parent_id)
728
ie.symlink_target = self.get_symlink_target(path, file_id)
726
ie.symlink_target = self.get_symlink_target(file_id, path)
729
727
ie.revision = revision_id
731
729
if kind == 'file':
732
ie.text_size, ie.text_sha1 = self.get_size_and_sha1(
730
ie.text_size, ie.text_sha1 = self.get_size_and_sha1(file_id)
734
731
if ie.text_size is None:
736
733
'Got a text_size of None for file_id %r' % file_id)
770
765
entries = inv.iter_entries(from_dir=from_dir_id, recursive=recursive)
771
766
if inv.root is not None and not include_root and from_dir is None:
772
767
# skip the root for compatability with the current apis.
774
769
for path, entry in entries:
775
770
yield path, 'V', entry.kind, entry.file_id, entry
777
772
def sorted_path_id(self):
779
for result in viewitems(self._new_id):
774
for result in self._new_id.iteritems():
780
775
paths.append(result)
781
776
for id in self.base_tree.all_file_ids():
782
777
path = self.id2path(id)
790
785
def patched_file(file_patch, original):
791
786
"""Produce a file-like object with the patched version of a text"""
792
from breezy.patches import iter_patched
793
from breezy.iterablefile import IterableFile
787
from bzrlib.patches import iter_patched
788
from bzrlib.iterablefile import IterableFile
794
789
if file_patch == "":
795
790
return IterableFile(())
796
791
# string.splitlines(True) also splits on '\r', but the iter_patched code
797
792
# only expects to iterate over '\n' style lines
798
793
return IterableFile(iter_patched(original,
799
BytesIO(file_patch).readlines()))
794
StringIO(file_patch).readlines()))