261
261
def supports_views(self):
262
262
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()
265
273
def open(path=None, _unsupported=False):
266
274
"""Open an existing working tree at path.
379
387
list_current=list_current)
380
388
return [tr for tr in iterator if tr is not None]
382
def all_file_ids(self):
383
"""See Tree.iter_all_file_ids"""
384
raise NotImplementedError(self.all_file_ids)
386
390
def __repr__(self):
387
391
return "<%s of %s>" % (self.__class__.__name__,
388
392
getattr(self, 'basedir', None))
1946
1950
if entry.parent_id == orig_root_id:
1947
1951
entry.parent_id = inv.root.file_id
1949
def all_file_ids(self):
1950
"""See Tree.iter_all_file_ids"""
1951
return set(self.inventory)
1953
1953
@needs_tree_write_lock
1954
1954
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
1955
1955
"""See MutableTree.set_parent_trees."""
1974
1974
# parent tree from the repository.
1975
1975
self._cache_basis_inventory(leftmost_parent_id)
1977
inv = leftmost_parent_tree.inventory
1977
inv = leftmost_parent_tree.root_inventory
1978
1978
xml = self._create_basis_xml_from_inventory(
1979
1979
leftmost_parent_id, inv)
1980
1980
self._write_basis_inventory(xml)
2078
2078
def has_id(self, file_id):
2079
2079
# files that have been deleted are excluded
2080
inv = self.inventory
2081
if not inv.has_id(file_id):
2080
inv, inv_file_id = self._unpack_file_id(file_id)
2081
if not inv.has_id(inv_file_id):
2083
path = inv.id2path(file_id)
2083
path = inv.id2path(inv_file_id)
2084
2084
return osutils.lexists(self.abspath(path))
2086
2086
def has_or_had_id(self, file_id):
2087
if file_id == self.inventory.root.file_id:
2087
if file_id == self.get_root_id():
2089
return self.inventory.has_id(file_id)
2089
inv, inv_file_id = self._unpack_file_id(file_id)
2090
return inv.has_id(inv_file_id)
2091
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4, 0)))
2092
def all_file_ids(self):
2093
2093
"""Iterate through file_ids for this tree.
2095
2095
file_ids are in a WorkingTree if they are in the working inventory
2096
2096
and the working file exists.
2098
inv = self._inventory
2099
for path, ie in inv.iter_entries():
2100
if osutils.lexists(self.abspath(path)):
2099
for path, ie in self.iter_entries_by_dir():
2103
2103
@needs_tree_write_lock
2104
2104
def set_last_revision(self, new_revision):
2160
2160
_mod_revision.NULL_REVISION)
2162
2162
rt = self.branch.repository.revision_tree(revision_ids[0])
2163
self._write_inventory(rt.inventory)
2163
self._write_inventory(rt.root_inventory)
2164
2164
self.set_parent_ids(revision_ids)
2166
2166
def flush(self):
2178
2178
def get_file_mtime(self, file_id, path=None):
2179
2179
"""See Tree.get_file_mtime."""
2181
path = self.inventory.id2path(file_id)
2181
path = self.id2path(file_id)
2183
2183
return os.lstat(self.abspath(path)).st_mtime
2184
2184
except OSError, e:
2189
2189
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
2190
file_id = self.path2id(path)
2190
inv, file_id = self._path2inv_file_id(path)
2191
2191
if file_id is None:
2192
2192
# For unversioned files on win32, we just assume they are not
2195
return self._inventory[file_id].executable
2195
return inv[file_id].executable
2197
2197
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
2198
2198
mode = stat_result.st_mode
2201
2201
def is_executable(self, file_id, path=None):
2202
2202
if not self._supports_executable():
2203
return self._inventory[file_id].executable
2203
inv, inv_file_id = self._unpack_file_id(file_id)
2204
return inv[inv_file_id].executable
2206
2207
path = self.id2path(file_id)
2220
2221
# should probably put it back with the previous ID.
2221
2222
# the read and write working inventory should not occur in this
2222
2223
# function - they should be part of lock_write and unlock.
2223
inv = self.inventory
2224
# FIXME: nested trees
2225
inv = self.root_inventory
2224
2226
for f, file_id, kind in zip(files, ids, kinds):
2225
2227
if file_id is None:
2226
2228
inv.add_path(f, kind=kind)
2267
2269
parent_tree = self.branch.repository.revision_tree(parent_id)
2268
2270
parent_tree.lock_read()
2270
if not parent_tree.has_id(file_id):
2273
kind = parent_tree.kind(file_id)
2274
except errors.NoSuchId:
2272
ie = parent_tree.inventory[file_id]
2273
if ie.kind != 'file':
2274
2277
# Note: this is slightly unnecessary, because symlinks and
2275
2278
# directories have a "text" which is the empty text, and we
2276
2279
# know that won't mess up annotations. But it seems cleaner
2278
parent_text_key = (file_id, ie.revision)
2282
file_id, parent_tree.get_file_revision(file_id))
2279
2283
if parent_text_key not in maybe_file_parent_keys:
2280
2284
maybe_file_parent_keys.append(parent_text_key)
2335
2339
for s in _mod_rio.RioReader(hashfile):
2336
2340
# RioReader reads in Unicode, so convert file_ids back to utf8
2337
2341
file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
2338
if not self.inventory.has_id(file_id):
2342
if not self.has_id(file_id):
2340
2344
text_hash = s.get("hash")
2341
2345
if text_hash == self.get_file_sha1(file_id):
2371
2375
other_tree.lock_tree_write()
2373
2377
new_parents = other_tree.get_parent_ids()
2374
other_root = other_tree.inventory.root
2378
other_root = other_tree.root_inventory.root
2375
2379
other_root.parent_id = new_root_parent
2376
2380
other_root.name = osutils.basename(other_tree_path)
2377
self.inventory.add(other_root)
2378
add_children(self.inventory, other_root)
2379
self._write_inventory(self.inventory)
2381
self.root_inventory.add(other_root)
2382
add_children(self.root_inventory, other_root)
2383
self._write_inventory(self.root_inventory)
2380
2384
# normally we don't want to fetch whole repositories, but i think
2381
2385
# here we really do want to consolidate the whole thing.
2382
2386
for parent_id in other_tree.get_parent_ids():
2425
2429
tree_bzrdir = branch_bzrdir
2426
2430
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
2427
2431
wt.set_parent_ids(self.get_parent_ids())
2428
my_inv = self.inventory
2432
# FIXME: Support nested trees
2433
my_inv = self.root_inventory
2429
2434
child_inv = inventory.Inventory(root_id=None)
2430
2435
new_root = my_inv[file_id]
2431
2436
my_inv.remove_recursive_id(file_id)
2451
2456
if not self.is_locked():
2452
2457
raise errors.ObjectNotLocked(self)
2454
inv = self.inventory
2455
2459
if from_dir is None and include_root is True:
2456
yield ('', 'V', 'directory', inv.root.file_id, inv.root)
2460
yield ('', 'V', 'directory', self.get_root_id(), self.root_inventory.root)
2457
2461
# Convert these into local objects to save lookup times
2458
2462
pathjoin = osutils.pathjoin
2459
2463
file_kind = self._kind
2467
2471
# directory file_id, relative path, absolute path, reverse sorted children
2468
2472
if from_dir is not None:
2469
from_dir_id = inv.path2id(from_dir)
2473
inv, from_dir_id = self._path2inv_file_id(from_dir)
2470
2474
if from_dir_id is None:
2471
2475
# Directory not versioned
2473
2477
from_dir_abspath = pathjoin(self.basedir, from_dir)
2479
inv = self.root_inventory
2475
2480
from_dir_id = inv.root.file_id
2476
2481
from_dir_abspath = self.basedir
2477
2482
children = os.listdir(from_dir_abspath)
2600
2605
rename_entries = []
2601
2606
rename_tuples = []
2608
invs_to_write = set()
2603
2610
# check for deprecated use of signature
2604
2611
if to_dir is None:
2605
2612
raise TypeError('You must supply a target directory')
2606
2613
# check destination directory
2607
2614
if isinstance(from_paths, basestring):
2608
2615
raise ValueError()
2609
inv = self.inventory
2610
2616
to_abs = self.abspath(to_dir)
2611
2617
if not isdir(to_abs):
2612
2618
raise errors.BzrMoveFailedError('',to_dir,
2614
2620
if not self.has_filename(to_dir):
2615
2621
raise errors.BzrMoveFailedError('',to_dir,
2616
2622
errors.NotInWorkingDirectory(to_dir))
2617
to_dir_id = inv.path2id(to_dir)
2623
to_inv, to_dir_id = self._path2inv_file_id(to_dir)
2618
2624
if to_dir_id is None:
2619
2625
raise errors.BzrMoveFailedError('',to_dir,
2620
2626
errors.NotVersionedError(path=to_dir))
2622
to_dir_ie = inv[to_dir_id]
2628
to_dir_ie = to_inv[to_dir_id]
2623
2629
if to_dir_ie.kind != 'directory':
2624
2630
raise errors.BzrMoveFailedError('',to_dir,
2625
2631
errors.NotADirectory(to_abs))
2627
2633
# create rename entries and tuples
2628
2634
for from_rel in from_paths:
2629
2635
from_tail = splitpath(from_rel)[-1]
2630
from_id = inv.path2id(from_rel)
2636
from_inv, from_id = self._path2inv_file_id(from_rel)
2631
2637
if from_id is None:
2632
2638
raise errors.BzrMoveFailedError(from_rel,to_dir,
2633
2639
errors.NotVersionedError(path=from_rel))
2635
from_entry = inv[from_id]
2641
from_entry = from_inv[from_id]
2636
2642
from_parent_id = from_entry.parent_id
2637
2643
to_rel = pathjoin(to_dir, from_tail)
2638
2644
rename_entry = InventoryWorkingTree._RenameEntry(
2657
2663
# restore the inventory on error
2658
2664
self._inventory_is_modified = original_modified
2660
self._write_inventory(inv)
2666
#FIXME: Should potentially also write the from_invs
2667
self._write_inventory(to_inv)
2661
2668
return rename_tuples
2663
2670
@needs_tree_write_lock
2684
2691
Everything else results in an error.
2686
inv = self.inventory
2687
2693
rename_entries = []
2689
2695
# create rename entries and tuples
2690
2696
from_tail = splitpath(from_rel)[-1]
2691
from_id = inv.path2id(from_rel)
2697
from_inv, from_id = self._path2inv_file_id(from_rel)
2692
2698
if from_id is None:
2693
2699
# if file is missing in the inventory maybe it's in the basis_tree
2694
2700
basis_tree = self.branch.basis_tree()
2697
2703
raise errors.BzrRenameFailedError(from_rel,to_rel,
2698
2704
errors.NotVersionedError(path=from_rel))
2699
2705
# put entry back in the inventory so we can rename it
2700
from_entry = basis_tree.inventory[from_id].copy()
2706
from_entry = basis_tree.root_inventory[from_id].copy()
2707
from_inv.add(from_entry)
2703
from_entry = inv[from_id]
2709
from_inv, from_inv_id = self._unpack_file_id(from_id)
2710
from_entry = from_inv[from_inv_id]
2704
2711
from_parent_id = from_entry.parent_id
2705
2712
to_dir, to_tail = os.path.split(to_rel)
2706
to_dir_id = inv.path2id(to_dir)
2713
to_inv, to_dir_id = self._path2inv_file_id(to_dir)
2707
2714
rename_entry = InventoryWorkingTree._RenameEntry(from_rel=from_rel,
2708
2715
from_id=from_id,
2709
2716
from_tail=from_tail,
2731
2738
from_id, from_rel, to_rel, to_dir, to_dir_id)
2733
2740
self._move(rename_entries)
2734
self._write_inventory(inv)
2741
self._write_inventory(to_inv)
2736
2743
class _RenameEntry(object):
2737
2744
def __init__(self, from_rel, from_id, from_tail, from_parent_id,
2754
2761
Also does basic plausability tests.
2756
inv = self.inventory
2763
# FIXME: Handling of nested trees
2764
inv = self.root_inventory
2758
2766
for rename_entry in rename_entries:
2759
2767
# store to local variables for easier reference
2845
2851
" Error message is: %s" % e)
2847
2853
def _move_entry(self, entry):
2848
inv = self.inventory
2854
inv = self.root_inventory
2849
2855
from_rel_abs = self.abspath(entry.from_rel)
2850
2856
to_rel_abs = self.abspath(entry.to_rel)
2851
2857
if from_rel_abs == to_rel_abs:
2893
2899
def stored_kind(self, file_id):
2894
2900
"""See Tree.stored_kind"""
2895
return self.inventory[file_id].kind
2901
inv, inv_file_id = self._unpack_file_id(file_id)
2902
return inv[inv_file_id].kind
2897
2904
def extras(self):
2898
2905
"""Yield all unversioned files in this WorkingTree.
2905
2912
This is the same order used by 'osutils.walkdirs'.
2907
2914
## TODO: Work from given directory downwards
2908
for path, dir_entry in self.inventory.directories():
2915
for path, dir_entry in self.iter_entries_by_dir():
2916
if dir_entry.kind != 'directory':
2909
2918
# mutter("search for unknowns in %r", path)
2910
2919
dirabs = self.abspath(path)
2911
2920
if not isdir(dirabs):
3070
3078
def __ne__(self, other):
3071
3079
return not (self == other)
3074
@symbol_versioning.deprecated_method(
3075
symbol_versioning.deprecated_in((2, 4, 0)))
3076
def get_default_format(klass):
3077
"""Return the current default format."""
3078
return format_registry.get_default()
3080
3081
def get_format_description(self):
3081
3082
"""Return the short description for this format."""
3082
3083
raise NotImplementedError(self.get_format_description)
3098
3099
"""True if this format supports stored views."""
3102
@symbol_versioning.deprecated_method(
3103
symbol_versioning.deprecated_in((2, 4, 0)))
3104
def register_format(klass, format):
3105
format_registry.register(format)
3108
@symbol_versioning.deprecated_method(
3109
symbol_versioning.deprecated_in((2, 4, 0)))
3110
def register_extra_format(klass, format):
3111
format_registry.register_extra(format)
3114
@symbol_versioning.deprecated_method(
3115
symbol_versioning.deprecated_in((2, 4, 0)))
3116
def unregister_extra_format(klass, format):
3117
format_registry.unregister_extra(format)
3120
@symbol_versioning.deprecated_method(
3121
symbol_versioning.deprecated_in((2, 4, 0)))
3122
def get_formats(klass):
3123
return format_registry._get_all()
3126
@symbol_versioning.deprecated_method(
3127
symbol_versioning.deprecated_in((2, 4, 0)))
3128
def set_default_format(klass, format):
3129
format_registry.set_default(format)
3132
@symbol_versioning.deprecated_method(
3133
symbol_versioning.deprecated_in((2, 4, 0)))
3134
def unregister_format(klass, format):
3135
format_registry.remove(format)
3137
3102
def get_controldir_for_branch(self):
3138
3103
"""Get the control directory format for creating branches.