72
# Explicitly import bzrlib.bzrdir so that the BzrProber
73
# is guaranteed to be registered.
73
from bzrlib import symbol_versioning
79
74
from bzrlib.decorators import needs_read_lock, needs_write_lock
80
from bzrlib.i18n import gettext
81
75
from bzrlib.lock import LogicalLockResult
82
76
import bzrlib.mutabletree
83
77
from bzrlib.mutabletree import needs_tree_write_lock
198
193
self._branch = self.bzrdir.open_branch()
199
194
self.basedir = realpath(basedir)
200
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()
201
218
self._rules_searcher = None
202
219
self.views = self._make_views()
222
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()
224
252
branch = property(
225
253
fget=lambda self: self._branch,
226
254
doc="""The branch this WorkingTree is connected to.
229
257
the working tree has been constructed from.
232
def has_versioned_directories(self):
233
"""See `Tree.has_versioned_directories`."""
234
return self._format.supports_versioned_directories
236
def _supports_executable(self):
237
if sys.platform == 'win32':
239
# FIXME: Ideally this should check the file system
242
260
def break_lock(self):
243
261
"""Break a lock if one is present from another instance.
261
280
def supports_views(self):
262
281
return self.views.supports_views()
264
def get_config_stack(self):
265
"""Retrieve the config stack for this tree.
267
:return: A ``bzrlib.config.Stack``
269
# For the moment, just provide the branch config stack.
270
return self.branch.get_config_stack()
273
284
def open(path=None, _unsupported=False):
274
285
"""Open an existing working tree at path.
384
395
return True, tree
385
396
t = transport.get_transport(location)
386
iterator = controldir.ControlDir.find_bzrdirs(t, evaluate=evaluate,
397
iterator = bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate,
387
398
list_current=list_current)
388
399
return [tr for tr in iterator if tr is not None]
401
def all_file_ids(self):
402
"""See Tree.iter_all_file_ids"""
403
raise NotImplementedError(self.all_file_ids)
390
405
def __repr__(self):
391
406
return "<%s of %s>" % (self.__class__.__name__,
392
407
getattr(self, 'basedir', None))
507
522
raise NotImplementedError(self.get_root_id)
510
def clone(self, to_controldir, revision_id=None):
525
def clone(self, to_bzrdir, revision_id=None):
511
526
"""Duplicate this working tree into to_bzr, including all state.
513
528
Specifically modified files are kept as modified, but
514
529
ignored and unknown files are discarded.
516
If you want to make a new line of development, see ControlDir.sprout()
531
If you want to make a new line of development, see bzrdir.sprout()
519
534
If not None, the cloned tree will have its last revision set to
535
550
# TODO now merge from tree.last_revision to revision (to preserve
536
551
# user local changes)
537
552
merge.transform_tree(tree, self)
538
if revision_id == _mod_revision.NULL_REVISION:
541
new_parents = [revision_id]
542
tree.set_parent_ids(new_parents)
553
tree.set_parent_ids([revision_id])
544
555
def id2abspath(self, file_id):
545
556
return self.abspath(self.id2path(file_id))
755
770
@needs_tree_write_lock
756
771
def set_merge_modified(self, modified_hashes):
757
"""Set the merge modified hashes."""
758
raise NotImplementedError(self.set_merge_modified)
773
for file_id, hash in modified_hashes.iteritems():
774
yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
776
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
760
778
def _sha_from_stat(self, path, stat_result):
761
779
"""Get a sha digest from the tree's stat cache.
788
def _put_rio(self, filename, stanzas, header):
789
self._must_be_locked()
790
my_file = _mod_rio.rio_file(stanzas, header)
791
self._transport.put_file(filename, my_file,
792
mode=self.bzrdir._get_file_mode())
770
794
@needs_write_lock # because merge pulls data into the branch.
771
795
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
772
796
merge_type=None, force=False):
1012
1036
show_base=show_base)
1013
1037
basis_root_id = basis_tree.get_root_id()
1014
1038
new_root_id = new_basis_tree.get_root_id()
1015
if new_root_id is not None and basis_root_id != new_root_id:
1039
if basis_root_id != new_root_id:
1016
1040
self.set_root_id(new_root_id)
1018
1042
basis_tree.unlock()
1019
1043
# TODO - dedup parents list with things merged by pull ?
1020
1044
# reuse the revisiontree we merged against to set the new
1023
if self.branch.last_revision() != _mod_revision.NULL_REVISION:
1024
parent_trees.append(
1025
(self.branch.last_revision(), new_basis_tree))
1046
parent_trees = [(self.branch.last_revision(), new_basis_tree)]
1026
1047
# we have to pull the merge trees out again, because
1027
1048
# merge_inner has set the ids. - this corner is not yet
1028
1049
# layered well enough to prevent double handling.
1163
1188
:return: A bzrlib.lock.LogicalLockResult.
1165
raise NotImplementedError(self.lock_read)
1190
if not self.is_locked():
1192
self.branch.lock_read()
1194
self._control_files.lock_read()
1195
return LogicalLockResult(self.unlock)
1197
self.branch.unlock()
1167
1200
def lock_tree_write(self):
1168
1201
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1170
1203
:return: A bzrlib.lock.LogicalLockResult.
1172
raise NotImplementedError(self.lock_tree_write)
1205
if not self.is_locked():
1207
self.branch.lock_read()
1209
self._control_files.lock_write()
1210
return LogicalLockResult(self.unlock)
1212
self.branch.unlock()
1174
1215
def lock_write(self):
1175
1216
"""See MutableTree.lock_write, and WorkingTree.unlock.
1177
1218
:return: A bzrlib.lock.LogicalLockResult.
1179
raise NotImplementedError(self.lock_write)
1220
if not self.is_locked():
1222
self.branch.lock_write()
1224
self._control_files.lock_write()
1225
return LogicalLockResult(self.unlock)
1227
self.branch.unlock()
1181
1230
def get_physical_lock_status(self):
1182
raise NotImplementedError(self.get_physical_lock_status)
1231
return self._control_files.get_physical_lock_status()
1233
def _reset_data(self):
1234
"""Reset transient data that cannot be revalidated."""
1235
raise NotImplementedError(self._reset_data)
1184
1237
def set_last_revision(self, new_revision):
1185
1238
"""Change the last revision in the working tree."""
1527
1580
last_rev = parent_trees[0][0]
1528
1581
return nb_conflicts
1583
def _write_hashcache_if_dirty(self):
1584
"""Write out the hashcache if it is dirty."""
1585
if self._hashcache.needs_write:
1587
self._hashcache.write()
1589
if e.errno not in (errno.EPERM, errno.EACCES):
1591
# TODO: jam 20061219 Should this be a warning? A single line
1592
# warning might be sufficient to let the user know what
1594
mutter('Could not write hashcache for %s\nError: %s',
1595
self._hashcache.cache_file_name(), e)
1530
1597
def set_conflicts(self, arg):
1531
1598
raise errors.UnsupportedOperation(self.set_conflicts, self)
1761
1828
:param branch: A branch to override probing for the branch.
1763
1830
super(InventoryWorkingTree, self).__init__(basedir=basedir,
1764
branch=branch, _transport=_control_files._transport,
1765
_internal=_internal, _format=_format, _bzrdir=_bzrdir)
1767
self._control_files = _control_files
1768
self._detect_case_handling()
1831
branch=branch, _control_files=_control_files, _internal=_internal,
1832
_format=_format, _bzrdir=_bzrdir)
1770
1834
if _inventory is None:
1771
1835
# This will be acquired on lock_read() or lock_write()
1791
1855
self._inventory = inv
1792
1856
self._inventory_is_modified = dirty
1794
def _detect_case_handling(self):
1795
wt_trans = self.bzrdir.get_workingtree_transport(None)
1797
wt_trans.stat(self._format.case_sensitive_filename)
1798
except errors.NoSuchFile:
1799
self.case_sensitive = True
1801
self.case_sensitive = False
1803
self._setup_directory_is_tree_reference()
1805
1858
def _serialize(self, inventory, out_file):
1806
1859
xml5.serializer_v5.write_inventory(self._inventory, out_file,
1809
1862
def _deserialize(selt, in_file):
1810
1863
return xml5.serializer_v5.read_inventory(in_file)
1812
def break_lock(self):
1813
"""Break a lock if one is present from another instance.
1815
Uses the ui factory to ask for confirmation if the lock may be from
1818
This will probe the repository for its lock as well.
1820
self._control_files.break_lock()
1821
self.branch.break_lock()
1823
def is_locked(self):
1824
return self._control_files.is_locked()
1826
def _must_be_locked(self):
1827
if not self.is_locked():
1828
raise errors.ObjectNotLocked(self)
1830
def lock_read(self):
1831
"""Lock the tree for reading.
1833
This also locks the branch, and can be unlocked via self.unlock().
1835
:return: A bzrlib.lock.LogicalLockResult.
1837
if not self.is_locked():
1839
self.branch.lock_read()
1841
self._control_files.lock_read()
1842
return LogicalLockResult(self.unlock)
1844
self.branch.unlock()
1847
def lock_tree_write(self):
1848
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1850
:return: A bzrlib.lock.LogicalLockResult.
1852
if not self.is_locked():
1854
self.branch.lock_read()
1856
self._control_files.lock_write()
1857
return LogicalLockResult(self.unlock)
1859
self.branch.unlock()
1862
def lock_write(self):
1863
"""See MutableTree.lock_write, and WorkingTree.unlock.
1865
:return: A bzrlib.lock.LogicalLockResult.
1867
if not self.is_locked():
1869
self.branch.lock_write()
1871
self._control_files.lock_write()
1872
return LogicalLockResult(self.unlock)
1874
self.branch.unlock()
1877
def get_physical_lock_status(self):
1878
return self._control_files.get_physical_lock_status()
1880
1865
@needs_tree_write_lock
1881
1866
def _write_inventory(self, inv):
1882
1867
"""Write inventory as the current inventory."""
2078
2067
def has_id(self, file_id):
2079
2068
# files that have been deleted are excluded
2080
inv, inv_file_id = self._unpack_file_id(file_id)
2081
if not inv.has_id(inv_file_id):
2069
inv = self.inventory
2070
if not inv.has_id(file_id):
2083
path = inv.id2path(inv_file_id)
2072
path = inv.id2path(file_id)
2084
2073
return osutils.lexists(self.abspath(path))
2086
2075
def has_or_had_id(self, file_id):
2087
2076
if file_id == self.inventory.root.file_id:
2089
inv, inv_file_id = self._unpack_file_id(file_id)
2090
return inv.has_id(inv_file_id)
2078
return self.inventory.has_id(file_id)
2092
def all_file_ids(self):
2080
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
2093
2082
"""Iterate through file_ids for this tree.
2095
2084
file_ids are in a WorkingTree if they are in the working inventory
2096
2085
and the working file exists.
2099
for path, ie in self.iter_entries_by_dir():
2087
inv = self._inventory
2088
for path, ie in inv.iter_entries():
2089
if osutils.lexists(self.abspath(path)):
2103
2092
@needs_tree_write_lock
2104
2093
def set_last_revision(self, new_revision):
2175
2164
mode=self.bzrdir._get_file_mode())
2176
2165
self._inventory_is_modified = False
2168
def get_file_sha1(self, file_id, path=None, stat_value=None):
2170
path = self._inventory.id2path(file_id)
2171
return self._hashcache.get_sha1(path, stat_value)
2178
2173
def get_file_mtime(self, file_id, path=None):
2179
2174
"""See Tree.get_file_mtime."""
2181
path = self.id2path(file_id)
2183
return os.lstat(self.abspath(path)).st_mtime
2185
if e.errno == errno.ENOENT:
2186
raise errors.FileTimestampUnavailable(path)
2176
path = self.inventory.id2path(file_id)
2177
return os.lstat(self.abspath(path)).st_mtime
2189
2179
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2190
inv, file_id = self._path2inv_file_id(path)
2180
file_id = self.path2id(path)
2191
2181
if file_id is None:
2192
2182
# For unversioned files on win32, we just assume they are not
2195
return inv[file_id].executable
2185
return self._inventory[file_id].executable
2197
2187
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
2198
2188
mode = stat_result.st_mode
2199
2189
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
2201
def is_executable(self, file_id, path=None):
2202
if not self._supports_executable():
2203
inv, inv_file_id = self._unpack_file_id(file_id)
2204
return inv[inv_file_id].executable
2191
if not supports_executable():
2192
def is_executable(self, file_id, path=None):
2193
return self._inventory[file_id].executable
2195
_is_executable_from_path_and_stat = \
2196
_is_executable_from_path_and_stat_from_basis
2198
def is_executable(self, file_id, path=None):
2207
2200
path = self.id2path(file_id)
2208
2201
mode = os.lstat(self.abspath(path)).st_mode
2209
2202
return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
2211
def _is_executable_from_path_and_stat(self, path, stat_result):
2212
if not self._supports_executable():
2213
return self._is_executable_from_path_and_stat_from_basis(path, stat_result)
2215
return self._is_executable_from_path_and_stat_from_stat(path, stat_result)
2204
_is_executable_from_path_and_stat = \
2205
_is_executable_from_path_and_stat_from_stat
2217
2207
@needs_tree_write_lock
2218
2208
def _add(self, files, ids, kinds):
2268
2258
parent_tree = self.branch.repository.revision_tree(parent_id)
2269
2259
parent_tree.lock_read()
2272
kind = parent_tree.kind(file_id)
2273
except errors.NoSuchId:
2261
if not parent_tree.has_id(file_id):
2263
ie = parent_tree.inventory[file_id]
2264
if ie.kind != 'file':
2276
2265
# Note: this is slightly unnecessary, because symlinks and
2277
2266
# directories have a "text" which is the empty text, and we
2278
2267
# know that won't mess up annotations. But it seems cleaner
2281
file_id, parent_tree.get_file_revision(file_id))
2269
parent_text_key = (file_id, ie.revision)
2282
2270
if parent_text_key not in maybe_file_parent_keys:
2283
2271
maybe_file_parent_keys.append(parent_text_key)
2299
2287
for key, line in annotator.annotate_flat(this_key)]
2300
2288
return annotations
2302
def _put_rio(self, filename, stanzas, header):
2303
self._must_be_locked()
2304
my_file = _mod_rio.rio_file(stanzas, header)
2305
self._transport.put_file(filename, my_file,
2306
mode=self.bzrdir._get_file_mode())
2308
@needs_tree_write_lock
2309
def set_merge_modified(self, modified_hashes):
2311
for file_id, hash in modified_hashes.iteritems():
2312
yield _mod_rio.Stanza(file_id=file_id.decode('utf8'),
2314
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
2316
2290
@needs_read_lock
2317
2291
def merge_modified(self):
2318
2292
"""Return a dictionary of files modified by a merge.
2338
2312
for s in _mod_rio.RioReader(hashfile):
2339
2313
# RioReader reads in Unicode, so convert file_ids back to utf8
2340
2314
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2341
if not self.has_id(file_id):
2315
if not self.inventory.has_id(file_id):
2343
2317
text_hash = s.get("hash")
2344
2318
if text_hash == self.get_file_sha1(file_id):
2423
2397
tree_transport = self.bzrdir.root_transport.clone(sub_path)
2424
2398
if tree_transport.base != branch_transport.base:
2425
2399
tree_bzrdir = format.initialize_on_transport(tree_transport)
2426
tree_bzrdir.set_branch_reference(new_branch)
2400
branch.BranchReferenceFormat().initialize(tree_bzrdir,
2401
target_branch=new_branch)
2428
2403
tree_bzrdir = branch_bzrdir
2429
2404
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
2454
2429
if not self.is_locked():
2455
2430
raise errors.ObjectNotLocked(self)
2432
inv = self.inventory
2457
2433
if from_dir is None and include_root is True:
2458
yield ('', 'V', 'directory', self.get_root_id(), self.inventory.root)
2434
yield ('', 'V', 'directory', inv.root.file_id, inv.root)
2459
2435
# Convert these into local objects to save lookup times
2460
2436
pathjoin = osutils.pathjoin
2461
2437
file_kind = self._kind
2469
2445
# directory file_id, relative path, absolute path, reverse sorted children
2470
2446
if from_dir is not None:
2471
inv, from_dir_id = self._path2inv_file_id(from_dir)
2447
from_dir_id = inv.path2id(from_dir)
2472
2448
if from_dir_id is None:
2473
2449
# Directory not versioned
2475
2451
from_dir_abspath = pathjoin(self.basedir, from_dir)
2477
inv = self.inventory
2478
2453
from_dir_id = inv.root.file_id
2479
2454
from_dir_abspath = self.basedir
2480
2455
children = os.listdir(from_dir_abspath)
2616
2592
if not self.has_filename(to_dir):
2617
2593
raise errors.BzrMoveFailedError('',to_dir,
2618
2594
errors.NotInWorkingDirectory(to_dir))
2619
to_inv, to_dir_id = self._path2inv_file_id(to_dir)
2595
to_dir_id = inv.path2id(to_dir)
2620
2596
if to_dir_id is None:
2621
2597
raise errors.BzrMoveFailedError('',to_dir,
2622
2598
errors.NotVersionedError(path=to_dir))
2624
to_dir_ie = to_inv[to_dir_id]
2600
to_dir_ie = inv[to_dir_id]
2625
2601
if to_dir_ie.kind != 'directory':
2626
2602
raise errors.BzrMoveFailedError('',to_dir,
2627
2603
errors.NotADirectory(to_abs))
2629
2605
# create rename entries and tuples
2630
2606
for from_rel in from_paths:
2631
2607
from_tail = splitpath(from_rel)[-1]
2632
from_inv, from_id = self._path2inv_file_id(from_rel)
2608
from_id = inv.path2id(from_rel)
2633
2609
if from_id is None:
2634
2610
raise errors.BzrMoveFailedError(from_rel,to_dir,
2635
2611
errors.NotVersionedError(path=from_rel))
2637
from_entry = from_inv[from_id]
2613
from_entry = inv[from_id]
2638
2614
from_parent_id = from_entry.parent_id
2639
2615
to_rel = pathjoin(to_dir, from_tail)
2640
2616
rename_entry = InventoryWorkingTree._RenameEntry(
2687
2662
Everything else results in an error.
2664
inv = self.inventory
2689
2665
rename_entries = []
2691
2667
# create rename entries and tuples
2692
2668
from_tail = splitpath(from_rel)[-1]
2693
from_inv, from_id = self._path2inv_file_id(from_rel)
2669
from_id = inv.path2id(from_rel)
2694
2670
if from_id is None:
2695
2671
# if file is missing in the inventory maybe it's in the basis_tree
2696
2672
basis_tree = self.branch.basis_tree()
2700
2676
errors.NotVersionedError(path=from_rel))
2701
2677
# put entry back in the inventory so we can rename it
2702
2678
from_entry = basis_tree.inventory[from_id].copy()
2703
from_inv.add(from_entry)
2705
from_inv, from_inv_id = self._unpack_file_id(from_id)
2706
from_entry = from_inv[from_inv_id]
2681
from_entry = inv[from_id]
2707
2682
from_parent_id = from_entry.parent_id
2708
2683
to_dir, to_tail = os.path.split(to_rel)
2709
to_inv, to_dir_id = self._path2inv_file_id(to_dir)
2684
to_dir_id = inv.path2id(to_dir)
2710
2685
rename_entry = InventoryWorkingTree._RenameEntry(from_rel=from_rel,
2711
2686
from_id=from_id,
2712
2687
from_tail=from_tail,
2734
2709
from_id, from_rel, to_rel, to_dir, to_dir_id)
2736
2711
self._move(rename_entries)
2737
self._write_inventory(to_inv)
2712
self._write_inventory(inv)
2739
2714
class _RenameEntry(object):
2740
2715
def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2807
2782
# something is wrong, so lets determine what exactly
2808
2783
if not self.has_filename(from_rel) and \
2809
2784
not self.has_filename(to_rel):
2810
raise errors.BzrRenameFailedError(from_rel, to_rel,
2811
errors.PathsDoNotExist(paths=(from_rel, to_rel)))
2785
raise errors.BzrRenameFailedError(from_rel,to_rel,
2786
errors.PathsDoNotExist(paths=(str(from_rel),
2813
2789
raise errors.RenameFailedFilesExist(from_rel, to_rel)
2814
2790
rename_entry.only_change_inv = only_change_inv
2977
2955
if dir[2] == _directory:
2978
2956
pending.append(dir)
2981
def update_feature_flags(self, updated_flags):
2982
"""Update the feature flags for this branch.
2984
:param updated_flags: Dictionary mapping feature names to necessities
2985
A necessity can be None to indicate the feature should be removed
2987
self._format._update_feature_flags(updated_flags)
2988
self.control_transport.put_bytes('format', self._format.as_string())
2991
2959
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
2992
2960
"""Registry for working tree formats."""
3049
3017
supports_versioned_directories = None
3051
def initialize(self, controldir, revision_id=None, from_branch=None,
3020
def find_format_string(klass, a_bzrdir):
3021
"""Return format name for the working tree object in a_bzrdir."""
3023
transport = a_bzrdir.get_workingtree_transport(None)
3024
return transport.get_bytes("format")
3025
except errors.NoSuchFile:
3026
raise errors.NoWorkingTree(base=transport.base)
3029
def find_format(klass, a_bzrdir):
3030
"""Return the format for the working tree object in a_bzrdir."""
3032
format_string = klass.find_format_string(a_bzrdir)
3033
format_string = bzrdir.extract_format_string(format_string)
3034
return format_registry.get(format_string)
3036
raise errors.UnknownFormatError(format=format_string,
3037
kind="working tree")
3039
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
3052
3040
accelerator_tree=None, hardlink=False):
3053
"""Initialize a new working tree in controldir.
3041
"""Initialize a new working tree in a_bzrdir.
3055
:param controldir: ControlDir to initialize the working tree in.
3043
:param a_bzrdir: BzrDir to initialize the working tree in.
3056
3044
:param revision_id: allows creating a working tree at a different
3057
3045
revision than the branch is at.
3058
3046
:param from_branch: Branch to checkout
3078
3066
"""Return the current default format."""
3079
3067
return format_registry.get_default()
3069
def get_format_string(self):
3070
"""Return the ASCII format string that identifies this format."""
3071
raise NotImplementedError(self.get_format_string)
3081
3073
def get_format_description(self):
3082
3074
"""Return the short description for this format."""
3083
3075
raise NotImplementedError(self.get_format_description)
3135
3127
def unregister_format(klass, format):
3136
3128
format_registry.remove(format)
3138
def get_controldir_for_branch(self):
3139
"""Get the control directory format for creating branches.
3141
This is to support testing of working tree formats that can not exist
3142
in the same control directory as a branch.
3144
return self._matchingbzrdir
3147
class WorkingTreeFormatMetaDir(bzrdir.BzrFormat, WorkingTreeFormat):
3148
"""Base class for working trees that live in bzr meta directories."""
3151
WorkingTreeFormat.__init__(self)
3152
bzrdir.BzrFormat.__init__(self)
3155
def find_format_string(klass, controldir):
3156
"""Return format name for the working tree object in controldir."""
3158
transport = controldir.get_workingtree_transport(None)
3159
return transport.get_bytes("format")
3160
except errors.NoSuchFile:
3161
raise errors.NoWorkingTree(base=transport.base)
3164
def find_format(klass, controldir):
3165
"""Return the format for the working tree object in controldir."""
3166
format_string = klass.find_format_string(controldir)
3167
return klass._find_format(format_registry, 'working tree',
3170
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
3172
WorkingTreeFormat.check_support_status(self,
3173
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
3175
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
3176
recommend_upgrade=recommend_upgrade, basedir=basedir)
3179
3131
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3180
3132
"bzrlib.workingtree_4", "WorkingTreeFormat4")