~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Aaron Bentley
  • Date: 2007-01-26 04:00:12 UTC
  • mfrom: (2245 +trunk)
  • mto: (2255.6.1 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: aaron.bentley@utoronto.ca-20070126040012-j80k7qhvj80dyp9j
merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
75
75
 
76
76
from bzrlib import symbol_versioning
77
77
from bzrlib.decorators import needs_read_lock, needs_write_lock
78
 
from bzrlib.errors import (BzrCheckError,
79
 
                           BzrError,
80
 
                           ConflictFormatError,
81
 
                           WeaveRevisionNotPresent,
82
 
                           NotBranchError,
83
 
                           NoSuchFile,
84
 
                           NotVersionedError,
85
 
                           MergeModifiedFormatError,
86
 
                           UnsupportedOperation,
87
 
                           )
88
78
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
89
79
from bzrlib.lockable_files import LockableFiles, TransportLock
90
80
from bzrlib.lockdir import LockDir
94
84
    compact_date,
95
85
    file_kind,
96
86
    isdir,
 
87
    normpath,
97
88
    pathjoin,
 
89
    rand_chars,
 
90
    realpath,
98
91
    safe_unicode,
99
92
    splitpath,
100
 
    rand_chars,
101
 
    normpath,
102
 
    realpath,
103
93
    supports_executable,
104
94
    )
105
95
from bzrlib.trace import mutter, note
242
232
        mutter("opening working tree %r", basedir)
243
233
        if deprecated_passed(branch):
244
234
            if not _internal:
