~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: Martin Pool
  • Date: 2006-11-02 10:20:19 UTC
  • mfrom: (2114 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2119.
  • Revision ID: mbp@sourcefrog.net-20061102102019-9a5a02f485dff6f6
merge bzr.dev and reconcile several changes, also some test fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
# created, but it's not for now.
28
28
ROOT_ID = "TREE_ROOT"
29
29
 
30
 
 
31
 
import collections
32
 
import os.path
 
30
import os
33
31
import re
34
32
import sys
 
33
 
 
34
from bzrlib.lazy_import import lazy_import
 
35
lazy_import(globals(), """
 
36
import collections
35
37
import tarfile
36
 
import types
37
 
from warnings import warn
38
38
 
39
39
import bzrlib
40
 
from bzrlib import errors, osutils
41
 
from bzrlib.osutils import (pumpfile, quotefn, splitpath, joinpath,
42
 
                            pathjoin, sha_strings)
43
 
from bzrlib.errors import (NotVersionedError, InvalidEntryName,
44
 
                           BzrError, BzrCheckError, BinaryFile)
 
40
from bzrlib import (
 
41
    errors,
 
42
    osutils,
 
43
    symbol_versioning,
 
44
    )
 
45
""")
 
46
 
 
47
from bzrlib.errors import (
 
48
    BzrCheckError,
 
49
    BzrError,
 
50
    )
45
51
from bzrlib.trace import mutter
46
52
 
47
53
 
82
88
    InventoryDirectory('123', 'src', parent_id='TREE_ROOT', revision=None)
83
89
    >>> i.add(InventoryFile('2323', 'hello.c', parent_id='123'))
84
90
    InventoryFile('2323', 'hello.c', parent_id='123', sha1=None, len=None)
85
 
    >>> shouldbe = {0: '', 1: 'src', 2: pathjoin('src','hello.c')}
 
91
    >>> shouldbe = {0: '', 1: 'src', 2: 'src/hello.c'}
86
92
    >>> for ix, j in enumerate(i.iter_entries()):
87
93
    ...   print (j[0] == shouldbe[ix], j[1])
88
94
    ... 
246
252
 
247
253
    def get_tar_item(self, root, dp, now, tree):
248
254
        """Get a tarfile item and a file stream for its content."""
249
 
        item = tarfile.TarInfo(pathjoin(root, dp).encode('utf8'))
 
255
        item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
250
256
        # TODO: would be cool to actually set it to the timestamp of the
251
257
        # revision it was last changed
252
258
        item.mtime = now
281
287
        """
282
288
        assert isinstance(name, basestring), name
283
289
        if '/' in name or '\\' in name:
284
 
            raise InvalidEntryName(name=name)
 
290
            raise errors.InvalidEntryName(name=name)
285
291
        self.executable = False
286
292
        self.revision = None
287
293
        self.text_sha1 = None
311
317
        
312
318
        This is a template method - implement _put_on_disk in subclasses.
313
319
        """
314
 
        fullpath = pathjoin(dest, dp)
 
320
        fullpath = osutils.pathjoin(dest, dp)
315
321
        self._put_on_disk(fullpath, tree)
316
322
        # mutter("  export {%s} kind %s to %s", self.file_id,
317
323
        #         self.kind, fullpath)
514
520
        self.parent_id = None
515
521
        self.name = u''
516
522
        self.revision = None
517
 
        warn('RootEntry is deprecated as of bzr 0.10.  Please use '
518
 
             'InventoryDirectory instead.',
519
 
            DeprecationWarning, stacklevel=2)
 
523
        symbol_versioning.warn('RootEntry is deprecated as of bzr 0.10.'
 
524
                               '  Please use InventoryDirectory instead.',
 
525
                               DeprecationWarning, stacklevel=2)
520
526
 
521
527
    def __eq__(self, other):
522
528
        if not isinstance(other, RootEntry):
645
651
            else:
646
652
                text_diff(to_label, to_text,
647
653
                          from_label, from_text, output_to)
648
 
        except BinaryFile:
 
654
        except errors.BinaryFile:
649
655
            if reverse:
650
656
                label_pair = (to_label, from_label)
651
657
            else:
677
683
 
678
684
    def _put_on_disk(self, fullpath, tree):
679
685
        """See InventoryEntry._put_on_disk."""
680
 
        pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
 
686
        osutils.pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
681
687
        if tree.is_executable(self.file_id):
682
688
            os.chmod(fullpath, 0755)
683
689
 
849
855
    ['', u'hello.c']
850
856
    >>> inv = Inventory('TREE_ROOT-12345678-12345678')
851
857
    >>> inv.add(InventoryFile('123-123', 'hello.c', ROOT_ID))
 
858
    Traceback (most recent call last):
 
859
    BzrError: parent_id {TREE_ROOT} not in inventory
 
860
    >>> inv.add(InventoryFile('123-123', 'hello.c', 'TREE_ROOT-12345678-12345678'))
852
861
    InventoryFile('123-123', 'hello.c', parent_id='TREE_ROOT-12345678-12345678', sha1=None, len=None)
853
862
    """
854
863
    def __init__(self, root_id=ROOT_ID, revision_id=None):
861
870
        The inventory is created with a default root directory, with
862
871
        an id of None.
863
872
        """
864
 
        # We are letting Branch.create() create a unique inventory
865
 
        # root id. Rather than generating a random one here.
866
 
        #if root_id is None:
867
 
        #    root_id = bzrlib.branch.gen_file_id('TREE_ROOT')
868
873
        if root_id is not None:
869
874
            self._set_root(InventoryDirectory(root_id, '', None))
870
875
        else:
871
876
            self.root = None
872
877
            self._byid = {}
873
 
        # FIXME: this isn't ever used, changing it to self.revision may break
874
 
        # things. TODO make everything use self.revision_id
875
878
        self.revision_id = revision_id
876
879
 
877
880
    def _set_root(self, ie):
898
901
    def iter_entries(self, from_dir=None):
899
902
        """Return (path, entry) pairs, in order by name."""
900
903
        if from_dir is None:
901
 
            assert self.root
 
904
            if self.root is None:
 
905
                return
902
906
            from_dir = self.root
903
907
            yield '', self.root
904
908
        elif isinstance(from_dir, basestring):
951
955
        # TODO? Perhaps this should return the from_dir so that the root is
952
956
        # yielded? or maybe an option?
953
957
        if from_dir is None:
954
 
            assert self.root
 
958
            if self.root is None:
 
959
                return
955
960
            from_dir = self.root
956
961
            yield '', self.root
957
962
        elif isinstance(from_dir, basestring):
982
987
            kids = dir_ie.children.items()
983
988
            kids.sort()
984
989
            for name, ie in kids:
985
 
                child_path = pathjoin(dir_path, name)
 
990
                child_path = osutils.pathjoin(dir_path, name)
986
991
                accum.append((child_path, ie))
987
992
                if ie.kind == 'directory':
988
993
                    descend(ie, child_path)
1001
1006
            kids.sort()
1002
1007
 
1003
1008
            for name, child_ie in kids:
1004
 
                child_path = pathjoin(parent_path, name)
 
1009
                child_path = osutils.pathjoin(parent_path, name)
1005
1010
                descend(child_ie, child_path)
1006
1011
        descend(self.root, u'')
1007
1012
        return accum
1055
1060
            assert self.root is None and len(self._byid) == 0
1056
1061
            self._set_root(entry)
1057
1062
            return entry
1058
 
        if entry.parent_id == ROOT_ID:
1059
 
            assert self.root is not None, self
1060
 
            entry.parent_id = self.root.file_id
1061
 
 
1062
1063
        try:
1063
1064
            parent = self._byid[entry.parent_id]
1064
1065
        except KeyError:
1066
1067
 
1067
1068
        if entry.name in parent.children:
1068
1069
            raise BzrError("%s is already versioned" %
1069
 
                    pathjoin(self.id2path(parent.file_id), entry.name))
 
1070
                    osutils.pathjoin(self.id2path(parent.file_id), entry.name))
