/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-13 02:09:37 UTC
  • mto: This revision was merged to the branch mainline in revision 2004.
  • Revision ID: john@arbash-meinel.com-20060913020937-2df2f49f9a28ec43
Update HACKING and docstrings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 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
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
 
    generate_ids,
43
 
    osutils,
44
 
    symbol_versioning,
45
 
    workingtree,
46
 
    )
47
 
""")
48
 
 
49
 
from bzrlib.errors import (
50
 
    BzrCheckError,
51
 
    BzrError,
52
 
    )
 
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)
53
45
from bzrlib.trace import mutter
54
46
 
55
47
 
90
82
    InventoryDirectory('123', 'src', parent_id='TREE_ROOT', revision=None)
91
83
    >>> i.add(InventoryFile('2323', 'hello.c', parent_id='123'))
92
84
    InventoryFile('2323', 'hello.c', parent_id='123', sha1=None, len=None)
93
 
    >>> shouldbe = {0: '', 1: 'src', 2: 'src/hello.c'}
 
85
    >>> shouldbe = {0: '', 1: 'src', 2: pathjoin('src','hello.c')}
94
86
    >>> for ix, j in enumerate(i.iter_entries()):
95
87
    ...   print (j[0] == shouldbe[ix], j[1])
96
88
    ... 
97
 
    (True, InventoryDirectory('TREE_ROOT', u'', parent_id=None, revision=None))
 
89
    (True, InventoryDirectory('TREE_ROOT', '', parent_id=None, revision=None))
98
90
    (True, InventoryDirectory('123', 'src', parent_id='TREE_ROOT', revision=None))
99
91
    (True, InventoryFile('2323', 'hello.c', parent_id='123', sha1=None, len=None))
 
92
    >>> i.add(InventoryFile('2323', 'bye.c', '123'))
 
93
    Traceback (most recent call last):
 
94
    ...
 
95
    BzrError: inventory already contains entry with id {2323}
100
96
    >>> i.add(InventoryFile('2324', 'bye.c', '123'))
101
97
    InventoryFile('2324', 'bye.c', parent_id='123', sha1=None, len=None)
102
98
    >>> i.add(InventoryDirectory('2325', 'wibble', '123'))
193
189
            if self.file_id in inv:
194
190
                ie = inv[self.file_id]
195
191
                assert ie.file_id == self.file_id
196
 
                if ie.kind != self.kind:
197
 
                    # Can't be a candidate if the kind has changed.
198
 
                    continue
199
192
                if ie.revision in candidates:
200
193
                    # same revision value in two different inventories:
201
194
                    # correct possible inconsistencies:
253
246
 
254
247
    def get_tar_item(self, root, dp, now, tree):
255
248
        """Get a tarfile item and a file stream for its content."""
256
 
        item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
 
249
        item = tarfile.TarInfo(pathjoin(root, dp))
257
250
        # TODO: would be cool to actually set it to the timestamp of the
258
251
        # revision it was last changed
259
252
        item.mtime = now
288
281
        """
289
282
        assert isinstance(name, basestring), name
290
283
        if '/' in name or '\\' in name:
291
 
            raise errors.InvalidEntryName(name=name)
 
284
            raise InvalidEntryName(name=name)
292
285
        self.executable = False
293
286
        self.revision = None
294
287
        self.text_sha1 = None
295
288
        self.text_size = None
296
289
        self.file_id = file_id
297
 
        assert isinstance(file_id, (str, None.__class__)), \
298
 
            'bad type %r for %r' % (type(file_id), file_id)
299
290
        self.name = name
300
291
        self.text_id = text_id
301
292
        self.parent_id = parent_id
302
293
        self.symlink_target = None
303
 
        self.reference_revision = None
304
294
 
305
295
    def kind_character(self):
306
296
        """Return a short kind indicator useful for appending to names."""
321
311
        
322
312
        This is a template method - implement _put_on_disk in subclasses.
323
313
        """
324
 
        fullpath = osutils.pathjoin(dest, dp)
 
314
        fullpath = pathjoin(dest, dp)
325
315
        self._put_on_disk(fullpath, tree)
326
316
        # mutter("  export {%s} kind %s to %s", self.file_id,
327
317
        #         self.kind, fullpath)
335
325
 
336
326
    @staticmethod
337
327
    def versionable_kind(kind):
338
 
        return (kind in ('file', 'directory', 'symlink', 'tree-reference'))
 
328
        return (kind in ('file', 'directory', 'symlink'))
339
329
 
340
330
    def check(self, checker, rev_id, inv, tree):
341
331
        """Check this inventory entry is intact.