245
 
                warnings.warn("WorkingTree(..., branch=XXX) is deprecated as of bzr 0.8."
246
 
                     " Please use bzrdir.open_workingtree() or"
 
235
                warnings.warn("WorkingTree(..., branch=XXX) is deprecated"
 
236
                     " as of bzr 0.8. Please use bzrdir.open_workingtree() or"
247
237
                     " WorkingTree.open().",
248
238
                     DeprecationWarning,
249
239
                     stacklevel=2
268
258
        # if needed, or, when the cache sees a change, append it to the hash
269
259
        # cache file, and have the parser take the most recent entry for a
270
260
        # given path only.
271
 
        cache_filename = self.bzrdir.get_workingtree_transport(None).local_abspath('stat-cache')
 
261
        wt_trans = self.bzrdir.get_workingtree_transport(None)
 
262
        cache_filename = wt_trans.local_abspath('stat-cache')
272
263
        self._hashcache = hashcache.HashCache(basedir, cache_filename,
273
264
                                              self._control_files._file_mode)
274
265
        hc = self._hashcache
404
395
                if inv is not None and inv.revision_id == revision_id:
405
396
                    return bzrlib.revisiontree.RevisionTree(
406
397
                        self.branch.repository, inv, revision_id)
407
 
            except (NoSuchFile, errors.BadInventoryFormat):
 
398
            except (errors.NoSuchFile, errors.BadInventoryFormat):
408
399
                pass
409
400
        # No cached copy available, retrieve from the repository.
410
401
        # FIXME? RBC 20060403 should we cache the inventory locally
522
513
            parents = [last_rev]
523
514
        try:
524
515
            merges_file = self._control_files.get_utf8('pending-merges')
525
 
        except NoSuchFile:
 
516
        except errors.NoSuchFile:
526
517
            pass
527
518
        else:
528
519
            for l in merges_file.readlines():
633
624
 
634
625
    def add_reference(self, sub_tree):
635
626
        """Add a TreeReference to the tree, pointing at sub_tree"""
636
 
        raise UnsupportedOperation(self.add_reference, self)
 
627
        raise errors.UnsupportedOperation(self.add_reference, self)
637
628
 
638
629
    @needs_tree_write_lock
639
630
    def _gather_kinds(self, files, kinds):
645
636
                    kinds[pos] = file_kind(fullpath)
646
637
                except OSError, e:
647
638
                    if e.errno == errno.ENOENT:
648
 
                        raise NoSuchFile(fullpath)
 
639
                        raise errors.NoSuchFile(fullpath)
649
640
 
650
641
    @needs_write_lock
651
642
    def add_parent_tree_id(self, revision_id, allow_leftmost_as_ghost=False):
660
651
        :param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
661
652
        """
662
653
        parents = self.get_parent_ids() + [revision_id]
663
 
        self.set_parent_ids(parents,
664
 
            allow_leftmost_as_ghost=len(parents) > 1 or allow_leftmost_as_ghost)
 
654
        self.set_parent_ids(parents, allow_leftmost_as_ghost=len(parents) > 1
 
655
            or allow_leftmost_as_ghost)
665
656
 
666
657
    @needs_tree_write_lock
667
658
    def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
801
792
        """Merge from a branch into this working tree.
802
793
 
803
794
        :param branch: The branch to merge from.
804
 
        :param to_revision: If non-None, the merge will merge to to_revision, but 
805
 
            not beyond it. to_revision does not need to be in the history of
806
 
            the branch when it is supplied. If None, to_revision defaults to
 
795
        :param to_revision: If non-None, the merge will merge to to_revision,
 
796
            but not beyond it. to_revision does not need to be in the history
 
797
            of the branch when it is supplied. If None, to_revision defaults to
807
798
            branch.last_revision().
808
799
        """
809
800
        from bzrlib.merge import Merger, Merge3Merger
938
929
    def merge_modified(self):
939
930
        try:
940
931
            hashfile = self._control_files.get('merge-hashes')
941
 
        except NoSuchFile:
 
932
        except errors.NoSuchFile:
942
933
            return {}
943
934
        merge_hashes = {}
944
935
        try:
945
936
            if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
946
 
                raise MergeModifiedFormatError()
 
937
                raise errors.MergeModifiedFormatError()
947
938
        except StopIteration:
948
 
            raise MergeModifiedFormatError()
 
939
            raise errors.MergeModifiedFormatError()
949
940
        for s in RioReader(hashfile):
950
941
            file_id = s.get("file_id")
951
942
            if file_id not in self.inventory:
1075
1066
 
1076
1067
                if f_ie:
1077
1068
                    if f_ie.kind != fk:
1078
 
                        raise BzrCheckError("file %r entered as kind %r id %r, "
1079
 
                                            "now of kind %r"
1080
 
                                            % (fap, f_ie.kind, f_ie.file_id, fk))
 
1069
                        raise errors.BzrCheckError(
 
1070
                            "file %r entered as kind %r id %r, now of kind %r"
 
1071
                            % (fap, f_ie.kind, f_ie.file_id, fk))
1081
1072
 
1082
1073
                # make a last minute entry
1083
1074
                if f_ie:
1097
1088
                new_children.sort()
1098
1089
                new_children = collections.deque(new_children)
1099
1090
                stack.append((f_ie.file_id, fp, fap, new_children))
1100
 
                # Break out of inner loop, so that we start outer loop with child
 
1091
                # Break out of inner loop,
 
1092
                # so that we start outer loop with child
1101
1093
                break
1102
1094
            else:
1103
1095
                # if we finished all children, pop it off the stack
1104
1096
                stack.pop()
1105
1097
 
1106
1098
    @needs_tree_write_lock
1107
 
    def move(self, from_paths, to_name):
 
1099
    def move(self, from_paths, to_dir=None, after=False, **kwargs):
1108
1100
        """Rename files.
1109
1101
 
1110
 
        to_name must exist in the inventory.
 
1102
        to_dir must exist in the inventory.
1111
1103
 
1112
 
        If to_name exists and is a directory, the files are moved into
 
1104
        If to_dir exists and is a directory, the files are moved into
1113
1105
        it, keeping their old names.  
1114
1106
 
1115
 
        Note that to_name is only the last component of the new name;
 
1107
        Note that to_dir is only the last component of the new name;
1116
1108
        this doesn't change the directory.
1117
1109
 
 
1110
        For each entry in from_paths the move mode will be determined
 
1111
        independently.
 
1112
 
 
1113
        The first mode moves the file in the filesystem and updates the
 
1114
        inventory. The second mode only updates the inventory without
 
1115
        touching the file on the filesystem. This is the new mode introduced
 
1116
        in version 0.15.
 
1117
 
 
1118
        move uses the second mode if 'after == True' and the target is not
 
1119
        versioned but present in the working tree.
 
1120
 
 
1121
        move uses the second mode if 'after == False' and the source is
 
1122
        versioned but no longer in the working tree, and the target is not
 
1123
        versioned but present in the working tree.
 
1124
 
 
1125
        move uses the first mode if 'after == False' and the source is
 
1126
        versioned and present in the working tree, and the target is not
 
1127
        versioned and not present in the working tree.
 
1128
 
 
1129
        Everything else results in an error.
 
1130
 
1118
1131
        This returns a list of (from_path, to_path) pairs for each
1119
1132
        entry that is moved.
1120
1133
        """
1121
 
        result = []
1122
 
        ## TODO: Option to move IDs only
 
1134
        rename_entries = []
 
1135
        rename_tuples = []
 
1136
 
 
1137
        # check for deprecated use of signature
 
1138
        if to_dir is None:
 
1139
            to_dir = kwargs.get('to_name', None)
 
1140
            if to_dir is None:
 
1141
                raise TypeError('You must supply a target directory')
 
1142
            else:
 
1143
                symbol_versioning.warn('The parameter to_name was deprecated'
 
1144
                                       ' in version 0.13. Use to_dir instead',
 
1145
                                       DeprecationWarning)
 
1146
 
 
1147
        # check destination directory
1123
1148
        assert not isinstance(from_paths, basestring)
1124
1149
        inv = self.inventory
1125
 
        to_abs = self.abspath(to_name)
 
1150
        to_abs = self.abspath(to_dir)
1126
1151
        if not isdir(to_abs):
1127
 
            raise BzrError("destination %r is not a directory" % to_abs)
1128
 
        if not self.has_filename(to_name):
1129
 
            raise BzrError("destination %r not in working directory" % to_abs)
1130
 
        to_dir_id = inv.path2id(to_name)
1131
 
        if to_dir_id is None and to_name != '':
1132
 
            raise BzrError("destination %r is not a versioned directory" % to_name)
 
1152
            raise errors.BzrMoveFailedError('',to_dir,
 
1153
                errors.NotADirectory(to_abs))
 
1154
        if not self.has_filename(to_dir):
 
1155
            raise errors.BzrMoveFailedError('',to_dir,
 
1156
                errors.NotInWorkingDirectory(to_dir))
 
1157
        to_dir_id = inv.path2id(to_dir)
 
1158
        if to_dir_id is None:
 
1159
            raise errors.BzrMoveFailedError('',to_dir,
 
1160
                errors.NotVersionedError(path=str(to_dir)))
 
1161
 
1133
1162
        to_dir_ie = inv[to_dir_id]
1134
1163
        if to_dir_ie.kind != 'directory':
1135
 
            raise BzrError("destination %r is not a directory" % to_abs)
1136
 
 
1137
 
        to_idpath = inv.get_idpath(to_dir_id)
1138
 
 
1139
 
        for f in from_paths:
1140
 
            if not self.has_filename(f):
1141
 
                raise BzrError("%r does not exist in working tree" % f)
1142
 
            f_id = inv.path2id(f)
1143
 
            if f_id is None:
1144
 
                raise BzrError("%r is not versioned" % f)
1145
 
            name_tail = splitpath(f)[-1]
1146
 
            dest_path = pathjoin(to_name, name_tail)
1147
 
            if self.has_filename(dest_path):
1148
 
                raise BzrError("destination %r already exists" % dest_path)
1149
 
            if f_id in to_idpath:
1150
 
                raise BzrError("can't move %r to a subdirectory of itself" % f)
1151
 
 
1152
 
        # OK, so there's a race here, it's possible that someone will
1153
 
        # create a file in this interval and then the rename might be
1154
 
        # left half-done.  But we should have caught most problems.
1155
 
        orig_inv = deepcopy(self.inventory)
 
1164
            raise errors.BzrMoveFailedError('',to_dir,
 
1165
                errors.NotADirectory(to_abs))
 
1166
 
 
1167
        # create rename entries and tuples
 
1168
        for from_rel in from_paths:
 
1169
            from_tail = splitpath(from_rel)[-1]
 
1170
            from_id = inv.path2id(from_rel)
 
1171
            if from_id is None:
 
1172
                raise errors.BzrMoveFailedError(from_rel,to_dir,
 
1173
                    errors.NotVersionedError(path=str(from_rel)))
 
1174
 
 
1175
            from_entry = inv[from_id]
 
1176
            from_parent_id = from_entry.parent_id
 
1177
            to_rel = pathjoin(to_dir, from_tail)
 
1178
            rename_entry = WorkingTree._RenameEntry(from_rel=from_rel,
 
1179
                                         from_id=from_id,
 
1180
                                         from_tail=from_tail,
 
1181
                                         from_parent_id=from_parent_id,
 
1182
                                         to_rel=to_rel, to_tail=from_tail,
 
1183
                                         to_parent_id=to_dir_id)
 
1184
            rename_entries.append(rename_entry)
 
1185
            rename_tuples.append((from_rel, to_rel))
 
1186
 
 
1187
        # determine which move mode to use. checks also for movability
 
1188
        rename_entries = self._determine_mv_mode(rename_entries, after)
 
1189
 
1156
1190
        original_modified = self._inventory_is_modified
1157
1191
        try:
1158
1192
            if len(from_paths):
1159
1193
                self._inventory_is_modified = True
1160
 
            for f in from_paths:
1161
 
                name_tail = splitpath(f)[-1]
1162
 
                dest_path = pathjoin(to_name, name_tail)
1163
 
                result.append((f, dest_path))
1164
 
                inv.rename(inv.path2id(f), to_dir_id, name_tail)
1165
 
                try:
1166
 
                    osutils.rename(self.abspath(f), self.abspath(dest_path))
1167
 
                except OSError, e:
1168
 
                    raise BzrError("failed to rename %r to %r: %s" %
1169
 
                                   (f, dest_path, e[1]))
 
1194
            self._move(rename_entries)
1170
1195
        except:
1171
1196
            # restore the inventory on error
1172
 
            self._set_inventory(orig_inv, dirty=original_modified)
 
1197
            self._inventory_is_modified = original_modified
1173
1198
            raise
1174
1199
        self._write_inventory(inv)
1175
 
        return result
 
1200
        return rename_tuples
 
1201
 
 
1202
    def _determine_mv_mode(self, rename_entries, after=False):
 
1203
        """Determines for each from-to pair if both inventory and working tree
 
1204
        or only the inventory has to be changed.
 
1205
 
 
1206
        Also does basic plausability tests.
 
1207
        """
 
1208
        inv = self.inventory
 
1209
 
 
1210
        for rename_entry in rename_entries:
 
1211
            # store to local variables for easier reference
 
1212
            from_rel = rename_entry.from_rel
 
1213
            from_id = rename_entry.from_id
 
1214
            to_rel = rename_entry.to_rel
 
1215
            to_id = inv.path2id(to_rel)
 
1216
            only_change_inv = False
 
1217
 
 
1218
            # check the inventory for source and destination
 
1219
            if from_id is None:
 
1220
                raise errors.BzrMoveFailedError(from_rel,to_rel,
 
1221
                    errors.NotVersionedError(path=str(from_rel)))
 
1222
            if to_id is not None:
 
1223
                raise errors.BzrMoveFailedError(from_rel,to_rel,
 
1224
                    errors.AlreadyVersionedError(path=str(to_rel)))
 
1225
 
 
1226
            # try to determine the mode for rename (only change inv or change
 
1227
            # inv and file system)
 
1228
            if after:
 
1229
                if not self.has_filename(to_rel):
 
1230
                    raise errors.BzrMoveFailedError(from_id,to_rel,
 
1231
                        errors.NoSuchFile(path=str(to_rel),
 
1232
                        extra="New file has not been created yet"))
 
1233
                only_change_inv = True
 
1234
            elif not self.has_filename(from_rel) and self.has_filename(to_rel):
 
1235
                only_change_inv = True
 
1236
            elif self.has_filename(from_rel) and not self.has_filename(to_rel):
 
1237
                only_change_inv = False
 
1238
            else:
 
1239
                # something is wrong, so lets determine what exactly
 
1240
                if not self.has_filename(from_rel) and \
 
1241
                   not self.has_filename(to_rel):
 
1242
                    raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1243
                        errors.PathsDoNotExist(paths=(str(from_rel),
 
1244
                        str(to_rel))))
 
1245
                else:
 
1246
                    raise errors.RenameFailedFilesExist(from_rel, to_rel,
 
1247
                        extra="(Use --after to update the Bazaar id)")
 
1248
            rename_entry.only_change_inv = only_change_inv
 
1249
        return rename_entries
 
1250
 
 
1251
    def _move(self, rename_entries):
 
1252
        """Moves a list of files.
 
1253
 
 
1254
        Depending on the value of the flag 'only_change_inv', the
 
1255
        file will be moved on the file system or not.
 
1256
        """
 
1257
        inv = self.inventory
 
1258
        moved = []
 
1259
 
 
1260
        for entry in rename_entries:
 
1261
            try:
 
1262
                self._move_entry(entry)
 
1263
            except:
 
1264
                self._rollback_move(moved)
 
1265
                raise
 
1266
            moved.append(entry)
 
1267
 
 
1268
    def _rollback_move(self, moved):
 
1269
        """Try to rollback a previous move in case of an filesystem error."""
 
1270
        inv = self.inventory
 
1271
        for entry in moved:
 
1272
            try:
 
1273
                self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
 
1274
                    entry.to_tail, entry.to_parent_id, entry.from_rel,
 
1275
                    entry.from_tail, entry.from_parent_id,
 
1276
                    entry.only_change_inv))
 
1277
            except errors.BzrMoveFailedError, e:
 
1278
                raise errors.BzrMoveFailedError( '', '', "Rollback failed."
 
1279
                        " The working tree is in an inconsistent state."
 
1280
                        " Please consider doing a 'bzr revert'."
 
1281
                        " Error message is: %s" % e)
 
1282
 
 
1283
    def _move_entry(self, entry):
 
1284
        inv = self.inventory
 
1285
        from_rel_abs = self.abspath(entry.from_rel)
 
1286
        to_rel_abs = self.abspath(entry.to_rel)
 
1287
        if from_rel_abs == to_rel_abs:
 
1288
            raise errors.BzrMoveFailedError(entry.from_rel, entry.to_rel,
 
1289
                "Source and target are identical.")
 
1290
 
 
1291
        if not entry.only_change_inv:
 
1292
            try:
 
1293
                osutils.rename(from_rel_abs, to_rel_abs)
 
1294
            except OSError, e:
 
1295
                raise errors.BzrMoveFailedError(entry.from_rel,
 
1296
                    entry.to_rel, e[1])
 
1297
        inv.rename(entry.from_id, entry.to_parent_id, entry.to_tail)
1176
1298
 
1177
1299
    @needs_tree_write_lock
1178
 
    def rename_one(self, from_rel, to_rel):
 
1300
    def rename_one(self, from_rel, to_rel, after=False):
1179
1301
        """Rename one file.
1180
1302
 
1181
1303
        This can change the directory or the filename or both.
 
1304
 
 
1305
        rename_one has several 'modes' to work. First, it can rename a physical
 
1306
        file and change the file_id. That is the normal mode. Second, it can
 
1307
        only change the file_id without touching any physical file. This is
 
1308
        the new mode introduced in version 0.15.
 
1309
 
 
1310
        rename_one uses the second mode if 'after == True' and 'to_rel' is not
 
1311
        versioned but present in the working tree.
 
1312
 
 
1313
        rename_one uses the second mode if 'after == False' and 'from_rel' is
 
1314
        versioned but no longer in the working tree, and 'to_rel' is not
 
1315
        versioned but present in the working tree.
 
1316
 
 
1317
        rename_one uses the first mode if 'after == False' and 'from_rel' is
 
1318
        versioned and present in the working tree, and 'to_rel' is not
 
1319
        versioned and not present in the working tree.
 
1320
 
 
1321
        Everything else results in an error.
1182
1322
        """
1183
1323
        inv = self.inventory
1184
 
        if not self.has_filename(from_rel):
1185
 
            raise BzrError("can't rename: old working file %r does not exist" % from_rel)
1186
 
        if self.has_filename(to_rel):
1187
 
            raise BzrError("can't rename: new working file %r already exists" % to_rel)
1188
 
 
1189
 
        file_id = inv.path2id(from_rel)
1190
 
        if file_id is None:
1191
 
            raise BzrError("can't rename: old name %r is not versioned" % from_rel)
1192
 
 
1193
 
        entry = inv[file_id]
1194
 
        from_parent = entry.parent_id
1195
 
        from_name = entry.name
1196
 
        
1197
 
        if inv.path2id(to_rel):
1198
 
            raise BzrError("can't rename: new name %r is already versioned" % to_rel)
1199
 
 
 
1324
        rename_entries = []
 
1325
 
 
1326
        # create rename entries and tuples
 
1327
        from_tail = splitpath(from_rel)[-1]
 
1328
        from_id = inv.path2id(from_rel)
 
1329
        if from_id is None:
 
1330
            raise errors.BzrRenameFailedError(from_rel,to_rel,
 
1331
                errors.NotVersionedError(path=str(from_rel)))
 
1332
        from_entry = inv[from_id]
 
1333
        from_parent_id = from_entry.parent_id
1200
1334
        to_dir, to_tail = os.path.split(to_rel)
1201
1335
        to_dir_id = inv.path2id(to_dir)
1202
 
        if to_dir_id is None and to_dir != '':
1203
 
            raise BzrError("can't determine destination directory id for %r" % to_dir)
1204
 
 
1205
 
        mutter("rename_one:")
1206
 
        mutter("  file_id    {%s}" % file_id)
1207
 
        mutter("  from_rel   %r" % from_rel)
1208
 
        mutter("  to_rel     %r" % to_rel)
1209
 
        mutter("  to_dir     %r" % to_dir)
1210
 
        mutter("  to_dir_id  {%s}" % to_dir_id)
1211
 
 
1212
 
        inv.rename(file_id, to_dir_id, to_tail)
1213
 
 
1214
 
        from_abs = self.abspath(from_rel)
1215
 
        to_abs = self.abspath(to_rel)
1216
 
        try:
1217
 
            osutils.rename(from_abs, to_abs)
1218
 
        except OSError, e:
1219
 
            inv.rename(file_id, from_parent, from_name)
1220
 
            raise BzrError("failed to rename %r to %r: %s"
1221
 
                    % (from_abs, to_abs, e[1]))
 
1336
        rename_entry = WorkingTree._RenameEntry(from_rel=from_rel,
 
1337
                                     from_id=from_id,
 
1338
                                     from_tail=from_tail,
 
1339
                                     from_parent_id=from_parent_id,
 
1340
                                     to_rel=to_rel, to_tail=to_tail,
 
1341
                                     to_parent_id=to_dir_id)
 
1342
        rename_entries.append(rename_entry)
 
1343
 
 
1344
        # determine which move mode to use. checks also for movability
 
1345
        rename_entries = self._determine_mv_mode(rename_entries, after)
 
1346
 
 
1347
        # check if the target changed directory and if the target directory is
 
1348
        # versioned
 
1349
        if to_dir_id is None:
 
1350
            raise errors.BzrMoveFailedError(from_rel,to_rel,
 
1351
                errors.NotVersionedError(path=str(to_dir)))
 
1352
 
 
1353
        # all checks done. now we can continue with our actual work
 
1354
        mutter('rename_one:\n'
 
1355
               '  from_id   {%s}\n'
 
1356
               '  from_rel: %r\n'
 
1357
               '  to_rel:   %r\n'
 
1358
               '  to_dir    %r\n'
 
1359
               '  to_dir_id {%s}\n',
 
1360
               from_id, from_rel, to_rel, to_dir, to_dir_id)
 
1361
 
 
1362
        self._move(rename_entries)
1222
1363
        self._write_inventory(inv)
1223
1364
 
 
1365
    class _RenameEntry(object):
 
1366
        def __init__(self, from_rel, from_id, from_tail, from_parent_id,
 
1367
                     to_rel, to_tail, to_parent_id, only_change_inv=False):
 
1368
            self.from_rel = from_rel
 
1369
            self.from_id = from_id
 
1370
            self.from_tail = from_tail
 
1371
            self.from_parent_id = from_parent_id
 
1372
            self.to_rel = to_rel
 
1373
            self.to_tail = to_tail
 
1374
            self.to_parent_id = to_parent_id
 
1375
            self.only_change_inv = only_change_inv
 
1376
 
1224
1377
    @needs_read_lock
1225
1378
    def unknowns(self):
1226
1379
        """Return all unknown files.
1603
1756
            if not fid:
1604
1757
                # TODO: Perhaps make this just a warning, and continue?
1605
1758
                # This tends to happen when 
1606
 
                raise NotVersionedError(path=f)
 
1759
                raise errors.NotVersionedError(path=f)
1607
1760
            if verbose:
1608
1761
                # having remove it, it must be either ignored or unknown
1609
1762
                if self.is_ignored(f):
1652
1805
            elif kind == 'symlink':
1653
1806
                inv.add(InventoryLink(file_id, name, parent))
1654
1807
            else:
1655
 
                raise BzrError("unknown kind %r" % kind)
 
1808
                raise errors.BzrError("unknown kind %r" % kind)
1656
1809
        self._write_inventory(inv)
1657
1810
 
1658
1811
    @needs_tree_write_lock
1833
1986
        self.flush()
1834
1987
 
1835
1988
    def set_conflicts(self, arg):
1836
 
        raise UnsupportedOperation(self.set_conflicts, self)
 
1989
        raise errors.UnsupportedOperation(self.set_conflicts, self)
1837
1990
 
1838
1991
    def add_conflicts(self, arg):
1839
 
        raise UnsupportedOperation(self.add_conflicts, self)
 
1992
        raise errors.UnsupportedOperation(self.add_conflicts, self)
1840
1993
 
1841
1994
    @needs_read_lock
1842
1995
    def conflicts(self):
1916
2069
        """See Mutable.last_revision."""
1917
2070
        try:
1918
2071
            return self._control_files.get_utf8('last-revision').read()
1919
 
        except NoSuchFile:
 
2072
        except errors.NoSuchFile:
1920
2073
            return None
1921
2074
 
1922
2075
    def _change_last_revision(self, revision_id):
1947
2100
    def conflicts(self):
1948
2101
        try:
1949
2102
            confile = self._control_files.get('conflicts')
1950
 
        except NoSuchFile:
 
2103
        except errors.NoSuchFile:
1951
2104
            return _mod_conflicts.ConflictList()
1952
2105
        try:
1953
2106
            if confile.next() != CONFLICT_HEADER_1 + '\n':
1954
 
                raise ConflictFormatError()
 
2107
                raise errors.ConflictFormatError()
1955
2108
        except StopIteration:
1956
 
            raise ConflictFormatError()
 
2109
            raise errors.ConflictFormatError()
1957
2110
        return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
1958
2111
 
1959
2112
    def unlock(self):
2064
2217
            transport = a_bzrdir.get_workingtree_transport(None)
2065
2218
            format_string = transport.get("format").read()
2066
2219
            return klass._formats[format_string]
2067
 
        except NoSuchFile:
 
2220
        except errors.NoSuchFile:
2068
2221
            raise errors.NoWorkingTree(base=transport.base)
2069
2222
        except KeyError:
2070
2223
            raise errors.UnknownFormatError(format=format_string)