~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-14 16:16:53 UTC
  • mto: (1946.2.6 reduce-knit-churn)
  • mto: This revision was merged to the branch mainline in revision 1919.
  • Revision ID: john@arbash-meinel.com-20060814161653-54cdcdadcd4e9003
Remove bogus entry from BRANCH.TODO

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
 
import os
 
30
 
 
31
import collections
 
32
import os.path
31
33
import re
32
34
import sys
33
 
 
34
 
from bzrlib.lazy_import import lazy_import
35
 
lazy_import(globals(), """
36
 
import collections
37
35
import tarfile
 
36
import types
 
37
from warnings import warn
38
38
 
39
39
import bzrlib
40
 
from bzrlib import (
41
 
    errors,
42
 
    osutils,
43
 
    symbol_versioning,
44
 
    )
45
 
""")
46
 
 
47
 
from bzrlib.errors import (
48
 
    BzrCheckError,
49
 
    BzrError,
50
 
    )
 
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)
51
45
from bzrlib.trace import mutter
52
46
 
53
47
 
88
82
    InventoryDirectory('123', 'src', parent_id='TREE_ROOT', revision=None)
89
83
    >>> i.add(InventoryFile('2323', 'hello.c', parent_id='123'))
90
84
    InventoryFile('2323', 'hello.c', parent_id='123', sha1=None, len=None)
91
 
    >>> shouldbe = {0: '', 1: 'src', 2: 'src/hello.c'}
 
85
    >>> shouldbe = {0: '', 1: 'src', 2: pathjoin('src','hello.c')}
92
86
    >>> for ix, j in enumerate(i.iter_entries()):
93
87
    ...   print (j[0] == shouldbe[ix], j[1])
94
88
    ... 
252
246
 
253
247
    def get_tar_item(self, root, dp, now, tree):
254
248
        """Get a tarfile item and a file stream for its content."""
255
 
        item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
 
249
        item = tarfile.TarInfo(pathjoin(root, dp))
256
250
        # TODO: would be cool to actually set it to the timestamp of the
257
251
        # revision it was last changed
258
252
        item.mtime = now
287
281
        """
288
282
        assert isinstance(name, basestring), name
289
283
        if '/' in name or '\\' in name:
290
 
            raise errors.InvalidEntryName(name=name)
 
284
            raise InvalidEntryName(name=name)
291
285
        self.executable = False
292
286
        self.revision = None
293
287
        self.text_sha1 = None
317
311
        
318
312
        This is a template method - implement _put_on_disk in subclasses.
319
313
        """
320
 
        fullpath = osutils.pathjoin(dest, dp)
 
314
        fullpath = pathjoin(dest, dp)
321
315
        self._put_on_disk(fullpath, tree)
322
316
        # mutter("  export {%s} kind %s to %s", self.file_id,
323
317
        #         self.kind, fullpath)
331
325
 
332
326
    @staticmethod
333
327
    def versionable_kind(kind):
334
 
        return (kind in ('file', 'directory', 'symlink'))
 
328
        return kind in ('file', 'directory', 'symlink')
335
329
 
336
330
    def check(self, checker, rev_id, inv, tree):
337
331
        """Check this inventory entry is intact.
520
514
        self.parent_id = None
521
515
        self.name = u''
522
516
        self.revision = None
523
 
        symbol_versioning.warn('RootEntry is deprecated as of bzr 0.10.'
524
 
                               '  Please use InventoryDirectory instead.',
525
 
                               DeprecationWarning, stacklevel=2)
 
517
        warn('RootEntry is deprecated as of bzr 0.10.  Please use '
 
518
             'InventoryDirectory instead.',
 
519
            DeprecationWarning, stacklevel=2)
526
520
 
527
521
    def __eq__(self, other):
528
522
        if not isinstance(other, RootEntry):
651
645
            else:
652
646
                text_diff(to_label, to_text,
653
647
                          from_label, from_text, output_to)
654
 
        except errors.BinaryFile:
 
648
        except BinaryFile:
655
649
            if reverse:
656
650
                label_pair = (to_label, from_label)
657
651
            else:
683
677
 
684
678
    def _put_on_disk(self, fullpath, tree):
685
679
        """See InventoryEntry._put_on_disk."""
686
 
        osutils.pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
 
680
        pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
687
681
        if tree.is_executable(self.file_id):
688
682
            os.chmod(fullpath, 0755)
689
683
 
855
849
    ['', u'hello.c']
856
850
    >>> inv = Inventory('TREE_ROOT-12345678-12345678')
857
851
    >>> 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'))
861
852
    InventoryFile('123-123', 'hello.c', parent_id='TREE_ROOT-12345678-12345678', sha1=None, len=None)
862
853
    """
863
854
    def __init__(self, root_id=ROOT_ID, revision_id=None):
870
861
        The inventory is created with a default root directory, with
871
862
        an id of None.
