72
73
from bzrlib import symbol_versioning
73
74
from bzrlib.decorators import needs_read_lock, needs_write_lock
74
from bzrlib.i18n import gettext
75
75
from bzrlib.lock import LogicalLockResult
76
76
import bzrlib.mutabletree
77
77
from bzrlib.mutabletree import needs_tree_write_lock
173
173
def __init__(self, basedir='.',
174
174
branch=DEPRECATED_PARAMETER,
179
179
"""Construct a WorkingTree instance. This is not a public API.
193
193
self._branch = self.bzrdir.open_branch()
194
194
self.basedir = realpath(basedir)
195
self._transport = _transport
195
self._control_files = _control_files
196
self._transport = self._control_files._transport
197
# update the whole cache up front and write to disk if anything changed;
198
# in the future we might want to do this more selectively
199
# two possible ways offer themselves : in self._unlock, write the cache
200
# if needed, or, when the cache sees a change, append it to the hash
201
# cache file, and have the parser take the most recent entry for a
203
wt_trans = self.bzrdir.get_workingtree_transport(None)
204
cache_filename = wt_trans.local_abspath('stat-cache')
205
self._hashcache = hashcache.HashCache(basedir, cache_filename,
206
self.bzrdir._get_file_mode(),
207
self._content_filter_stack_provider())
210
# is this scan needed ? it makes things kinda slow.
217
self._detect_case_handling()
196
218
self._rules_searcher = None
197
219
self.views = self._make_views()
217
239
return self.bzrdir.is_control_filename(filename)
241
def _detect_case_handling(self):
242
wt_trans = self.bzrdir.get_workingtree_transport(None)
244
wt_trans.stat(self._format.case_sensitive_filename)
245
except errors.NoSuchFile:
246
self.case_sensitive = True
248
self.case_sensitive = False
250
self._setup_directory_is_tree_reference()
219
252
branch = property(
220
253
fget=lambda self: self._branch,
221
254
doc="""The branch this WorkingTree is connected to.
224
257
the working tree has been constructed from.
227
def has_versioned_directories(self):
228
"""See `Tree.has_versioned_directories`."""
229
return self._format.supports_versioned_directories
231
260
def break_lock(self):
232
261
"""Break a lock if one is present from another instance.
237
266
This will probe the repository for its lock as well.
239
raise NotImplementedError(self.break_lock)
268
self._control_files.break_lock()
269
self.branch.break_lock()
241
271
def requires_rich_root(self):
242
272
return self._format.requires_rich_root
277
307
path = osutils.getcwd()
278
control, relpath = controldir.ControlDir.open_containing(path)
308
control, relpath = bzrdir.BzrDir.open_containing(path)
279
309
return control.open_workingtree(), relpath
365
395
return True, tree
366
396
t = transport.get_transport(location)
367
iterator = controldir.ControlDir.find_bzrdirs(t, evaluate=evaluate,
397
iterator = bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate,
368
398
list_current=list_current)
369
399
return [tr for tr in iterator if tr is not None]
499
def _get_ancestors(self, default_revision):
500
ancestors = set([default_revision])
501
for parent_id in self.get_parent_ids():
502
ancestors.update(self.branch.repository.get_ancestry(
503
parent_id, topo_sorted=False))
469
506
def get_parent_ids(self):
470
507
"""See Tree.get_parent_ids.
492
529
raise NotImplementedError(self.get_root_id)
495
def clone(self, to_controldir, revision_id=None):
532
def clone(self, to_bzrdir, revision_id=None):
496
533
"""Duplicate this working tree into to_bzr, including all state.
498
535
Specifically modified files are kept as modified, but
499
536
ignored and unknown files are discarded.
501
If you want to make a new line of development, see ControlDir.sprout()
538
If you want to make a new line of development, see bzrdir.sprout()
504
541
If not None, the cloned tree will have its last revision set to
506
543
and this one merged in.
508
545
# assumes the target bzr dir format is compatible.
509
result = to_controldir.create_workingtree()
546
result = to_bzrdir.create_workingtree()
510
547
self.copy_content_into(result, revision_id)
520
557
# TODO now merge from tree.last_revision to revision (to preserve
521
558
# user local changes)
522
559
merge.transform_tree(tree, self)
523
if revision_id == _mod_revision.NULL_REVISION:
526
new_parents = [revision_id]
527
tree.set_parent_ids(new_parents)
560
tree.set_parent_ids([revision_id])
529
562
def id2abspath(self, file_id):
530
563
return self.abspath(self.id2path(file_id))
605
def get_file_sha1(self, file_id, path=None, stat_value=None):
606
# FIXME: Shouldn't this be in Tree?
607
raise NotImplementedError(self.get_file_sha1)
572
609
@needs_tree_write_lock
573
610
def _gather_kinds(self, files, kinds):
574
611
"""See MutableTree._gather_kinds."""
740
777
@needs_tree_write_lock
741
778
def set_merge_modified(self, modified_hashes):
742
"""Set the merge modified hashes."""
743
raise NotImplementedError(self.set_merge_modified)
780
for file_id, hash in modified_hashes.iteritems():
781
yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
783
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
745
785
def _sha_from_stat(self, path, stat_result):
746
786
"""Get a sha digest from the tree's stat cache.
795
def _put_rio(self, filename, stanzas, header):
796
self._must_be_locked()
797
my_file = _mod_rio.rio_file(stanzas, header)
798
self._transport.put_file(filename, my_file,
799
mode=self.bzrdir._get_file_mode())
755
801
@needs_write_lock # because merge pulls data into the branch.
756
802
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
757
803
merge_type=None, force=False):
997
1043
show_base=show_base)
998
1044
basis_root_id = basis_tree.get_root_id()
999
1045
new_root_id = new_basis_tree.get_root_id()
1000
if new_root_id is not None and basis_root_id != new_root_id:
1046
if basis_root_id != new_root_id:
1001
1047
self.set_root_id(new_root_id)
1003
1049
basis_tree.unlock()
1004
1050
# TODO - dedup parents list with things merged by pull ?
1005
1051
# reuse the revisiontree we merged against to set the new
1008
if self.branch.last_revision() != _mod_revision.NULL_REVISION:
1009
parent_trees.append(
1010
(self.branch.last_revision(), new_basis_tree))
1053
parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1011
1054
# we have to pull the merge trees out again, because
1012
1055
# merge_inner has set the ids. - this corner is not yet
1013
1056
# layered well enough to prevent double handling.
1137
1181
return _mod_revision.ensure_null(self.branch.last_revision())
1139
1183
def is_locked(self):
1140
"""Check if this tree is locked."""
1141
raise NotImplementedError(self.is_locked)
1184
return self._control_files.is_locked()
1186
def _must_be_locked(self):
1187
if not self.is_locked():
1188
raise errors.ObjectNotLocked(self)
1143
1190
def lock_read(self):
1144
1191
"""Lock the tree for reading.
1148
1195
:return: A bzrlib.lock.LogicalLockResult.
1150
raise NotImplementedError(self.lock_read)
1197
if not self.is_locked():
1199
self.branch.lock_read()
1201
self._control_files.lock_read()
1202
return LogicalLockResult(self.unlock)
1204
self.branch.unlock()
1152
1207
def lock_tree_write(self):
1153
1208
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1155
1210
:return: A bzrlib.lock.LogicalLockResult.
1157
raise NotImplementedError(self.lock_tree_write)
1212
if not self.is_locked():
1214
self.branch.lock_read()
1216
self._control_files.lock_write()
1217
return LogicalLockResult(self.unlock)
1219
self.branch.unlock()
1159
1222
def lock_write(self):
1160
1223
"""See MutableTree.lock_write, and WorkingTree.unlock.
1162
1225
:return: A bzrlib.lock.LogicalLockResult.
1164
raise NotImplementedError(self.lock_write)
1227
if not self.is_locked():
1229
self.branch.lock_write()
1231
self._control_files.lock_write()
1232
return LogicalLockResult(self.unlock)
1234
self.branch.unlock()
1166
1237
def get_physical_lock_status(self):
1167
raise NotImplementedError(self.get_physical_lock_status)
1238
return self._control_files.get_physical_lock_status()
1240
def _reset_data(self):
1241
"""Reset transient data that cannot be revalidated."""
1242
raise NotImplementedError(self._reset_data)
1169
1244
def set_last_revision(self, new_revision):
1170
1245
"""Change the last revision in the working tree."""
1464
1539
show_base=show_base)
1465
1540
if nb_conflicts:
1466
1541
self.add_parent_tree((old_tip, other_tree))
1467
note(gettext('Rerun update after fixing the conflicts.'))
1542
note('Rerun update after fixing the conflicts.')
1468
1543
return nb_conflicts
1470
1545
if last_rev != _mod_revision.ensure_null(revision):
1512
1587
last_rev = parent_trees[0][0]
1513
1588
return nb_conflicts
1590
def _write_hashcache_if_dirty(self):
1591
"""Write out the hashcache if it is dirty."""
1592
if self._hashcache.needs_write:
1594
self._hashcache.write()
1596
if e.errno not in (errno.EPERM, errno.EACCES):
1598
# TODO: jam 20061219 Should this be a warning? A single line
1599
# warning might be sufficient to let the user know what
1601
mutter('Could not write hashcache for %s\nError: %s',
1602
self._hashcache.cache_file_name(), e)
1515
1604
def set_conflicts(self, arg):
1516
1605
raise errors.UnsupportedOperation(self.set_conflicts, self)
1746
1835
:param branch: A branch to override probing for the branch.
1748
1837
super(InventoryWorkingTree, self).__init__(basedir=basedir,
1749
branch=branch, _transport=_control_files._transport,
1750
_internal=_internal, _format=_format, _bzrdir=_bzrdir)
1752
self._control_files = _control_files
1753
self._detect_case_handling()
1838
branch=branch, _control_files=_control_files, _internal=_internal,
1839
_format=_format, _bzrdir=_bzrdir)
1755
1841
if _inventory is None:
1756
1842
# This will be acquired on lock_read() or lock_write()
1776
1862
self._inventory = inv
1777
1863
self._inventory_is_modified = dirty
1779
def _detect_case_handling(self):
1780
wt_trans = self.bzrdir.get_workingtree_transport(None)
1782
wt_trans.stat(self._format.case_sensitive_filename)
1783
except errors.NoSuchFile:
1784
self.case_sensitive = True
1786
self.case_sensitive = False
1788
self._setup_directory_is_tree_reference()
1790
1865
def _serialize(self, inventory, out_file):
1791
1866
xml5.serializer_v5.write_inventory(self._inventory, out_file,
1794
1869
def _deserialize(selt, in_file):
1795
1870
return xml5.serializer_v5.read_inventory(in_file)
1797
def break_lock(self):
1798
"""Break a lock if one is present from another instance.
1800
Uses the ui factory to ask for confirmation if the lock may be from
1803
This will probe the repository for its lock as well.
1805
self._control_files.break_lock()
1806
self.branch.break_lock()
1808
def is_locked(self):
1809
return self._control_files.is_locked()
1811
def _must_be_locked(self):
1812
if not self.is_locked():
1813
raise errors.ObjectNotLocked(self)
1815
def lock_read(self):
1816
"""Lock the tree for reading.
1818
This also locks the branch, and can be unlocked via self.unlock().
1820
:return: A bzrlib.lock.LogicalLockResult.
1822
if not self.is_locked():
1824
self.branch.lock_read()
1826
self._control_files.lock_read()
1827
return LogicalLockResult(self.unlock)
1829
self.branch.unlock()
1832
def lock_tree_write(self):
1833
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1835
:return: A bzrlib.lock.LogicalLockResult.
1837
if not self.is_locked():
1839
self.branch.lock_read()
1841
self._control_files.lock_write()
1842
return LogicalLockResult(self.unlock)
1844
self.branch.unlock()
1847
def lock_write(self):
1848
"""See MutableTree.lock_write, and WorkingTree.unlock.
1850
:return: A bzrlib.lock.LogicalLockResult.
1852
if not self.is_locked():
1854
self.branch.lock_write()
1856
self._control_files.lock_write()
1857
return LogicalLockResult(self.unlock)
1859
self.branch.unlock()
1862
def get_physical_lock_status(self):
1863
return self._control_files.get_physical_lock_status()
1865
1872
@needs_tree_write_lock
1866
1873
def _write_inventory(self, inv):
1867
1874
"""Write inventory as the current inventory."""
2164
2173
mode=self.bzrdir._get_file_mode())
2165
2174
self._inventory_is_modified = False
2177
def get_file_sha1(self, file_id, path=None, stat_value=None):
2179
path = self._inventory.id2path(file_id)
2180
return self._hashcache.get_sha1(path, stat_value)
2167
2182
def get_file_mtime(self, file_id, path=None):
2168
2183
"""See Tree.get_file_mtime."""
2170
2185
path = self.inventory.id2path(file_id)
2172
return os.lstat(self.abspath(path)).st_mtime
2174
if e.errno == errno.ENOENT:
2175
raise errors.FileTimestampUnavailable(path)
2186
return os.lstat(self.abspath(path)).st_mtime
2178
2188
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2179
2189
file_id = self.path2id(path)
2286
2296
for key, line in annotator.annotate_flat(this_key)]
2287
2297
return annotations
2289
def _put_rio(self, filename, stanzas, header):
2290
self._must_be_locked()
2291
my_file = _mod_rio.rio_file(stanzas, header)
2292
self._transport.put_file(filename, my_file,
2293
mode=self.bzrdir._get_file_mode())
2295
@needs_tree_write_lock
2296
def set_merge_modified(self, modified_hashes):
2298
for file_id, hash in modified_hashes.iteritems():
2299
yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
2301
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
2303
2299
@needs_read_lock
2304
2300
def merge_modified(self):
2305
2301
"""Return a dictionary of files modified by a merge.
2325
2321
for s in _mod_rio.RioReader(hashfile):
2326
2322
# RioReader reads in Unicode, so convert file_ids back to utf8
2327
2323
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2328
if not self.inventory.has_id(file_id):
2324
if file_id not in self.inventory:
2330
2326
text_hash = s.get("hash")
2331
2327
if text_hash == self.get_file_sha1(file_id):
2866
2862
:raises: NoSuchId if any fileid is not currently versioned.
2868
2864
for file_id in file_ids:
2869
if not self._inventory.has_id(file_id):
2865
if file_id not in self._inventory:
2870
2866
raise errors.NoSuchId(self, file_id)
2871
2867
for file_id in file_ids:
2872
2868
if self._inventory.has_id(file_id):
3027
3023
missing_parent_conflicts = False
3028
3024
"""If this format supports missing parent conflicts."""
3030
supports_versioned_directories = None
3033
def find_format_string(klass, controldir):
3034
"""Return format name for the working tree object in controldir."""
3027
def find_format_string(klass, a_bzrdir):
3028
"""Return format name for the working tree object in a_bzrdir."""
3036
transport = controldir.get_workingtree_transport(None)
3030
transport = a_bzrdir.get_workingtree_transport(None)
3037
3031
return transport.get_bytes("format")
3038
3032
except errors.NoSuchFile:
3039
3033
raise errors.NoWorkingTree(base=transport.base)
3042
def find_format(klass, controldir):
3043
"""Return the format for the working tree object in controldir."""
3036
def find_format(klass, a_bzrdir):
3037
"""Return the format for the working tree object in a_bzrdir."""
3045
format_string = klass.find_format_string(controldir)
3039
format_string = klass.find_format_string(a_bzrdir)
3046
3040
return format_registry.get(format_string)
3047
3041
except KeyError:
3048
3042
raise errors.UnknownFormatError(format=format_string,
3049
3043
kind="working tree")
3051
def initialize(self, controldir, revision_id=None, from_branch=None,
3045
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3052
3046
accelerator_tree=None, hardlink=False):
3053
"""Initialize a new working tree in controldir.
3047
"""Initialize a new working tree in a_bzrdir.
3055
:param controldir: ControlDir to initialize the working tree in.
3049
:param a_bzrdir: BzrDir to initialize the working tree in.
3056
3050
:param revision_id: allows creating a working tree at a different
3057
3051
revision than the branch is at.
3058
3052
:param from_branch: Branch to checkout
3139
3133
def unregister_format(klass, format):
3140
3134
format_registry.remove(format)
3142
def get_controldir_for_branch(self):
3143
"""Get the control directory format for creating branches.
3145
This is to support testing of working tree formats that can not exist
3146
in the same control directory as a branch.
3148
return self._matchingbzrdir
3151
3137
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3152
3138
"bzrlib.workingtree_4", "WorkingTreeFormat4")