386
376
            return 'added'
387
377
        elif new_entry is None:
388
378
            return 'removed'
389
 
        if old_entry.kind != new_entry.kind:
390
 
            return 'modified'
391
379
        text_modified, meta_modified = new_entry.detect_changes(old_entry)
392
380
        if text_modified or meta_modified:
393
381
            modified = True
473
461
                and (self.kind == other.kind)
474
462
                and (self.revision == other.revision)
475
463
                and (self.executable == other.executable)
476
 
                and (self.reference_revision == other.reference_revision)
477
464
                )
478
465
 
479
466
    def __ne__(self, other):
494
481
        # renamed
495
482
        elif previous_ie.name != self.name:
496
483
            compatible = False
497
 
        elif previous_ie.kind != self.kind:
498
 
            compatible = False
499
484
        return compatible
500
485
 
501
486
    def _read_tree_state(self, path, work_tree):
516
501
class RootEntry(InventoryEntry):
517
502
 
518
503
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
519
 
                 'text_id', 'parent_id', 'children', 'executable',
520
 
                 'revision', 'symlink_target', 'reference_revision']
 
504
                 'text_id', 'parent_id', 'children', 'executable', 
 
505
                 'revision', 'symlink_target']
521
506
 
522
507
    def _check(self, checker, rev_id, tree):
523
508
        """See InventoryEntry._check"""
529
514
        self.parent_id = None
530
515
        self.name = u''
531
516
        self.revision = None
532
 
        symbol_versioning.warn('RootEntry is deprecated as of bzr 0.10.'
533
 
                               '  Please use InventoryDirectory instead.',
534
 
                               DeprecationWarning, stacklevel=2)
 
517
        warn('RootEntry is deprecated as of bzr 0.10.  Please use '
 
518
             'InventoryDirectory instead.',
 
519
            DeprecationWarning, stacklevel=2)
535
520
 
536
521
    def __eq__(self, other):
537
522
        if not isinstance(other, RootEntry):
545
530
    """A directory in an inventory."""
546
531
 
547
532
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
548
 
                 'text_id', 'parent_id', 'children', 'executable',
549
 
                 'revision', 'symlink_target', 'reference_revision']
 
533
                 'text_id', 'parent_id', 'children', 'executable', 
 
534
                 'revision', 'symlink_target']
550
535
 
551
536
    def _check(self, checker, rev_id, tree):
552
537
        """See InventoryEntry._check"""
592
577
    """A file in an inventory."""
593
578
 
594
579
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
595
 
                 'text_id', 'parent_id', 'children', 'executable',
596
 
                 'revision', 'symlink_target', 'reference_revision']
 
580
                 'text_id', 'parent_id', 'children', 'executable', 
 
581
                 'revision', 'symlink_target']
597
582
 
598
583
    def _check(self, checker, tree_revision_id, tree):
599
584
        """See InventoryEntry._check"""
660
645
            else:
661
646
                text_diff(to_label, to_text,
662
647
                          from_label, from_text, output_to)
663
 
        except errors.BinaryFile:
 
648
        except BinaryFile:
664
649
            if reverse:
665
650
                label_pair = (to_label, from_label)
666
651
            else:
692
677
 
693
678
    def _put_on_disk(self, fullpath, tree):
694
679
        """See InventoryEntry._put_on_disk."""
695
 
        osutils.pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
 
680
        pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
696
681
        if tree.is_executable(self.file_id):
697
682
            os.chmod(fullpath, 0755)
698
683
 
740
725
    """A file in an inventory."""
741
726
 
742
727
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
743
 
                 'text_id', 'parent_id', 'children', 'executable',
744
 
                 'revision', 'symlink_target', 'reference_revision']
 
728
                 'text_id', 'parent_id', 'children', 'executable', 
 
729
                 'revision', 'symlink_target']
745
730
 
746
731
    def _check(self, checker, rev_id, tree):
747
732
        """See InventoryEntry._check"""
828
813
            self.file_id, file_parents, self.symlink_target)
829
814
 
830
815
 
831
 
class TreeReference(InventoryEntry):
832
 
    
833
 
    kind = 'tree-reference'
