61
from .controldir import (
63
ControlComponentFormatRegistry,
64
ControlComponentFormat,
71
63
from .i18n import gettext
72
64
from . import mutabletree
73
from .symbol_versioning import deprecated_method, deprecated_in
74
65
from .trace import mutter, note
68
ERROR_PATH_NOT_FOUND = 3 # WindowsError errno code, equivalent to ENOENT
77
71
class SettingFileIdUnsupported(errors.BzrError):
79
73
_fmt = "This format does not support setting file ids."
84
78
_fmt = "This format does not support shelving changes."
87
class WorkingTree(mutabletree.MutableTree, ControlComponent):
81
class WorkingTree(mutabletree.MutableTree, controldir.ControlComponent):
88
82
"""Working copy tree.
90
84
:ivar basedir: The root of the tree on disk. This is a unicode path object
129
123
def control_transport(self):
130
124
return self._transport
132
def supports_symlinks(self):
133
return osutils.supports_symlinks(self.basedir)
135
126
def is_control_filename(self, filename):
136
127
"""True if filename is the name of a control file in this tree.
162
153
return self._format.supports_merge_modified
164
155
def _supports_executable(self):
165
return osutils.supports_executable(self.basedir)
156
if sys.platform == 'win32':
158
# FIXME: Ideally this should check the file system
167
161
def break_lock(self):
168
162
"""Break a lock if one is present from another instance.
224
218
path = osutils.getcwd()
225
control, relpath = ControlDir.open_containing(path)
219
control, relpath = controldir.ControlDir.open_containing(path)
226
220
return control.open_workingtree(), relpath
301
295
return WorkingTree.open(path, _unsupported=True)
298
def find_trees(location):
299
def list_current(transport):
300
return [d for d in transport.list_dir('')
301
if not controldir.is_control_filename(d)]
303
def evaluate(controldir):
305
tree = controldir.open_workingtree()
306
except errors.NoWorkingTree:
310
t = transport.get_transport(location)
311
iterator = controldir.ControlDir.find_controldirs(t, evaluate=evaluate,
312
list_current=list_current)
313
return [tr for tr in iterator if tr is not None]
303
315
def __repr__(self):
304
316
return "<%s of %s>" % (self.__class__.__name__,
305
317
getattr(self, 'basedir', None))
368
380
stat_value = _fstat(file_obj.fileno())
369
381
if filtered and self.supports_content_filtering():
370
382
filters = self._content_filter_stack(path)
372
file_obj, size = _mod_filters.filtered_input_file(
374
stat_value = _mod_filters.FilteredStat(
375
stat_value, st_size=size)
383
file_obj = _mod_filters.filtered_input_file(file_obj, filters)
376
384
return (file_obj, stat_value)
378
386
def get_file_text(self, path, filtered=True):
405
413
parents.append(revision_id)
416
def get_root_id(self):
417
"""Return the id of this trees root"""
418
raise NotImplementedError(self.get_root_id)
408
420
def clone(self, to_controldir, revision_id=None):
409
421
"""Duplicate this working tree into to_bzr, including all state.
427
439
def copy_content_into(self, tree, revision_id=None):
428
440
"""Copy the current content and user files of this tree into tree."""
429
441
with self.lock_read():
430
tree.set_root_id(self.path2id(''))
442
tree.set_root_id(self.get_root_id())
431
443
if revision_id is None:
432
444
merge.transform_tree(tree, self)
661
673
merger.other_rev_id = to_revision
662
674
if _mod_revision.is_null(merger.other_rev_id):
663
675
raise errors.NoCommits(branch)
664
self.branch.fetch(branch, stop_revision=merger.other_rev_id)
676
self.branch.fetch(branch, last_revision=merger.other_rev_id)
665
677
merger.other_basis = merger.other_rev_id
666
678
merger.other_tree = self.branch.repository.revision_tree(
667
679
merger.other_rev_id)
717
729
def subsume(self, other_tree):
718
730
raise NotImplementedError(self.subsume)
720
def _directory_is_tree_reference(self, relpath):
721
raise NotImplementedError(self._directory_is_tree_reference)
732
def _setup_directory_is_tree_reference(self):
733
if self._branch.repository._format.supports_tree_reference:
734
self._directory_is_tree_reference = \
735
self._directory_may_be_tree_reference
737
self._directory_is_tree_reference = \
738
self._directory_is_never_tree_reference
740
def _directory_is_never_tree_reference(self, relpath):
743
def _directory_may_be_tree_reference(self, relpath):
744
# as a special case, if a directory contains control files then
745
# it's a tree reference, except that the root of the tree is not
746
return relpath and osutils.isdir(self.abspath(relpath) + u"/.bzr")
747
# TODO: We could ask all the control formats whether they
748
# recognize this directory, but at the moment there's no cheap api
749
# to do that. Since we probably can only nest bzr checkouts and
750
# they always use this name it's ok for now. -- mbp 20060306
752
# FIXME: There is an unhandled case here of a subdirectory
753
# containing .bzr but not a branch; that will probably blow up
754
# when you try to commit it. It might happen if there is a
755
# checkout in a subdirectory. This can be avoided by not adding
723
758
def extract(self, path, format=None):
724
759
"""Extract a subtree from this tree.
734
769
def kind(self, relpath):
735
770
return osutils.file_kind(self.abspath(relpath))
737
def list_files(self, include_root=False, from_dir=None, recursive=True,
738
recurse_nested=False):
772
def list_files(self, include_root=False, from_dir=None, recursive=True):
739
773
"""List all files as (path, class, kind, id, entry).
741
775
Lists, but does not descend into unversioned directories.
822
856
def pull(self, source, overwrite=False, stop_revision=None,
823
857
change_reporter=None, possible_transports=None, local=False,
824
show_base=False, tag_selector=None):
825
859
with self.lock_write(), source.lock_read():
826
860
old_revision_info = self.branch.last_revision_info()
827
861
basis_tree = self.basis_tree()
828
862
count = self.branch.pull(source, overwrite, stop_revision,
829
863
possible_transports=possible_transports,
830
local=local, tag_selector=tag_selector)
831
865
new_revision_info = self.branch.last_revision_info()
832
866
if new_revision_info != old_revision_info:
833
867
repository = self.branch.repository
846
880
change_reporter=change_reporter,
847
881
show_base=show_base)
848
basis_root_id = basis_tree.path2id('')
849
new_root_id = new_basis_tree.path2id('')
882
basis_root_id = basis_tree.get_root_id()
883
new_root_id = new_basis_tree.get_root_id()
850
884
if new_root_id is not None and basis_root_id != new_root_id:
851
885
self.set_root_id(new_root_id)
852
886
# TODO - dedup parents list with things merged by pull ?
1002
1036
def revert(self, filenames=None, old_tree=None, backups=True,
1003
1037
pb=None, report_changes=False):
1004
1038
from .conflicts import resolve
1005
with cleanup.ExitStack() as exit_stack:
1006
exit_stack.enter_context(self.lock_tree_write())
1039
with self.lock_tree_write():
1007
1040
if old_tree is None:
1008
1041
basis_tree = self.basis_tree()
1009
exit_stack.enter_context(basis_tree.lock_read())
1042
basis_tree.lock_read()
1010
1043
old_tree = basis_tree
1012
1045
basis_tree = None
1013
conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1015
if filenames is None and len(self.get_parent_ids()) > 1:
1017
last_revision = self.last_revision()
1018
if last_revision != _mod_revision.NULL_REVISION:
1019
if basis_tree is None:
1020
basis_tree = self.basis_tree()
1021
exit_stack.enter_context(basis_tree.lock_read())
1022
parent_trees.append((last_revision, basis_tree))
1023
self.set_parent_trees(parent_trees)
1026
resolve(self, filenames, ignore_misses=True, recursive=True)
1047
conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1049
if filenames is None and len(self.get_parent_ids()) > 1:
1051
last_revision = self.last_revision()
1052
if last_revision != _mod_revision.NULL_REVISION:
1053
if basis_tree is None:
1054
basis_tree = self.basis_tree()
1055
basis_tree.lock_read()
1056
parent_trees.append((last_revision, basis_tree))
1057
self.set_parent_trees(parent_trees)
1060
resolve(self, filenames, ignore_misses=True, recursive=True)
1062
if basis_tree is not None:
1027
1064
return conflicts
1029
1066
def store_uncommitted(self):
1171
1208
# the working tree is up to date with the branch
1172
1209
# we can merge the specified revision from master
1173
1210
to_tree = self.branch.repository.revision_tree(revision)
1174
to_root_id = to_tree.path2id('')
1211
to_root_id = to_tree.get_root_id()
1176
1213
basis = self.basis_tree()
1177
1214
with basis.lock_read():
1178
if (basis.path2id('') is None or basis.path2id('') != to_root_id):
1215
if (basis.get_root_id() is None or basis.get_root_id() != to_root_id):
1179
1216
self.set_root_id(to_root_id)
1248
1284
with self.lock_tree_write():
1249
1285
un_resolved = _mod_conflicts.ConflictList()
1250
1286
resolved = _mod_conflicts.ConflictList()
1287
conflict_re = re.compile(b'^(<{7}|={7}|>{7})')
1251
1288
for conflict in self.conflicts():
1253
conflict.action_auto(self)
1254
except NotImplementedError:
1289
path = self.id2path(conflict.file_id)
1290
if (conflict.typestring != 'text conflict' or
1291
self.kind(path) != 'file'):
1255
1292
un_resolved.append(conflict)
1257
conflict.cleanup(self)
1258
resolved.append(conflict)
1294
with open(self.abspath(path), 'rb') as my_file:
1295
for line in my_file:
1296
if conflict_re.search(line):
1297
un_resolved.append(conflict)
1300
resolved.append(conflict)
1301
resolved.remove_files(self)
1259
1302
self.set_conflicts(un_resolved)
1260
1303
return un_resolved, resolved
1329
1372
with self.lock_read():
1330
1373
return next(self.get_canonical_paths([path]))
1332
def reference_parent(self, path, branch=None, possible_transports=None):
1333
raise errors.UnsupportedOperation(self.reference_parent, self)
1335
def get_reference_info(self, path, branch=None):
1336
raise errors.UnsupportedOperation(self.get_reference_info, self)
1338
def set_reference_info(self, tree_path, branch_location):
1339
raise errors.UnsupportedOperation(self.set_reference_info, self)
1342
class WorkingTreeFormatRegistry(ControlComponentFormatRegistry):
1376
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
1343
1377
"""Registry for working tree formats."""
1345
1379
def __init__(self, other_registry=None):
1368
1402
format_registry = WorkingTreeFormatRegistry()
1371
class WorkingTreeFormat(ControlComponentFormat):
1405
class WorkingTreeFormat(controldir.ControlComponentFormat):
1372
1406
"""An encapsulation of the initialization and open routines for a format.
1374
1408
Formats provide three things: