210
210
self._branch = self.bzrdir.open_branch()
211
211
self.basedir = realpath(basedir)
212
# if branch is at our basedir and is a format 6 or less
213
if isinstance(self._format, WorkingTreeFormat2):
214
# share control object
215
self._control_files = self.branch.control_files
217
# assume all other formats have their own control files.
218
self._control_files = _control_files
212
self._control_files = _control_files
219
213
self._transport = self._control_files._transport
220
214
# update the whole cache up front and write to disk if anything changed;
221
215
# in the future we might want to do this more selectively
353
347
return control.open_workingtree(), relpath
356
def open_containing_paths(file_list, default_directory='.',
357
canonicalize=True, apply_view=True):
350
def open_containing_paths(file_list, default_directory=None,
351
canonicalize=True, apply_view=True):
358
352
"""Open the WorkingTree that contains a set of paths.
360
354
Fail if the paths given are not all in a single tree.
375
371
view_str = views.view_display_str(view_files)
376
372
note("Ignoring files outside view. View is %s" % view_str)
377
373
return tree, file_list
378
tree = WorkingTree.open_containing(file_list[0])[0]
374
if default_directory == u'.':
377
seed = default_directory
378
file_list = [osutils.pathjoin(default_directory, f)
380
tree = WorkingTree.open_containing(seed)[0]
379
381
return tree, tree.safe_relpath_files(file_list, canonicalize,
380
apply_view=apply_view)
382
apply_view=apply_view)
382
384
def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
383
385
"""Convert file_list into a list of relpaths in tree.
2078
2082
files_to_backup.append(path[1])
2080
2084
def backup(file_to_backup):
2081
backup_name = self.bzrdir.generate_backup_name(file_to_backup)
2085
backup_name = self.bzrdir._available_backup_name(file_to_backup)
2082
2086
osutils.rename(abs_path, self.abspath(backup_name))
2083
return "removed %s (but kept a copy: %s)" % (file_to_backup, backup_name)
2087
return "removed %s (but kept a copy: %s)" % (file_to_backup,
2085
2090
# Build inv_delta and delete files where applicable,
2086
2091
# do this before any modifications to inventory.
2305
2310
if old_tip is self._marker:
2307
return self._update_tree(old_tip, change_reporter, revision)
2312
return self._update_tree(old_tip, change_reporter, revision, show_base)
2311
2316
@needs_tree_write_lock
2312
def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2317
def _update_tree(self, old_tip=None, change_reporter=None, revision=None,
2313
2319
"""Update a tree to the master branch.
2315
2321
:param old_tip: if supplied, the previous tip revision the branch,
2342
2348
other_tree = self.branch.repository.revision_tree(old_tip)
2343
2349
nb_conflicts = merge.merge_inner(self.branch, other_tree,
2344
2350
base_tree, this_tree=self,
2345
change_reporter=change_reporter)
2351
change_reporter=change_reporter,
2352
show_base=show_base)
2346
2353
if nb_conflicts:
2347
2354
self.add_parent_tree((old_tip, other_tree))
2348
2355
trace.note('Rerun update after fixing the conflicts.')
2680
2688
return ShelfManager(self, self._transport)
2683
class WorkingTree2(WorkingTree):
2684
"""This is the Format 2 working tree.
2686
This was the first weave based working tree.
2687
- uses os locks for locking.
2688
- uses the branch last-revision.
2691
def __init__(self, *args, **kwargs):
2692
super(WorkingTree2, self).__init__(*args, **kwargs)
2693
# WorkingTree2 has more of a constraint that self._inventory must
2694
# exist. Because this is an older format, we don't mind the overhead
2695
# caused by the extra computation here.
2697
# Newer WorkingTree's should only have self._inventory set when they
2699
if self._inventory is None:
2700
self.read_working_inventory()
2702
def _get_check_refs(self):
2703
"""Return the references needed to perform a check of this tree."""
2704
return [('trees', self.last_revision())]
2706
def lock_tree_write(self):
2707
"""See WorkingTree.lock_tree_write().
2709
In Format2 WorkingTrees we have a single lock for the branch and tree
2710
so lock_tree_write() degrades to lock_write().
2712
:return: An object with an unlock method which will release the lock
2715
self.branch.lock_write()
2717
self._control_files.lock_write()
2720
self.branch.unlock()
2724
# do non-implementation specific cleanup
2727
# we share control files:
2728
if self._control_files._lock_count == 3:
2729
# _inventory_is_modified is always False during a read lock.
2730
if self._inventory_is_modified:
2732
self._write_hashcache_if_dirty()
2734
# reverse order of locking.
2736
return self._control_files.unlock()
2738
self.branch.unlock()
2741
2691
class WorkingTree3(WorkingTree):
2742
2692
"""This is the Format 3 working tree.
2912
2862
del klass._formats[format.get_format_string()]
2915
class WorkingTreeFormat2(WorkingTreeFormat):
2916
"""The second working tree format.
2918
This format modified the hash cache from the format 1 hash cache.
2921
upgrade_recommended = True
2923
def get_format_description(self):
2924
"""See WorkingTreeFormat.get_format_description()."""
2925
return "Working tree format 2"
2927
def _stub_initialize_on_transport(self, transport, file_mode):
2928
"""Workaround: create control files for a remote working tree.
2930
This ensures that it can later be updated and dealt with locally,
2931
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2932
no working tree. (See bug #43064).
2935
inv = inventory.Inventory()
2936
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2938
transport.put_file('inventory', sio, file_mode)
2939
transport.put_bytes('pending-merges', '', file_mode)
2941
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2942
accelerator_tree=None, hardlink=False):
2943
"""See WorkingTreeFormat.initialize()."""
2944
if not isinstance(a_bzrdir.transport, LocalTransport):
2945
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2946
if from_branch is not None:
2947
branch = from_branch
2949
branch = a_bzrdir.open_branch()
2950
if revision_id is None:
2951
revision_id = _mod_revision.ensure_null(branch.last_revision())
2954
branch.generate_revision_history(revision_id)
2957
inv = inventory.Inventory()
2958
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2964
basis_tree = branch.repository.revision_tree(revision_id)
2965
if basis_tree.inventory.root is not None:
2966
wt.set_root_id(basis_tree.get_root_id())
2967
# set the parent list and cache the basis tree.
2968
if _mod_revision.is_null(revision_id):
2971
parent_trees = [(revision_id, basis_tree)]
2972
wt.set_parent_trees(parent_trees)
2973
transform.build_tree(basis_tree, wt)
2977
super(WorkingTreeFormat2, self).__init__()
2978
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2980
def open(self, a_bzrdir, _found=False):
2981
"""Return the WorkingTree object for a_bzrdir
2983
_found is a private parameter, do not use it. It is used to indicate
2984
if format probing has already been done.
2987
# we are being called directly and must probe.
2988
raise NotImplementedError
2989
if not isinstance(a_bzrdir.transport, LocalTransport):
2990
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2991
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2997
2865
class WorkingTreeFormat3(WorkingTreeFormat):
2998
2866
"""The second working tree format updated to record a format marker.