834
 
    
835
 
    def __init__(self, file_id, name, parent_id, revision=None,
836
 
                 reference_revision=None):
837
 
        InventoryEntry.__init__(self, file_id, name, parent_id)
838
 
        self.revision = revision
839
 
        self.reference_revision = reference_revision
840
 
 
841
 
    def copy(self):
842
 
        return TreeReference(self.file_id, self.name, self.parent_id,
843
 
                             self.revision, self.reference_revision)
844
 
 
845
 
    def _snapshot_text(self, file_parents, work_tree, commit_builder):
846
 
        commit_builder.modified_reference(self.file_id, file_parents)
847
 
 
848
 
    def _read_tree_state(self, path, work_tree):
849
 
        """Populate fields in the inventory entry from the given tree.
850
 
        """
851
 
        self.reference_revision = work_tree.get_reference_revision(
852
 
            self.file_id, path)
853
 
 
854
 
    def _forget_tree_state(self):
855
 
        self.reference_revision = None 
856
 
 
857
 
 
858
816
class Inventory(object):
859
817
    """Inventory of versioned files in a tree.
860
818
 
891
849
    ['', u'hello.c']
892
850
    >>> inv = Inventory('TREE_ROOT-12345678-12345678')
893
851
    >>> inv.add(InventoryFile('123-123', 'hello.c', ROOT_ID))
894
 
    Traceback (most recent call last):
895
 
    BzrError: parent_id {TREE_ROOT} not in inventory
896
 
    >>> inv.add(InventoryFile('123-123', 'hello.c', 'TREE_ROOT-12345678-12345678'))
897
852
    InventoryFile('123-123', 'hello.c', parent_id='TREE_ROOT-12345678-12345678', sha1=None, len=None)
898
853
    """
899
854
    def __init__(self, root_id=ROOT_ID, revision_id=None):
906
861
        The inventory is created with a default root directory, with
907
862
        an id of None.
908
863
        """
 
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')
909
868
        if root_id is not None:
910
 
            assert root_id.__class__ == str
911
 
            self._set_root(InventoryDirectory(root_id, u'', None))
 
869
            self._set_root(InventoryDirectory(root_id, '', None))
912
870
        else:
913
871
            self.root = None
914
872
            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
915
875
        self.revision_id = revision_id
916
876
 
917
877
    def _set_root(self, ie):
938
898
    def iter_entries(self, from_dir=None):
939
899
        """Return (path, entry) pairs, in order by name."""
940
900
        if from_dir is None:
941
 
            if self.root is None:
942
 
                return
 
901
            assert self.root
943
902
            from_dir = self.root
944
903
            yield '', self.root
945
904
        elif isinstance(from_dir, basestring):
979
938
                # if we finished all children, pop it off the stack
980
939
                stack.pop()
981
940
 
982
 
    def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None):
 
941
    def iter_entries_by_dir(self, from_dir=None):
983
942
        """Iterate over the entries in a directory first order.
984
943
 
985
944
        This returns all entries for a directory before returning
989
948
 
990
949
        :return: This yields (path, entry) pairs