872
863
        """
873
 
        if root_id is not None:
874
 
            self._set_root(InventoryDirectory(root_id, '', None))
875
 
        else:
876
 
            self.root = None
877
 
            self._byid = {}
 
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
        self.root = InventoryDirectory(root_id, '', None)
 
869
        # FIXME: this isn't ever used, changing it to self.revision may break
 
870
        # things. TODO make everything use self.revision_id
878
871
        self.revision_id = revision_id
879
 
 
880
 
    def _set_root(self, ie):
881
 
        self.root = ie
882
872
        self._byid = {self.root.file_id: self.root}
883
873
 
884
874
    def copy(self):
901
891
    def iter_entries(self, from_dir=None):
902
892
        """Return (path, entry) pairs, in order by name."""
903
893
        if from_dir is None:
904
 
            if self.root is None:
905
 
                return
 
894
            assert self.root
906
895
            from_dir = self.root
907
896
            yield '', self.root
908
897
        elif isinstance(from_dir, basestring):
955
944
        # TODO? Perhaps this should return the from_dir so that the root is
956
945
        # yielded? or maybe an option?
957
946
        if from_dir is None:
958
 
            if self.root is None:
959
 
                return
 
947
            assert self.root
960
948
            from_dir = self.root
961
949
            yield '', self.root
962
950
        elif isinstance(from_dir, basestring):
987
975
            kids = dir_ie.children.items()
988
976
            kids.sort()
989
977
            for name, ie in kids:
990
 
                child_path = osutils.pathjoin(dir_path, name)
 
978
                child_path = pathjoin(dir_path, name)
991
979
                accum.append((child_path, ie))
992
980
                if ie.kind == 'directory':
993
981
                    descend(ie, child_path)
1006
994
            kids.sort()
1007
995
 
1008
996
            for name, child_ie in kids:
1009
 
                child_path = osutils.pathjoin(parent_path, name)
 
997
                child_path = pathjoin(parent_path, name)
1010
998
                descend(child_ie, child_path)
1011
999
        descend(self.root, u'')
1012
1000
        return accum
1022
1010
        >>> '456' in inv
1023
1011
        False
1024
1012
        """
1025
 
        return (file_id in self._byid)
 
1013
        return file_id in self._byid
1026
1014
 
1027
1015
    def __getitem__(self, file_id):
1028
1016
        """Return the entry for given file_id.
1058
1046
        if entry.file_id in self._byid:
1059
1047
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
1060
1048
 
1061
 
        if entry.parent_id is None:
1062
 
            assert self.root is None and len(self._byid) == 0
1063
 
            self._set_root(entry)
1064
 
            return entry
 
1049
        if entry.parent_id == ROOT_ID or entry.parent_id is None:
 
1050
            entry.parent_id = self.root.file_id
 
1051
 
1065
1052
        try:
1066
1053
            parent = self._byid[entry.parent_id]
1067
1054
        except KeyError:
1069
1056
 
1070
1057
        if entry.name in parent.children:
1071
1058
            raise BzrError("%s is already versioned" %
1072
 
                    osutils.pathjoin(self.id2path(parent.file_id), entry.name))
 
1059
                    pathjoin(self.id2path(parent.file_id), entry.name))
1073
1060
 
1074
1061
        self._byid[entry.file_id] = entry
1075
1062
        parent.children[entry.name] = entry
1094
1081
            parent_path = parts[:-1]
1095
1082
            parent_id = self.path2id(parent_path)
1096
1083
            if parent_id is None:
1097
 
                raise errors.NotVersionedError(path=parent_path)
 
1084
                raise NotVersionedError(path=parent_path)
1098
1085
        ie = make_entry(kind, parts[-1], parent_id, file_id)
1099
1086
        return self.add(ie)
1100
1087
 
1194
1181
 
1195
1182
        Returns None IFF the path is not found.
1196
1183
        """
1197
 
        if isinstance(name, basestring):
1198
 
            name = osutils.splitpath(name)
 
1184
        if isinstance(name, types.StringTypes):
 
1185
            name = splitpath(name)
1199
1186
 
1200
1187
        # mutter("lookup path %r" % name)
1201
1188
 
1202
1189
        parent = self.root
1203
 
        if parent is None:
1204
 
            return None
1205
1190
        for f in name:
1206
1191
            try:
1207
 
                children = getattr(parent, 'children', None)
1208
 
                if children is None:
1209
 
                    return None
1210
 
                cie = children[f]
 
1192
                cie = parent.children[f]
1211
1193
                assert cie.name == f
1212
1194
                assert cie.parent_id == parent.file_id
1213
1195
                parent = cie
1221
1203
        return bool(self.path2id(names))
1222
1204
 
1223
1205
    def has_id(self, file_id):
1224
 
        return (file_id in self._byid)
1225
 
 
1226
 
    def remove_recursive_id(self, file_id):
1227
 
        """Remove file_id, and children, from the inventory.
1228
 
        
1229
 
        :param file_id: A file_id to remove.
1230
 
        """
1231
 
        to_find_delete = [self._byid[file_id]]
1232
 
        to_delete = []
1233
 
        while to_find_delete:
1234
 
            ie = to_find_delete.pop()
1235
 
            to_delete.append(ie.file_id)
1236
 
            if ie.kind == 'directory':
1237
 
                to_find_delete.extend(ie.children.values())
1238
 
        for file_id in reversed(to_delete):
1239
 
            ie = self[file_id]
1240
 
            del self._byid[file_id]
1241
 
            if ie.parent_id is not None:
1242
 
                del self[ie.parent_id].children[ie.name]
 
1206
        return self._byid.has_key(file_id)
1243
1207
 
1244
1208
    def rename(self, file_id, new_parent_id, new_name):
1245
1209
        """Move a file within the inventory.
1270
1234
        file_ie.name = new_name
1271
1235
        file_ie.parent_id = new_parent_id
1272
1236
 
1273
 
    def is_root(self, file_id):
1274
 
        return self.root is not None and file_id == self.root.file_id
1275
 
 
1276
1237
 
1277
1238
def make_entry(kind, name, parent_id, file_id=None):
1278
1239
    """Create an inventory entry.