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
1345
1385
def revert(self, filenames=None, old_tree=None, backups=True,
1346
1386
pb=None, report_changes=False):
1347
1387
from bzrlib.conflicts import resolve
1390
symbol_versioning.warn('Using [] to revert all files is deprecated'
1391
' as of bzr 0.91. Please use None (the default) instead.',
1392
DeprecationWarning, stacklevel=2)
1348
1393
if old_tree is None:
1349
1394
basis_tree = self.basis_tree()
1350
1395
basis_tree.lock_read()
1499
1544
show_base=show_base)
1500
1545
if nb_conflicts:
1501
1546
self.add_parent_tree((old_tip, other_tree))
1502
note(gettext('Rerun update after fixing the conflicts.'))
1547
note('Rerun update after fixing the conflicts.')
1503
1548
return nb_conflicts
1505
1550
if last_rev != _mod_revision.ensure_null(revision):
1547
1592
last_rev = parent_trees[0][0]
1548
1593
return nb_conflicts
1595
def _write_hashcache_if_dirty(self):
1596
"""Write out the hashcache if it is dirty."""
1597
if self._hashcache.needs_write:
1599
self._hashcache.write()
1601
if e.errno not in (errno.EPERM, errno.EACCES):
1603
# TODO: jam 20061219 Should this be a warning? A single line
1604
# warning might be sufficient to let the user know what
1606
mutter('Could not write hashcache for %s\nError: %s',
1607
self._hashcache.cache_file_name(), e)
1550
1609
def set_conflicts(self, arg):
1551
1610
raise errors.UnsupportedOperation(self.set_conflicts, self)
1784
1843
branch=branch, _control_files=_control_files, _internal=_internal,
1785
1844
_format=_format, _bzrdir=_bzrdir)
1787
self._detect_case_handling()
1789
1846
if _inventory is None:
1790
1847
# This will be acquired on lock_read() or lock_write()
1791
1848
self._inventory_is_modified = False
1810
1867
self._inventory = inv
1811
1868
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
1870
def _serialize(self, inventory, out_file):
1825
1871
xml5.serializer_v5.write_inventory(self._inventory, out_file,
2130
2178
mode=self.bzrdir._get_file_mode())
2131
2179
self._inventory_is_modified = False
2182
def get_file_sha1(self, file_id, path=None, stat_value=None):
2184
path = self._inventory.id2path(file_id)
2185
return self._hashcache.get_sha1(path, stat_value)
2133
2187
def get_file_mtime(self, file_id, path=None):
2134
2188
"""See Tree.get_file_mtime."""
2136
2190
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)
2191
return os.lstat(self.abspath(path)).st_mtime
2144
2193
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2145
2194
file_id = self.path2id(path)
2277
2326
for s in _mod_rio.RioReader(hashfile):
2278
2327
# RioReader reads in Unicode, so convert file_ids back to utf8
2279
2328
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2280
if not self.inventory.has_id(file_id):
2329
if file_id not in self.inventory:
2282
2331
text_hash = s.get("hash")
2283
2332
if text_hash == self.get_file_sha1(file_id):
2524
2573
inventory. The second mode only updates the inventory without
2525
2574
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.
2576
move uses the second mode if 'after == True' and the target is not
2577
versioned but present in the working tree.
2530
2579
move uses the second mode if 'after == False' and the source is
2531
2580
versioned but no longer in the working tree, and the target is not
2679
2728
class _RenameEntry(object):
2680
2729
def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2681
to_rel, to_tail, to_parent_id, only_change_inv=False,
2730
to_rel, to_tail, to_parent_id, only_change_inv=False):
2683
2731
self.from_rel = from_rel
2684
2732
self.from_id = from_id
2685
2733
self.from_tail = from_tail
2687
2735
self.to_rel = to_rel
2688
2736
self.to_tail = to_tail
2689
2737
self.to_parent_id = to_parent_id
2690
self.change_id = change_id
2691
2738
self.only_change_inv = only_change_inv
2693
2740
def _determine_mv_mode(self, rename_entries, after=False):
2705
2752
to_rel = rename_entry.to_rel
2706
2753
to_id = inv.path2id(to_rel)
2707
2754
only_change_inv = False
2710
2756
# check the inventory for source and destination
2711
2757
if from_id is None:
2712
2758
raise errors.BzrMoveFailedError(from_rel,to_rel,
2713
2759
errors.NotVersionedError(path=from_rel))
2714
2760
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))
2761
raise errors.BzrMoveFailedError(from_rel,to_rel,
2762
errors.AlreadyVersionedError(path=to_rel))
2730
2764
# try to determine the mode for rename (only change inv or change
2731
2765
# inv and file system)
2802
2836
except OSError, e:
2803
2837
raise errors.BzrMoveFailedError(entry.from_rel,
2804
2838
entry.to_rel, e[1])
2806
to_id = inv.path2id(entry.to_rel)
2807
inv.remove_recursive_id(to_id)
2808
2839
inv.rename(entry.from_id, entry.to_parent_id, entry.to_tail)
2810
2841
@needs_tree_write_lock
2818
2849
:raises: NoSuchId if any fileid is not currently versioned.
2820
2851
for file_id in file_ids:
2821
if not self._inventory.has_id(file_id):
2852
if file_id not in self._inventory:
2822
2853
raise errors.NoSuchId(self, file_id)
2823
2854
for file_id in file_ids:
2824
2855
if self._inventory.has_id(file_id):
2979
3010
missing_parent_conflicts = False
2980
3011
"""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."""
3014
def find_format_string(klass, a_bzrdir):
3015
"""Return format name for the working tree object in a_bzrdir."""
2988
transport = controldir.get_workingtree_transport(None)
3017
transport = a_bzrdir.get_workingtree_transport(None)
2989
3018
return transport.get_bytes("format")
2990
3019
except errors.NoSuchFile:
2991
3020
raise errors.NoWorkingTree(base=transport.base)
2994
def find_format(klass, controldir):
2995
"""Return the format for the working tree object in controldir."""
3023
def find_format(klass, a_bzrdir):
3024
"""Return the format for the working tree object in a_bzrdir."""
2997
format_string = klass.find_format_string(controldir)
3026
format_string = klass.find_format_string(a_bzrdir)
2998
3027
return format_registry.get(format_string)
2999
3028
except KeyError:
3000
3029
raise errors.UnknownFormatError(format=format_string,
3001
3030
kind="working tree")
3003
def initialize(self, controldir, revision_id=None, from_branch=None,
3032
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3004
3033
accelerator_tree=None, hardlink=False):
3005
"""Initialize a new working tree in controldir.
3034
"""Initialize a new working tree in a_bzrdir.
3007
:param controldir: ControlDir to initialize the working tree in.
3036
:param a_bzrdir: BzrDir to initialize the working tree in.
3008
3037
:param revision_id: allows creating a working tree at a different
3009
3038
revision than the branch is at.
3010
3039
:param from_branch: Branch to checkout
3091
3120
def unregister_format(klass, format):
3092
3121
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
3124
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3104
3125
"bzrlib.workingtree_4", "WorkingTreeFormat4")