991
950
        """
992
 
        if specific_file_ids:
993
 
            safe = osutils.safe_file_id
994
 
            specific_file_ids = set(safe(fid) for fid in specific_file_ids)
995
951
        # TODO? Perhaps this should return the from_dir so that the root is
996
952
        # yielded? or maybe an option?
997
953
        if from_dir is None:
998
 
            if self.root is None:
999
 
                return
1000
 
            # Optimize a common case
1001
 
            if specific_file_ids is not None and len(specific_file_ids) == 1:
1002
 
                file_id = list(specific_file_ids)[0]
1003
 
                if file_id in self:
1004
 
                    yield self.id2path(file_id), self[file_id]
1005
 
                return 
 
954
            assert self.root
1006
955
            from_dir = self.root
1007
 
            if (specific_file_ids is None or 
1008
 
                self.root.file_id in specific_file_ids):
1009
 
                yield u'', self.root
 
956
            yield '', self.root
1010
957
        elif isinstance(from_dir, basestring):
1011
958
            from_dir = self._byid[from_dir]
1012
 
 
1013
 
        if specific_file_ids is not None:
1014
 
            # TODO: jam 20070302 This could really be done as a loop rather
1015
 
            #       than a bunch of recursive calls.
1016
 
            parents = set()
1017
 
            byid = self._byid
1018
 
            def add_ancestors(file_id):
1019
 
                if file_id not in byid:
1020
 
                    return
1021
 
                parent_id = byid[file_id].parent_id
1022
 
                if parent_id is None:
1023
 
                    return
1024
 
                if parent_id not in parents:
1025
 
                    parents.add(parent_id)
1026
 
                    add_ancestors(parent_id)
1027
 
            for file_id in specific_file_ids:
1028
 
                add_ancestors(file_id)
1029
 
        else:
1030
 
            parents = None
1031
959
            
1032
960
        stack = [(u'', from_dir)]
1033
961
        while stack:
1038
966
 
1039
967
                child_relpath = cur_relpath + child_name
1040
968
 
1041
 
                if (specific_file_ids is None or 
1042
 
                    child_ie.file_id in specific_file_ids):
1043
 
                    yield child_relpath, child_ie
 
969
                yield child_relpath, child_ie
1044
970
 
1045
971
                if child_ie.kind == 'directory':
1046
 
                    if parents is None or child_ie.file_id in parents:
1047
 
                        child_dirs.append((child_relpath+'/', child_ie))
 
972
                    child_dirs.append((child_relpath+'/', child_ie))
1048
973
            stack.extend(reversed(child_dirs))
1049
974
 
1050
975
    def entries(self):
1057
982
            kids = dir_ie.children.items()
1058
983
            kids.sort()
1059
984
            for name, ie in kids:
1060
 
                child_path = osutils.pathjoin(dir_path, name)
 
985
                child_path = pathjoin(dir_path, name)
1061
986
                accum.append((child_path, ie))
1062
987
                if ie.kind == 'directory':
1063
988
                    descend(ie, child_path)
1076
1001
            kids.sort()
1077
1002
 
1078
1003
            for name, child_ie in kids:
1079
 
                child_path = osutils.pathjoin(parent_path, name)
 
1004
                child_path = pathjoin(parent_path, name)
1080
1005
                descend(child_ie, child_path)
1081
1006
        descend(self.root, u'')
1082
1007
        return accum
1092
1017
        >>> '456' in inv
1093
1018
        False
1094
1019
        """
1095
 
        file_id = osutils.safe_file_id(file_id)
1096
1020
        return (file_id in self._byid)
1097
1021
 
1098
1022
    def __getitem__(self, file_id):
1104
1028
        >>> inv['123123'].name
1105
1029
        'hello.c'
1106
1030
        """
1107
 
        file_id = osutils.safe_file_id(file_id)
1108
1031
        try:
1109
1032
            return self._byid[file_id]
1110
1033
        except KeyError:
1111
 
            # really we're passing an inventory, not a tree...
1112
 
            raise errors.NoSuchId(self, file_id)
 
1034
            if file_id is None:
 
1035
                raise BzrError("can't look up file_id None")
 
1036
            else:
 
1037
                raise BzrError("file_id {%s} not in inventory" % file_id)
1113
1038
 
1114
1039
    def get_file_kind(self, file_id):
1115
 
        file_id = osutils.safe_file_id(file_id)
1116
1040
        return self._byid[file_id].kind
1117
1041
 
1118
1042
    def get_child(self, parent_id, filename):
1119
 
        parent_id = osutils.safe_file_id(parent_id)
1120
1043
        return self[parent_id].children.get(filename)
1121
1044
 
1122
 
    def _add_child(self, entry):
1123
 
        """Add an entry to the inventory, without adding it to its parent"""
1124
 
        if entry.file_id in self._byid:
1125
 
            raise BzrError("inventory already contains entry with id {%s}" %
1126
 
                           entry.file_id)
1127
 
        self._byid[entry.file_id] = entry
1128
 
        for child in getattr(entry, 'children', {}).itervalues():
1129
 
            self._add_child(child)
1130
 
        return entry
1131
 
 
1132
1045
    def add(self, entry):
1133
1046
        """Add entry to inventory.
1134
1047
 
1138
1051
        Returns the new entry object.
