199
193
self._branch = self.bzrdir.open_branch()
200
194
self.basedir = realpath(basedir)
201
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()
202
218
self._rules_searcher = None
203
219
self.views = self._make_views()
1169
1202
:return: A bzrlib.lock.LogicalLockResult.
1171
raise NotImplementedError(self.lock_read)
1204
if not self.is_locked():
1206
self.branch.lock_read()
1208
self._control_files.lock_read()
1209
return LogicalLockResult(self.unlock)
1211
self.branch.unlock()
1173
1214
def lock_tree_write(self):
1174
1215
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1176
1217
:return: A bzrlib.lock.LogicalLockResult.
1178
raise NotImplementedError(self.lock_tree_write)
1219
if not self.is_locked():
1221
self.branch.lock_read()
1223
self._control_files.lock_write()
1224
return LogicalLockResult(self.unlock)
1226
self.branch.unlock()
1180
1229
def lock_write(self):
1181
1230
"""See MutableTree.lock_write, and WorkingTree.unlock.
1183
1232
:return: A bzrlib.lock.LogicalLockResult.
1185
raise NotImplementedError(self.lock_write)
1234
if not self.is_locked():
1236
self.branch.lock_write()
1238
self._control_files.lock_write()
1239
return LogicalLockResult(self.unlock)
1241
self.branch.unlock()
1187
1244
def get_physical_lock_status(self):
1188
raise NotImplementedError(self.get_physical_lock_status)
1245
return self._control_files.get_physical_lock_status()
1247
def _reset_data(self):
1248
"""Reset transient data that cannot be revalidated."""
1249
raise NotImplementedError(self._reset_data)
1190
1251
def set_last_revision(self, new_revision):
1191
1252
"""Change the last revision in the working tree."""
1357
1423
basis_tree.unlock()
1358
1424
return conflicts
1361
def store_uncommitted(self):
1362
"""Store uncommitted changes from the tree in the branch."""
1363
target_tree = self.basis_tree()
1364
shelf_creator = shelf.ShelfCreator(self, target_tree)
1366
if not shelf_creator.shelve_all():
1368
self.branch.store_uncommitted(shelf_creator)
1369
shelf_creator.transform()
1371
shelf_creator.finalize()
1372
note('Uncommitted changes stored in branch "%s".', self.branch.nick)
1375
def restore_uncommitted(self):
1376
"""Restore uncommitted changes from the branch into the tree."""
1377
unshelver = self.branch.get_unshelver(self)
1378
if unshelver is None:
1381
merger = unshelver.make_merger()
1382
merger.ignore_zero = True
1384
self.branch.store_uncommitted(None)
1386
unshelver.finalize()
1388
1426
def revision_tree(self, revision_id):
1389
1427
"""See Tree.revision_tree.
1694
1745
def _walkdirs(self, prefix=""):
1695
1746
"""Walk the directories of this tree.
1697
:param prefix: is used as the directrory to start with.
1698
:returns: a generator which yields items in the form::
1700
((curren_directory_path, fileid),
1701
[(file1_path, file1_name, file1_kind, None, file1_id,
1748
:prefix: is used as the directrory to start with.
1749
returns a generator which yields items in the form:
1750
((curren_directory_path, fileid),
1751
[(file1_path, file1_name, file1_kind, None, file1_id,
1704
1754
raise NotImplementedError(self._walkdirs)
1843
1904
def _deserialize(selt, in_file):
1844
1905
return xml5.serializer_v5.read_inventory(in_file)
1846
def break_lock(self):
1847
"""Break a lock if one is present from another instance.
1849
Uses the ui factory to ask for confirmation if the lock may be from
1852
This will probe the repository for its lock as well.
1854
self._control_files.break_lock()
1855
self.branch.break_lock()
1857
def is_locked(self):
1858
return self._control_files.is_locked()
1860
def _must_be_locked(self):
1861
if not self.is_locked():
1862
raise errors.ObjectNotLocked(self)
1864
def lock_read(self):
1865
"""Lock the tree for reading.
1867
This also locks the branch, and can be unlocked via self.unlock().
1869
:return: A bzrlib.lock.LogicalLockResult.
1871
if not self.is_locked():
1873
self.branch.lock_read()
1875
self._control_files.lock_read()
1876
return LogicalLockResult(self.unlock)
1878
self.branch.unlock()
1881
def lock_tree_write(self):
1882
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1884
:return: A bzrlib.lock.LogicalLockResult.
1886
if not self.is_locked():
1888
self.branch.lock_read()
1890
self._control_files.lock_write()
1891
return LogicalLockResult(self.unlock)
1893
self.branch.unlock()
1896
def lock_write(self):
1897
"""See MutableTree.lock_write, and WorkingTree.unlock.
1899
:return: A bzrlib.lock.LogicalLockResult.
1901
if not self.is_locked():
1903
self.branch.lock_write()
1905
self._control_files.lock_write()
1906
return LogicalLockResult(self.unlock)
1908
self.branch.unlock()
1911
def get_physical_lock_status(self):
1912
return self._control_files.get_physical_lock_status()
1914
1907
@needs_tree_write_lock
1915
1908
def _write_inventory(self, inv):
1916
1909
"""Write inventory as the current inventory."""
2112
2109
def has_id(self, file_id):
2113
2110
# files that have been deleted are excluded
2114
inv, inv_file_id = self._unpack_file_id(file_id)
2115
if not inv.has_id(inv_file_id):
2111
inv = self.inventory
2112
if not inv.has_id(file_id):
2117
path = inv.id2path(inv_file_id)
2114
path = inv.id2path(file_id)
2118
2115
return osutils.lexists(self.abspath(path))
2120
2117
def has_or_had_id(self, file_id):
2121
if file_id == self.get_root_id():
2118
if file_id == self.inventory.root.file_id:
2123
inv, inv_file_id = self._unpack_file_id(file_id)
2124
return inv.has_id(inv_file_id)
2126
def all_file_ids(self):
2120
return self.inventory.has_id(file_id)
2122
__contains__ = has_id
2124
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
2127
2126
"""Iterate through file_ids for this tree.
2129
2128
file_ids are in a WorkingTree if they are in the working inventory
2130
2129
and the working file exists.
2133
for path, ie in self.iter_entries_by_dir():
2131
inv = self._inventory
2132
for path, ie in inv.iter_entries():
2133
if osutils.lexists(self.abspath(path)):
2137
2136
@needs_tree_write_lock
2138
2137
def set_last_revision(self, new_revision):
2140
2139
if self._change_last_revision(new_revision):
2141
2140
self._cache_basis_inventory(new_revision)
2143
def _get_check_refs(self):
2144
"""Return the references needed to perform a check of this tree.
2146
The default implementation returns no refs, and is only suitable for
2147
trees that have no local caching and can commit on ghosts at any time.
2149
:seealso: bzrlib.check for details about check_refs.
2154
def _check(self, references):
2155
"""Check the tree for consistency.
2157
:param references: A dict with keys matching the items returned by
2158
self._get_check_refs(), and values from looking those keys up in
2161
tree_basis = self.basis_tree()
2162
tree_basis.lock_read()
2164
repo_basis = references[('trees', self.last_revision())]
2165
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2166
raise errors.BzrCheckError(
2167
"Mismatched basis inventory content.")
2173
def check_state(self):
2174
"""Check that the working state is/isn't valid."""
2175
check_refs = self._get_check_refs()
2177
for ref in check_refs:
2180
refs[ref] = self.branch.repository.revision_tree(value)
2183
2142
@needs_tree_write_lock
2184
2143
def reset_state(self, revision_ids=None):
2185
2144
"""Reset the state of the working tree.
2209
2168
mode=self.bzrdir._get_file_mode())
2210
2169
self._inventory_is_modified = False
2172
def get_file_sha1(self, file_id, path=None, stat_value=None):
2174
path = self._inventory.id2path(file_id)
2175
return self._hashcache.get_sha1(path, stat_value)
2212
2177
def get_file_mtime(self, file_id, path=None):
2213
2178
"""See Tree.get_file_mtime."""
2215
path = self.id2path(file_id)
2217
return os.lstat(self.abspath(path)).st_mtime
2219
if e.errno == errno.ENOENT:
2220
raise errors.FileTimestampUnavailable(path)
2180
path = self.inventory.id2path(file_id)
2181
return os.lstat(self.abspath(path)).st_mtime
2223
2183
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2224
inv, file_id = self._path2inv_file_id(path)
2184
file_id = self.path2id(path)
2225
2185
if file_id is None:
2226
2186
# For unversioned files on win32, we just assume they are not
2229
return inv[file_id].executable
2189
return self._inventory[file_id].executable
2231
2191
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
2232
2192
mode = stat_result.st_mode
2233
2193
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
2235
def is_executable(self, file_id, path=None):
2236
if not self._supports_executable():
2237
inv, inv_file_id = self._unpack_file_id(file_id)
2238
return inv[inv_file_id].executable
2195
if not supports_executable():
2196
def is_executable(self, file_id, path=None):
2197
return self._inventory[file_id].executable
2199
_is_executable_from_path_and_stat = \
2200
_is_executable_from_path_and_stat_from_basis
2202
def is_executable(self, file_id, path=None):
2241
2204
path = self.id2path(file_id)
2242
2205
mode = os.lstat(self.abspath(path)).st_mode
2243
2206
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
2245
def _is_executable_from_path_and_stat(self, path, stat_result):
2246
if not self._supports_executable():
2247
return self._is_executable_from_path_and_stat_from_basis(path, stat_result)
2249
return self._is_executable_from_path_and_stat_from_stat(path, stat_result)
2208
_is_executable_from_path_and_stat = \
2209
_is_executable_from_path_and_stat_from_stat
2251
2211
@needs_tree_write_lock
2252
2212
def _add(self, files, ids, kinds):
2334
2291
for key, line in annotator.annotate_flat(this_key)]
2335
2292
return annotations
2337
def _put_rio(self, filename, stanzas, header):
2338
self._must_be_locked()
2339
my_file = _mod_rio.rio_file(stanzas, header)
2340
self._transport.put_file(filename, my_file,
2341
mode=self.bzrdir._get_file_mode())
2343
@needs_tree_write_lock
2344
def set_merge_modified(self, modified_hashes):
2346
for file_id, hash in modified_hashes.iteritems():
2347
yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
2349
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
2351
2294
@needs_read_lock
2352
2295
def merge_modified(self):
2353
2296
"""Return a dictionary of files modified by a merge.
2409
2352
other_tree.lock_tree_write()
2411
2354
new_parents = other_tree.get_parent_ids()
2412
other_root = other_tree.root_inventory.root
2355
other_root = other_tree.inventory.root
2413
2356
other_root.parent_id = new_root_parent
2414
2357
other_root.name = osutils.basename(other_tree_path)
2415
self.root_inventory.add(other_root)
2416
add_children(self.root_inventory, other_root)
2417
self._write_inventory(self.root_inventory)
2358
self.inventory.add(other_root)
2359
add_children(self.inventory, other_root)
2360
self._write_inventory(self.inventory)
2418
2361
# normally we don't want to fetch whole repositories, but i think
2419
2362
# here we really do want to consolidate the whole thing.
2420
2363
for parent_id in other_tree.get_parent_ids():
2737
2679
raise errors.BzrRenameFailedError(from_rel,to_rel,
2738
2680
errors.NotVersionedError(path=from_rel))
2739
2681
# put entry back in the inventory so we can rename it
2740
from_entry = basis_tree.root_inventory[from_id].copy()
2741
from_inv.add(from_entry)
2682
from_entry = basis_tree.inventory[from_id].copy()
2743
from_inv, from_inv_id = self._unpack_file_id(from_id)
2744
from_entry = from_inv[from_inv_id]
2685
from_entry = inv[from_id]
2745
2686
from_parent_id = from_entry.parent_id
2746
2687
to_dir, to_tail = os.path.split(to_rel)
2747
to_inv, to_dir_id = self._path2inv_file_id(to_dir)
2688
to_dir_id = inv.path2id(to_dir)
2748
2689
rename_entry = InventoryWorkingTree._RenameEntry(from_rel=from_rel,
2749
2690
from_id=from_id,
2750
2691
from_tail=from_tail,
2772
2713
from_id, from_rel, to_rel, to_dir, to_dir_id)
2774
2715
self._move(rename_entries)
2775
self._write_inventory(to_inv)
2716
self._write_inventory(inv)
2777
2718
class _RenameEntry(object):
2778
2719
def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2779
to_rel, to_tail, to_parent_id, only_change_inv=False,
2720
to_rel, to_tail, to_parent_id, only_change_inv=False):
2781
2721
self.from_rel = from_rel
2782
2722
self.from_id = from_id
2783
2723
self.from_tail = from_tail
2804
2742
to_rel = rename_entry.to_rel
2805
2743
to_id = inv.path2id(to_rel)
2806
2744
only_change_inv = False
2809
2746
# check the inventory for source and destination
2810
2747
if from_id is None:
2811
2748
raise errors.BzrMoveFailedError(from_rel,to_rel,
2812
2749
errors.NotVersionedError(path=from_rel))
2813
2750
if to_id is not None:
2815
# allow it with --after but only if dest is newly added
2817
basis = self.basis_tree()
2820
if not basis.has_id(to_id):
2821
rename_entry.change_id = True
2826
raise errors.BzrMoveFailedError(from_rel,to_rel,
2827
errors.AlreadyVersionedError(path=to_rel))
2751
raise errors.BzrMoveFailedError(from_rel,to_rel,
2752
errors.AlreadyVersionedError(path=to_rel))
2829
2754
# try to determine the mode for rename (only change inv or change
2830
2755
# inv and file system)
2982
2904
def _walkdirs(self, prefix=""):
2983
2905
"""Walk the directories of this tree.
2985
:param prefix: is used as the directrory to start with.
2986
:returns: a generator which yields items in the form::
2988
((curren_directory_path, fileid),
2989
[(file1_path, file1_name, file1_kind, None, file1_id,
2907
:prefix: is used as the directrory to start with.
2908
returns a generator which yields items in the form:
2909
((curren_directory_path, fileid),
2910
[(file1_path, file1_name, file1_kind, None, file1_id,
2992
2913
_directory = 'directory'
2993
2914
# get the root in the inventory
2994
inv, top_id = self._path2inv_file_id(prefix)
2915
inv = self.inventory
2916
top_id = inv.path2id(prefix)
2995
2917
if top_id is None:
3087
2999
missing_parent_conflicts = False
3088
3000
"""If this format supports missing parent conflicts."""
3090
supports_versioned_directories = None
3092
def initialize(self, controldir, revision_id=None, from_branch=None,
3003
def find_format_string(klass, a_bzrdir):
3004
"""Return format name for the working tree object in a_bzrdir."""
3006
transport = a_bzrdir.get_workingtree_transport(None)
3007
return transport.get_bytes("format")
3008
except errors.NoSuchFile:
3009
raise errors.NoWorkingTree(base=transport.base)
3012
def find_format(klass, a_bzrdir):
3013
"""Return the format for the working tree object in a_bzrdir."""
3015
format_string = klass.find_format_string(a_bzrdir)
3016
return format_registry.get(format_string)
3018
raise errors.UnknownFormatError(format=format_string,
3019
kind="working tree")
3021
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3093
3022
accelerator_tree=None, hardlink=False):
3094
"""Initialize a new working tree in controldir.
3023
"""Initialize a new working tree in a_bzrdir.
3096
:param controldir: ControlDir to initialize the working tree in.
3025
:param a_bzrdir: BzrDir to initialize the working tree in.
3097
3026
:param revision_id: allows creating a working tree at a different
3098
3027
revision than the branch is at.
3099
3028
:param from_branch: Branch to checkout
3133
3073
"""True if this format supports stored views."""
3136
def get_controldir_for_branch(self):
3137
"""Get the control directory format for creating branches.
3139
This is to support testing of working tree formats that can not exist
3140
in the same control directory as a branch.
3142
return self._matchingbzrdir
3145
class WorkingTreeFormatMetaDir(bzrdir.BzrFormat, WorkingTreeFormat):
3146
"""Base class for working trees that live in bzr meta directories."""
3149
WorkingTreeFormat.__init__(self)
3150
bzrdir.BzrFormat.__init__(self)
3153
def find_format_string(klass, controldir):
3154
"""Return format name for the working tree object in controldir."""
3156
transport = controldir.get_workingtree_transport(None)
3157
return transport.get_bytes("format")
3158
except errors.NoSuchFile:
3159
raise errors.NoWorkingTree(base=transport.base)
3162
def find_format(klass, controldir):
3163
"""Return the format for the working tree object in controldir."""
3164
format_string = klass.find_format_string(controldir)
3165
return klass._find_format(format_registry, 'working tree',
3168
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
3170
WorkingTreeFormat.check_support_status(self,
3171
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
3173
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
3174
recommend_upgrade=recommend_upgrade, basedir=basedir)
3176
def get_controldir_for_branch(self):
3177
"""Get the control directory format for creating branches.
3179
This is to support testing of working tree formats that can not exist
3180
in the same control directory as a branch.
3182
return self._matchingbzrdir
3185
class WorkingTreeFormatMetaDir(bzrdir.BzrFormat, WorkingTreeFormat):
3186
"""Base class for working trees that live in bzr meta directories."""
3189
WorkingTreeFormat.__init__(self)
3190
bzrdir.BzrFormat.__init__(self)
3193
def find_format_string(klass, controldir):
3194
"""Return format name for the working tree object in controldir."""
3196
transport = controldir.get_workingtree_transport(None)
3197
return transport.get_bytes("format")
3198
except errors.NoSuchFile:
3199
raise errors.NoWorkingTree(base=transport.base)
3202
def find_format(klass, controldir):
3203
"""Return the format for the working tree object in controldir."""
3204
format_string = klass.find_format_string(controldir)
3205
return klass._find_format(format_registry, 'working tree',
3208
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
3210
WorkingTreeFormat.check_support_status(self,
3211
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
3213
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
3214
recommend_upgrade=recommend_upgrade, basedir=basedir)
3077
@symbol_versioning.deprecated_method(
3078
symbol_versioning.deprecated_in((2, 4, 0)))
3079
def register_format(klass, format):
3080
format_registry.register(format)
3083
@symbol_versioning.deprecated_method(
3084
symbol_versioning.deprecated_in((2, 4, 0)))
3085
def register_extra_format(klass, format):
3086
format_registry.register_extra(format)
3089
@symbol_versioning.deprecated_method(
3090
symbol_versioning.deprecated_in((2, 4, 0)))
3091
def unregister_extra_format(klass, format):
3092
format_registry.unregister_extra(format)
3095
@symbol_versioning.deprecated_method(
3096
symbol_versioning.deprecated_in((2, 4, 0)))
3097
def get_formats(klass):
3098
return format_registry._get_all()
3101
@symbol_versioning.deprecated_method(
3102
symbol_versioning.deprecated_in((2, 4, 0)))
3103
def set_default_format(klass, format):
3104
format_registry.set_default(format)
3107
@symbol_versioning.deprecated_method(
3108
symbol_versioning.deprecated_in((2, 4, 0)))
3109
def unregister_format(klass, format):
3110
format_registry.remove(format)
3217
3113
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",