1070
1071
 
1071
1072
        self._byid[entry.file_id] = entry
1072
1073
        parent.children[entry.name] = entry
1091
1092
            parent_path = parts[:-1]
1092
1093
            parent_id = self.path2id(parent_path)
1093
1094
            if parent_id is None:
1094
 
                raise NotVersionedError(path=parent_path)
 
1095
                raise errors.NotVersionedError(path=parent_path)
1095
1096
        ie = make_entry(kind, parts[-1], parent_id, file_id)
1096
1097
        return self.add(ie)
1097
1098
 
1191
1192
 
1192
1193
        Returns None IFF the path is not found.
1193
1194
        """
1194
 
        if isinstance(name, types.StringTypes):
1195
 
            name = splitpath(name)
 
1195
        if isinstance(name, basestring):
 
1196
            name = osutils.splitpath(name)
1196
1197
 
1197
1198
        # mutter("lookup path %r" % name)
1198
1199
 
1199
1200
        parent = self.root
 
1201
        if parent is None:
 
1202
            return None
1200
1203
        for f in name:
1201
1204
            try:
1202
 
                cie = parent.children[f]
 
1205
                children = getattr(parent, 'children', None)
 
1206
                if children is None:
 
1207
                    return None
 
1208
                cie = children[f]
1203
1209
                assert cie.name == f
1204
1210
                assert cie.parent_id == parent.file_id
1205
1211
                parent = cie
1262
1268
        file_ie.name = new_name
1263
1269
        file_ie.parent_id = new_parent_id
1264
1270
 
 
1271
    def is_root(self, file_id):
 
1272
        return self.root is not None and file_id == self.root.file_id
 
1273
 
1265
1274
 
1266
1275
def make_entry(kind, name, parent_id, file_id=None):
1267
1276
    """Create an inventory entry.