1139
1052
        """
1140
1053
        if entry.file_id in self._byid:
1141
 
            raise errors.DuplicateFileId(entry.file_id,
1142
 
                                         self._byid[entry.file_id])
 
1054
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
1143
1055
 
1144
1056
        if entry.parent_id is None:
1145
1057
            assert self.root is None and len(self._byid) == 0
1146
 
            self.root = entry
1147
 
        else:
1148
 
            try:
1149
 
                parent = self._byid[entry.parent_id]
1150
 
            except KeyError:
1151
 
                raise BzrError("parent_id {%s} not in inventory" %
1152
 
                               entry.parent_id)
1153
 
 
1154
 
            if entry.name in parent.children:
1155
 
                raise BzrError("%s is already versioned" %
1156
 
                        osutils.pathjoin(self.id2path(parent.file_id),
1157
 
                        entry.name).encode('utf-8'))
1158
 
            parent.children[entry.name] = entry
1159
 
        return self._add_child(entry)
 
1058
            self._set_root(entry)
 
1059
            return entry
 
1060
        if entry.parent_id == ROOT_ID:
 
1061
            assert self.root is not None, self
 
1062
            entry.parent_id = self.root.file_id
 
1063
 
 
1064
        try:
 
1065
            parent = self._byid[entry.parent_id]
 
1066
        except KeyError:
 
1067
            raise BzrError("parent_id {%s} not in inventory" % entry.parent_id)
 
1068
 
 
1069
        if entry.name in parent.children:
 
1070
            raise BzrError("%s is already versioned" %
 
1071
                    pathjoin(self.id2path(parent.file_id), entry.name))
 
1072
 
 
1073
        self._byid[entry.file_id] = entry
 
1074
        parent.children[entry.name] = entry
 
1075
        return entry
1160
1076
 
1161
1077
    def add_path(self, relpath, kind, file_id=None, parent_id=None):
1162
1078
        """Add entry from a path.
1169
1085
 
1170
1086
        if len(parts) == 0:
1171
1087
            if file_id is None:
1172
 
                file_id = generate_ids.gen_root_id()
1173
 
            else:
1174
 
                file_id = osutils.safe_file_id(file_id)
 
1088
                file_id = bzrlib.workingtree.gen_root_id()
1175
1089
            self.root = InventoryDirectory(file_id, '', None)
1176
1090
            self._byid = {self.root.file_id: self.root}
1177
 
            return self.root
 
1091
            return
1178
1092
        else:
1179
1093
            parent_path = parts[:-1]
1180
1094
            parent_id = self.path2id(parent_path)
1181
1095
            if parent_id is None:
1182
 
                raise errors.NotVersionedError(path=parent_path)
 
1096
                raise NotVersionedError(path=parent_path)
1183
1097
        ie = make_entry(kind, parts[-1], parent_id, file_id)
1184
1098
        return self.add(ie)
1185
1099
 
1195
1109
        >>> '123' in inv
1196
1110
        False
1197
1111
        """
1198
 
        file_id = osutils.safe_file_id(file_id)
1199
1112
        ie = self[file_id]
1200
1113
 
1201
1114
        assert ie.parent_id is None or \
1234
1147
 
1235
1148
    def _iter_file_id_parents(self, file_id):
1236
1149
        """Yield the parents of file_id up to the root."""
1237
 
        file_id = osutils.safe_file_id(file_id)
1238
1150
        while file_id is not None:
1239
1151
            try:
1240
1152
                ie = self._byid[file_id]
1241
1153
            except KeyError:
1242
 
                raise errors.NoSuchId(tree=None, file_id=file_id)
 
1154
                raise BzrError("file_id {%s} not found in inventory" % file_id)
1243
1155
            yield ie
1244
1156
            file_id = ie.parent_id
1245
1157
 
1251
1163
        is equal to the depth of the file in the tree, counting the
1252
1164
        root directory as depth 1.
1253
1165
        """
1254
 
        file_id = osutils.safe_file_id(file_id)
1255
1166
        p = []
1256
1167
        for parent in self._iter_file_id_parents(file_id):
1257
1168
            p.insert(0, parent.file_id)
1266
1177
        >>> print i.id2path('foo-id')
1267
1178
        src/foo.c
1268
1179
        """
1269
 
        file_id = osutils.safe_file_id(file_id)
1270
1180
        # get all names, skipping root
1271
1181
        return '/'.join(reversed(
1272
1182
            [parent.name for parent in 
1283
1193
 
1284
1194
        Returns None IFF the path is not found.
1285
1195
        """
1286
 
        if isinstance(name, basestring):
1287
 
            name = osutils.splitpath(name)
 
1196
        if isinstance(name, types.StringTypes):
 
1197
            name = splitpath(name)
1288
1198
 
1289
1199
        # mutter("lookup path %r" % name)
