73
73
from bzrlib import symbol_versioning
74
74
from bzrlib.decorators import needs_read_lock, needs_write_lock
75
from bzrlib.errors import (AlreadyVersionedError,
82
NotInWorkingDirectory,
85
MergeModifiedFormatError,
87
WeaveRevisionNotPresent,
89
76
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID
90
77
from bzrlib.lockable_files import LockableFiles, TransportLock
91
78
from bzrlib.lockdir import LockDir
243
230
mutter("opening working tree %r", basedir)
244
231
if deprecated_passed(branch):
245
232
if not _internal:
246
warnings.warn("WorkingTree(..., branch=XXX) is deprecated as of bzr 0.8."
247
" Please use bzrdir.open_workingtree() or"
233
warnings.warn("WorkingTree(..., branch=XXX) is deprecated"
234
" as of bzr 0.8. Please use bzrdir.open_workingtree() or"
248
235
" WorkingTree.open().",
249
236
DeprecationWarning,
269
256
# if needed, or, when the cache sees a change, append it to the hash
270
257
# cache file, and have the parser take the most recent entry for a
271
258
# given path only.
272
cache_filename = self.bzrdir.get_workingtree_transport(None).local_abspath('stat-cache')
259
cache_filename = self.bzrdir.get_workingtree_transport(None) \
260
.local_abspath('stat-cache')
273
261
self._hashcache = hashcache.HashCache(basedir, cache_filename,
274
262
self._control_files._file_mode)
275
263
hc = self._hashcache
399
387
if inv is not None and inv.revision_id == revision_id:
400
388
return bzrlib.revisiontree.RevisionTree(
401
389
self.branch.repository, inv, revision_id)
402
except (NoSuchFile, errors.BadInventoryFormat):
390
except (errors.NoSuchFile, errors.BadInventoryFormat):
404
392
# No cached copy available, retrieve from the repository.
405
393
# FIXME? RBC 20060403 should we cache the inventory locally
636
624
kinds[pos] = file_kind(fullpath)
637
625
except OSError, e:
638
626
if e.errno == errno.ENOENT:
639
raise NoSuchFile(fullpath)
627
raise errors.NoSuchFile(fullpath)
641
629
@needs_write_lock
642
630
def add_parent_tree_id(self, revision_id, allow_leftmost_as_ghost=False):
651
639
:param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
653
641
parents = self.get_parent_ids() + [revision_id]
654
self.set_parent_ids(parents,
655
allow_leftmost_as_ghost=len(parents) > 1 or allow_leftmost_as_ghost)
642
self.set_parent_ids(parents, allow_leftmost_as_ghost=len(parents) > 1
643
or allow_leftmost_as_ghost)
657
645
@needs_tree_write_lock
658
646
def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
792
780
"""Merge from a branch into this working tree.
794
782
:param branch: The branch to merge from.
795
:param to_revision: If non-None, the merge will merge to to_revision, but
796
not beyond it. to_revision does not need to be in the history of
797
the branch when it is supplied. If None, to_revision defaults to
783
:param to_revision: If non-None, the merge will merge to to_revision,
784
but not beyond it. to_revision does not need to be in the history
785
of the branch when it is supplied. If None, to_revision defaults to
798
786
branch.last_revision().
800
788
from bzrlib.merge import Merger, Merge3Merger
834
822
def merge_modified(self):
836
824
hashfile = self._control_files.get('merge-hashes')
825
except errors.NoSuchFile:
839
827
merge_hashes = {}
841
829
if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
842
raise MergeModifiedFormatError()
830
raise errors.MergeModifiedFormatError()
843
831
except StopIteration:
844
raise MergeModifiedFormatError()
832
raise errors.MergeModifiedFormatError()
845
833
for s in RioReader(hashfile):
846
834
file_id = s.get("file_id")
847
835
if file_id not in self.inventory:
967
955
if f_ie.kind != fk:
968
raise BzrCheckError("file %r entered as kind %r id %r, "
970
% (fap, f_ie.kind, f_ie.file_id, fk))
956
raise errors.BzrCheckError(
957
"file %r entered as kind %r id %r, now of kind %r"
958
% (fap, f_ie.kind, f_ie.file_id, fk))
972
960
# make a last minute entry
987
975
new_children.sort()
988
976
new_children = collections.deque(new_children)
989
977
stack.append((f_ie.file_id, fp, fap, new_children))
990
# Break out of inner loop, so that we start outer loop with child
978
# Break out of inner loop,
979
# so that we start outer loop with child
993
982
# if we finished all children, pop it off the stack
1047
1036
inv = self.inventory
1048
1037
to_abs = self.abspath(to_dir)
1049
1038
if not isdir(to_abs):
1050
raise NotADirectory(to_abs, extra="Invalid move destination")
1039
raise errors.NotADirectory(to_abs,
1040
extra="Invalid move destination")
1051
1041
if not self.has_filename(to_dir):
1052
raise NotInWorkingDirectory(to_dir, extra=
1053
"(Invalid move destination)")
1042
raise errors.NotInWorkingDirectory(to_dir,
1043
extra="(Invalid move destination)")
1054
1044
to_dir_id = inv.path2id(to_dir)
1055
1045
if to_dir_id is None:
1056
raise NotVersionedError(path=str(to_dir),
1057
contextInfo="Invalid move destination")
1046
raise errors.NotVersionedError(path=str(to_dir),
1047
context_info="Invalid move destination")
1059
1049
to_dir_ie = inv[to_dir_id]
1060
1050
if to_dir_ie.kind != 'directory':
1061
raise NotADirectory(to_abs, extra="Invalid move destination")
1051
raise errors.NotADirectory(to_abs,
1052
extra="Invalid move destination")
1063
1054
# create rename entries and tuples
1064
1055
for from_rel in from_paths:
1065
1056
from_tail = splitpath(from_rel)[-1]
1066
1057
from_id = inv.path2id(from_rel)
1067
1058
if from_id is None:
1068
raise NotVersionedError(path=str(from_rel),
1069
contextInfo="Invalid source")
1059
raise errors.NotVersionedError(path=str(from_rel),
1060
context_info="Invalid source")
1071
1062
from_entry = inv[from_id]
1072
1063
from_parent_id = from_entry.parent_id
1115
1106
# check the inventory for source and destination
1116
1107
if from_id is None:
1117
raise NotVersionedError(path=str(from_rel),
1118
contextInfo="Invalid move source")
1108
raise errors.NotVersionedError(path=str(from_rel),
1109
context_info="Could not move file")
1119
1110
if to_id is not None:
1120
raise AlreadyVersionedError(path=str(to_rel),
1121
contextInfo="Invalid move destination")
1111
raise errors.AlreadyVersionedError(path=str(to_rel),
1112
context_info="Could not move file")
1123
1114
# try to determine the mode for rename (only change inv or change
1124
1115
# inv and file system)
1126
1117
if not self.has_filename(to_rel):
1127
raise NoSuchFile(path=str(to_rel),
1118
raise errors.NoSuchFile(path=str(to_rel),
1128
1119
extra="New file has not been created yet")
1129
1120
only_change_inv = True
1130
1121
elif not self.has_filename(from_rel) and self.has_filename(to_rel):
1136
1127
if not self.has_filename(from_rel) and \
1137
1128
not self.has_filename(to_rel):
1138
1129
raise PathsDoNotExist(paths=(str(from_rel), str(to_rel)),
1139
extra="can't rename")
1130
extra="Could not rename file")
1141
raise FilesExist(paths=(str(from_rel), str(to_rel)),
1142
extra="can't rename. Use option '--after' to"
1132
raise errors.FilesExist(paths=(str(from_rel), str(to_rel)),
1133
extra="Could not rename file. Use option '--after' to"
1143
1134
" force rename.")
1144
1135
rename_entry.only_change_inv = only_change_inv
1145
1136
return rename_entries
1158
1149
self._move_entry(entry)
1159
1150
except OSError, e:
1160
1151
self._rollback_move(moved)
1161
raise BzrError("failed to rename %r to %r: %s" %
1152
raise errors.BzrError("failed to rename %r to %r: %s" %
1162
1153
(entry.from_rel, entry.to_rel, e[1]))
1154
except errors.BzrError, e:
1164
1155
self._rollback_move(moved)
1166
1157
moved.append(entry)
1175
1166
self._move_entry(entry, inverse=True)
1176
1167
except OSError, e:
1177
raise BzrError("error moving files. Rollback failed. The"
1178
" working tree is in an inconsistent state."
1168
raise errors.BzrError("error moving files. Rollback failed."
1169
" The working tree is in an inconsistent state."
1179
1170
" Please consider doing a 'bzr revert'."
1180
1171
" Error message is: %s" % e[1])
1185
1176
to_rel_abs = self.abspath(entry.to_rel)
1187
1178
if from_rel_abs == to_rel_abs:
1188
raise BzrError("error moving files. Source %r and target %r are"
1189
" identical." % (from_rel, to_rel))
1179
raise errors.BzrError("error moving files. Source %r and target %r"
1180
" are identical." % (from_rel, to_rel))
1192
1183
if not entry.only_change_inv:
1228
1219
from_tail = splitpath(from_rel)[-1]
1229
1220
from_id = inv.path2id(from_rel)
1230
1221
if from_id is None:
1231
raise BzrError("can't rename: old name %r is not versioned" %
1222
raise errors.NotVersionedError(path=str(from_rel),
1223
context_info="Could not rename file")
1233
1224
from_entry = inv[from_id]
1234
1225
from_parent_id = from_entry.parent_id
1235
1226
to_dir, to_tail = os.path.split(to_rel)
1248
1239
# check if the target changed directory and if the target directory is
1250
1241
if to_dir_id is None:
1251
raise BzrError("destination %r is not a versioned"
1242
raise errors.BzrError("destination %r is not a versioned"
1252
1243
" directory" % to_dir)
1254
1245
# all checks done. now we can continue with our actual work
1659
1650
# TODO: Perhaps make this just a warning, and continue?
1660
1651
# This tends to happen when
1661
raise NotVersionedError(path=f)
1652
raise errors.NotVersionedError(path=f)
1663
1654
# having remove it, it must be either ignored or unknown
1664
1655
if self.is_ignored(f):
1707
1698
elif kind == 'symlink':
1708
1699
inv.add(InventoryLink(file_id, name, parent))
1710
raise BzrError("unknown kind %r" % kind)
1701
raise errors.BzrError("unknown kind %r" % kind)
1711
1702
self._write_inventory(inv)
1713
1704
@needs_tree_write_lock
1890
1881
def set_conflicts(self, arg):
1891
raise UnsupportedOperation(self.set_conflicts, self)
1882
raise errors.UnsupportedOperation(self.set_conflicts, self)
1893
1884
def add_conflicts(self, arg):
1894
raise UnsupportedOperation(self.add_conflicts, self)
1885
raise errors.UnsupportedOperation(self.add_conflicts, self)
1896
1887
@needs_read_lock
1897
1888
def conflicts(self):
1971
1962
"""See Mutable.last_revision."""
1973
1964
return self._control_files.get_utf8('last-revision').read()
1965
except errors.NoSuchFile:
1977
1968
def _change_last_revision(self, revision_id):
2002
1993
def conflicts(self):
2004
1995
confile = self._control_files.get('conflicts')
1996
except errors.NoSuchFile:
2006
1997
return _mod_conflicts.ConflictList()
2008
1999
if confile.next() != CONFLICT_HEADER_1 + '\n':
2009
raise ConflictFormatError()
2000
raise errors.ConflictFormatError()
2010
2001
except StopIteration:
2011
raise ConflictFormatError()
2002
raise errors.ConflictFormatError()
2012
2003
return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2014
2005
def unlock(self):
2076
2067
transport = a_bzrdir.get_workingtree_transport(None)
2077
2068
format_string = transport.get("format").read()
2078
2069
return klass._formats[format_string]
2070
except errors.NoSuchFile:
2080
2071
raise errors.NoWorkingTree(base=transport.base)
2081
2072
except KeyError:
2082
2073
raise errors.UnknownFormatError(format=format_string)