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
194
194
self.basedir = realpath(basedir)
195
195
self._control_files = _control_files
196
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()
197
218
self._rules_searcher = None
198
219
self.views = self._make_views()
218
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()
220
252
branch = property(
221
253
fget=lambda self: self._branch,
222
254
doc="""The branch this WorkingTree is connected to.
225
257
the working tree has been constructed from.
228
def has_versioned_directories(self):
229
"""See `Tree.has_versioned_directories`."""
230
return self._format.supports_versioned_directories
232
260
def break_lock(self):
233
261
"""Break a lock if one is present from another instance.
279
307
path = osutils.getcwd()
280
control, relpath = controldir.ControlDir.open_containing(path)
308
control, relpath = bzrdir.BzrDir.open_containing(path)
281
309
return control.open_workingtree(), relpath
367
395
return True, tree
368
396
t = transport.get_transport(location)
369
iterator = controldir.ControlDir.find_bzrdirs(t, evaluate=evaluate,
397
iterator = bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate,
370
398
list_current=list_current)
371
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))
471
506
def get_parent_ids(self):
472
507
"""See Tree.get_parent_ids.
494
529
raise NotImplementedError(self.get_root_id)
497
def clone(self, to_controldir, revision_id=None):
532
def clone(self, to_bzrdir, revision_id=None):
498
533
"""Duplicate this working tree into to_bzr, including all state.
500
535
Specifically modified files are kept as modified, but
501
536
ignored and unknown files are discarded.
503
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()
506
541
If not None, the cloned tree will have its last revision set to
508
543
and this one merged in.
510
545
# assumes the target bzr dir format is compatible.
511
result = to_controldir.create_workingtree()
546
result = to_bzrdir.create_workingtree()
512
547
self.copy_content_into(result, revision_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)
570
609
@needs_tree_write_lock
571
610
def _gather_kinds(self, files, kinds):
572
611
"""See MutableTree._gather_kinds."""
934
973
file and change the file_id. That is the normal mode. Second, it can
935
974
only change the file_id without touching any physical file.
937
rename_one uses the second mode if 'after == True' and 'to_rel' is
938
either not versioned or newly added, and present in the working tree.
976
rename_one uses the second mode if 'after == True' and 'to_rel' is not
977
versioned but present in the working tree.
940
979
rename_one uses the second mode if 'after == False' and 'from_rel' is
941
980
versioned but no longer in the working tree, and 'to_rel' is not
1499
1539
show_base=show_base)
1500
1540
if nb_conflicts:
1501
1541
self.add_parent_tree((old_tip, other_tree))
1502
note(gettext('Rerun update after fixing the conflicts.'))
1542
note('Rerun update after fixing the conflicts.')
1503
1543
return nb_conflicts
1505
1545
if last_rev != _mod_revision.ensure_null(revision):
1547
1587
last_rev = parent_trees[0][0]
1548
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)
1550
1604
def set_conflicts(self, arg):
1551
1605
raise errors.UnsupportedOperation(self.set_conflicts, self)
1784
1838
branch=branch, _control_files=_control_files, _internal=_internal,
1785
1839
_format=_format, _bzrdir=_bzrdir)
1787
self._detect_case_handling()
1789
1841
if _inventory is None:
1790
1842
# This will be acquired on lock_read() or lock_write()
1791
1843
self._inventory_is_modified = False
1810
1862
self._inventory = inv
1811
1863
self._inventory_is_modified = dirty
1813
def _detect_case_handling(self):
1814
wt_trans = self.bzrdir.get_workingtree_transport(None)
1816
wt_trans.stat(self._format.case_sensitive_filename)
1817
except errors.NoSuchFile:
1818
self.case_sensitive = True
1820
self.case_sensitive = False
1822
self._setup_directory_is_tree_reference()
1824
1865
def _serialize(self, inventory, out_file):
1825
1866
xml5.serializer_v5.write_inventory(self._inventory, out_file,
2130
2173
mode=self.bzrdir._get_file_mode())
2131
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)
2133
2182
def get_file_mtime(self, file_id, path=None):
2134
2183
"""See Tree.get_file_mtime."""
2136
2185
path = self.inventory.id2path(file_id)
2138
return os.lstat(self.abspath(path)).st_mtime
2140
if e.errno == errno.ENOENT:
2141
raise errors.FileTimestampUnavailable(path)
2186
return os.lstat(self.abspath(path)).st_mtime
2144
2188
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2145
2189
file_id = self.path2id(path)
2277
2321
for s in _mod_rio.RioReader(hashfile):
2278
2322
# RioReader reads in Unicode, so convert file_ids back to utf8
2279
2323
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2280
if not self.inventory.has_id(file_id):
2324
if file_id not in self.inventory:
2282
2326
text_hash = s.get("hash")
2283
2327
if text_hash == self.get_file_sha1(file_id):
2524
2568
inventory. The second mode only updates the inventory without
2525
2569
touching the file on the filesystem.
2527
move uses the second mode if 'after == True' and the target is
2528
either not versioned or newly added, and present in the working tree.
2571
move uses the second mode if 'after == True' and the target is not
2572
versioned but present in the working tree.
2530
2574
move uses the second mode if 'after == False' and the source is
2531
2575
versioned but no longer in the working tree, and the target is not
2679
2723
class _RenameEntry(object):
2680
2724
def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2681
to_rel, to_tail, to_parent_id, only_change_inv=False,
2725
to_rel, to_tail, to_parent_id, only_change_inv=False):
2683
2726
self.from_rel = from_rel
2684
2727
self.from_id = from_id
2685
2728
self.from_tail = from_tail
2687
2730
self.to_rel = to_rel
2688
2731
self.to_tail = to_tail
2689
2732
self.to_parent_id = to_parent_id
2690
self.change_id = change_id
2691
2733
self.only_change_inv = only_change_inv
2693
2735
def _determine_mv_mode(self, rename_entries, after=False):
2705
2747
to_rel = rename_entry.to_rel
2706
2748
to_id = inv.path2id(to_rel)
2707
2749
only_change_inv = False
2710
2751
# check the inventory for source and destination
2711
2752
if from_id is None:
2712
2753
raise errors.BzrMoveFailedError(from_rel,to_rel,
2713
2754
errors.NotVersionedError(path=from_rel))
2714
2755
if to_id is not None:
2716
# allow it with --after but only if dest is newly added
2718
basis = self.basis_tree()
2721
if not basis.has_id(to_id):
2722
rename_entry.change_id = True
2727
raise errors.BzrMoveFailedError(from_rel,to_rel,
2728
errors.AlreadyVersionedError(path=to_rel))
2756
raise errors.BzrMoveFailedError(from_rel,to_rel,
2757
errors.AlreadyVersionedError(path=to_rel))
2730
2759
# try to determine the mode for rename (only change inv or change
2731
2760
# inv and file system)
2802
2831
except OSError, e:
2803
2832
raise errors.BzrMoveFailedError(entry.from_rel,
2804
2833
entry.to_rel, e[1])
2806
to_id = inv.path2id(entry.to_rel)
2807
inv.remove_recursive_id(to_id)
2808
2834
inv.rename(entry.from_id, entry.to_parent_id, entry.to_tail)
2810
2836
@needs_tree_write_lock
2818
2844
:raises: NoSuchId if any fileid is not currently versioned.
2820
2846
for file_id in file_ids:
2821
if not self._inventory.has_id(file_id):
2847
if file_id not in self._inventory:
2822
2848
raise errors.NoSuchId(self, file_id)
2823
2849
for file_id in file_ids:
2824
2850
if self._inventory.has_id(file_id):
2979
3005
missing_parent_conflicts = False
2980
3006
"""If this format supports missing parent conflicts."""
2982
supports_versioned_directories = None
2985
def find_format_string(klass, controldir):
2986
"""Return format name for the working tree object in controldir."""
3009
def find_format_string(klass, a_bzrdir):
3010
"""Return format name for the working tree object in a_bzrdir."""
2988
transport = controldir.get_workingtree_transport(None)
3012
transport = a_bzrdir.get_workingtree_transport(None)
2989
3013
return transport.get_bytes("format")
2990
3014
except errors.NoSuchFile:
2991
3015
raise errors.NoWorkingTree(base=transport.base)
2994
def find_format(klass, controldir):
2995
"""Return the format for the working tree object in controldir."""
3018
def find_format(klass, a_bzrdir):
3019
"""Return the format for the working tree object in a_bzrdir."""
2997
format_string = klass.find_format_string(controldir)
3021
format_string = klass.find_format_string(a_bzrdir)
2998
3022
return format_registry.get(format_string)
2999
3023
except KeyError:
3000
3024
raise errors.UnknownFormatError(format=format_string,
3001
3025
kind="working tree")
3003
def initialize(self, controldir, revision_id=None, from_branch=None,
3027
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3004
3028
accelerator_tree=None, hardlink=False):
3005
"""Initialize a new working tree in controldir.
3029
"""Initialize a new working tree in a_bzrdir.
3007
:param controldir: ControlDir to initialize the working tree in.
3031
:param a_bzrdir: BzrDir to initialize the working tree in.
3008
3032
:param revision_id: allows creating a working tree at a different
3009
3033
revision than the branch is at.
3010
3034
:param from_branch: Branch to checkout
3091
3115
def unregister_format(klass, format):
3092
3116
format_registry.remove(format)
3094
def get_controldir_for_branch(self):
3095
"""Get the control directory format for creating branches.
3097
This is to support testing of working tree formats that can not exist
3098
in the same control directory as a branch.
3100
return self._matchingbzrdir
3103
3119
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3104
3120
"bzrlib.workingtree_4", "WorkingTreeFormat4")