1290
1200
 
1291
1201
        parent = self.root
1292
 
        if parent is None:
1293
 
            return None
1294
1202
        for f in name:
1295
1203
            try:
1296
 
                children = getattr(parent, 'children', None)
1297
 
                if children is None:
1298
 
                    return None
1299
 
                cie = children[f]
 
1204
                cie = parent.children[f]
1300
1205
                assert cie.name == f
1301
1206
                assert cie.parent_id == parent.file_id
1302
1207
                parent = cie
1310
1215
        return bool(self.path2id(names))
1311
1216
 
1312
1217
    def has_id(self, file_id):
1313
 
        file_id = osutils.safe_file_id(file_id)
1314
1218
        return (file_id in self._byid)
1315
1219
 
1316
1220
    def remove_recursive_id(self, file_id):
1318
1222
        
1319
1223
        :param file_id: A file_id to remove.
1320
1224
        """
1321
 
        file_id = osutils.safe_file_id(file_id)
1322
1225
        to_find_delete = [self._byid[file_id]]
1323
1226
        to_delete = []
1324
1227
        while to_find_delete:
1329
1232
        for file_id in reversed(to_delete):
1330
1233
            ie = self[file_id]
1331
1234
            del self._byid[file_id]
1332
 
        if ie.parent_id is not None:
1333
 
            del self[ie.parent_id].children[ie.name]
1334
 
        else:
1335
 
            self.root = None
 
1235
            if ie.parent_id is not None:
 
1236
                del self[ie.parent_id].children[ie.name]
1336
1237
 
1337
1238
    def rename(self, file_id, new_parent_id, new_name):
1338
1239
        """Move a file within the inventory.
1339
1240
 
1340
1241
        This can change either the name, or the parent, or both.
1341
1242
 
1342
 
        This does not move the working file.
1343
 
        """
1344
 
        file_id = osutils.safe_file_id(file_id)
 
1243
        This does not move the working file."""
1345
1244
        if not is_valid_name(new_name):
1346
1245
            raise BzrError("not an acceptable filename: %r" % new_name)
1347
1246
 
1365
1264
        file_ie.name = new_name
1366
1265
        file_ie.parent_id = new_parent_id
1367
1266
 
1368
 
    def is_root(self, file_id):
1369
 
        file_id = osutils.safe_file_id(file_id)
1370
 
        return self.root is not None and file_id == self.root.file_id
1371
 
 
1372
 
 
1373
 
entry_factory = {
1374
 
    'directory': InventoryDirectory,
1375
 
    'file': InventoryFile,
1376
 
    'symlink': InventoryLink,
1377
 
    'tree-reference': TreeReference
1378
 
}
1379
1267
 
1380
1268
def make_entry(kind, name, parent_id, file_id=None):
1381
1269
    """Create an inventory entry.
1386
1274
    :param file_id: the file_id to use. if None, one will be created.
1387
1275
    """
1388
1276
    if file_id is None:
1389
 
        file_id = generate_ids.gen_file_id(name)
1390
 
    else:
1391
 
        file_id = osutils.safe_file_id(file_id)
 
1277
        file_id = bzrlib.workingtree.gen_file_id(name)
1392
1278
 
1393
 
    #------- This has been copied to bzrlib.dirstate.DirState.add, please
1394
 
    # keep them synchronised.
1395
 
    # we dont import normalized_filename directly because we want to be
1396
 
    # able to change the implementation at runtime for tests.
1397
1279
    norm_name, can_access = osutils.normalized_filename(name)
1398
1280
    if norm_name != name:
1399
1281
        if can_access:
1403
1285
            #       if the error was raised with the full path
1404
1286
            raise errors.InvalidNormalization(name)
1405
1287
 
1406
 
    try:
1407
 
        factory = entry_factory[kind]
1408
 
    except KeyError:
 
1288
    if kind == 'directory':
 
1289
        return InventoryDirectory(file_id, name, parent_id)
 
1290
    elif kind == 'file':
 
1291
        return InventoryFile(file_id, name, parent_id)
 
1292
    elif kind == 'symlink':
 
1293
        return InventoryLink(file_id, name, parent_id)
 
1294
    else:
1409
1295
        raise BzrError("unknown kind %r" % kind)
1410
 
    return factory(file_id, name, parent_id)
1411
1296
 
1412
1297
 
1413
1298
_NAME_RE = None