206
210
self._branch = self.bzrdir.open_branch()
207
211
self.basedir = realpath(basedir)
208
# if branch is at our basedir and is a format 6 or less
209
if isinstance(self._format, WorkingTreeFormat2):
210
# share control object
211
self._control_files = self.branch.control_files
213
# assume all other formats have their own control files.
214
self._control_files = _control_files
212
self._control_files = _control_files
215
213
self._transport = self._control_files._transport
216
214
# update the whole cache up front and write to disk if anything changed;
217
215
# in the future we might want to do this more selectively
347
345
path = osutils.getcwd()
348
346
control, relpath = bzrdir.BzrDir.open_containing(path)
350
347
return control.open_workingtree(), relpath
350
def open_containing_paths(file_list, default_directory=None,
351
canonicalize=True, apply_view=True):
352
"""Open the WorkingTree that contains a set of paths.
354
Fail if the paths given are not all in a single tree.
356
This is used for the many command-line interfaces that take a list of
357
any number of files and that require they all be in the same tree.
359
if default_directory is None:
360
default_directory = u'.'
361
# recommended replacement for builtins.internal_tree_files
362
if file_list is None or len(file_list) == 0:
363
tree = WorkingTree.open_containing(default_directory)[0]
364
# XXX: doesn't really belong here, and seems to have the strange
365
# side effect of making it return a bunch of files, not the whole
366
# tree -- mbp 20100716
367
if tree.supports_views() and apply_view:
368
view_files = tree.views.lookup_view()
370
file_list = view_files
371
view_str = views.view_display_str(view_files)
372
note("Ignoring files outside view. View is %s" % view_str)
373
return tree, file_list
374
if default_directory == u'.':
377
seed = default_directory
378
file_list = [osutils.pathjoin(default_directory, f)
380
tree = WorkingTree.open_containing(seed)[0]
381
return tree, tree.safe_relpath_files(file_list, canonicalize,
382
apply_view=apply_view)
384
def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
385
"""Convert file_list into a list of relpaths in tree.
387
:param self: A tree to operate on.
388
:param file_list: A list of user provided paths or None.
389
:param apply_view: if True and a view is set, apply it or check that
390
specified files are within it
391
:return: A list of relative paths.
392
:raises errors.PathNotChild: When a provided path is in a different self
395
if file_list is None:
397
if self.supports_views() and apply_view:
398
view_files = self.views.lookup_view()
402
# self.relpath exists as a "thunk" to osutils, but canonical_relpath
403
# doesn't - fix that up here before we enter the loop.
405
fixer = lambda p: osutils.canonical_relpath(self.basedir, p)
408
for filename in file_list:
409
relpath = fixer(osutils.dereference_path(filename))
410
if view_files and not osutils.is_inside_any(view_files, relpath):
411
raise errors.FileOutsideView(filename, view_files)
412
new_list.append(relpath)
353
416
def open_downlevel(path=None):
354
417
"""Open an unsupported working tree.
368
431
return True, None
370
433
return True, tree
371
transport = get_transport(location)
372
iterator = bzrdir.BzrDir.find_bzrdirs(transport, evaluate=evaluate,
434
t = transport.get_transport(location)
435
iterator = bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate,
373
436
list_current=list_current)
374
return [t for t in iterator if t is not None]
437
return [tr for tr in iterator if tr is not None]
376
439
# should be deprecated - this is slow and in any case treating them as a
377
440
# container is (we now know) bad style -- mbp 20070302
462
525
return (file_obj, stat_value)
464
527
def get_file_text(self, file_id, path=None, filtered=True):
465
return self.get_file(file_id, path=path, filtered=filtered).read()
528
my_file = self.get_file(file_id, path=path, filtered=filtered)
530
return my_file.read()
467
534
def get_file_byname(self, filename, filtered=True):
468
535
path = self.abspath(filename)
523
590
# Now we have the parents of this content
524
591
annotator = self.branch.repository.texts.get_annotator()
525
text = self.get_file(file_id).read()
592
text = self.get_file_text(file_id)
526
593
this_key =(file_id, default_revision)
527
594
annotator.add_special_text(this_key, file_parent_keys, text)
528
595
annotations = [(key[-1], line)
1202
1269
# absolute path
1203
1270
fap = from_dir_abspath + '/' + f
1205
f_ie = inv.get_child(from_dir_id, f)
1272
dir_ie = inv[from_dir_id]
1273
if dir_ie.kind == 'directory':
1274
f_ie = dir_ie.children.get(f)
1208
1279
elif self.is_ignored(fp[1:]):
1211
# we may not have found this file, because of a unicode issue
1282
# we may not have found this file, because of a unicode
1283
# issue, or because the directory was actually a symlink.
1212
1284
f_norm, can_access = osutils.normalized_filename(f)
1213
1285
if f == f_norm or not can_access:
1214
1286
# No change, so treat this file normally
1298
1370
# check for deprecated use of signature
1299
1371
if to_dir is None:
1300
to_dir = kwargs.get('to_name', None)
1302
raise TypeError('You must supply a target directory')
1304
symbol_versioning.warn('The parameter to_name was deprecated'
1305
' in version 0.13. Use to_dir instead',
1372
raise TypeError('You must supply a target directory')
1308
1373
# check destination directory
1309
1374
if isinstance(from_paths, basestring):
1310
1375
raise ValueError()
1798
1865
raise errors.ObjectNotLocked(self)
1800
1867
def lock_read(self):
1801
"""See Branch.lock_read, and WorkingTree.unlock."""
1868
"""Lock the tree for reading.
1870
This also locks the branch, and can be unlocked via self.unlock().
1872
:return: A bzrlib.lock.LogicalLockResult.
1802
1874
if not self.is_locked():
1803
1875
self._reset_data()
1804
1876
self.branch.lock_read()
1806
return self._control_files.lock_read()
1878
self._control_files.lock_read()
1879
return LogicalLockResult(self.unlock)
1808
1881
self.branch.unlock()
1811
1884
def lock_tree_write(self):
1812
"""See MutableTree.lock_tree_write, and WorkingTree.unlock."""
1885
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1887
:return: A bzrlib.lock.LogicalLockResult.
1813
1889
if not self.is_locked():
1814
1890
self._reset_data()
1815
1891
self.branch.lock_read()
1817
return self._control_files.lock_write()
1893
self._control_files.lock_write()
1894
return LogicalLockResult(self.unlock)
1819
1896
self.branch.unlock()
1822
1899
def lock_write(self):
1823
"""See MutableTree.lock_write, and WorkingTree.unlock."""
1900
"""See MutableTree.lock_write, and WorkingTree.unlock.
1902
:return: A bzrlib.lock.LogicalLockResult.
1824
1904
if not self.is_locked():
1825
1905
self._reset_data()
1826
1906
self.branch.lock_write()
1828
return self._control_files.lock_write()
1908
self._control_files.lock_write()
1909
return LogicalLockResult(self.unlock)
1830
1911
self.branch.unlock()
2032
all_files = set() # specified and nested files
1952
2033
unknown_nested_files=set()
1953
2034
if to_file is None:
1954
2035
to_file = sys.stdout
2037
files_to_backup = []
1956
2039
def recurse_directory_to_add_files(directory):
1957
2040
# Recurse directory and add all files
1958
2041
# so we can check if they have changed.
1959
for parent_info, file_infos in\
1960
self.walkdirs(directory):
2042
for parent_info, file_infos in self.walkdirs(directory):
1961
2043
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1962
2044
# Is it versioned or ignored?
1963
if self.path2id(relpath) or self.is_ignored(relpath):
2045
if self.path2id(relpath):
1964
2046
# Add nested content for deletion.
1965
new_files.add(relpath)
2047
all_files.add(relpath)
1967
# Files which are not versioned and not ignored
2049
# Files which are not versioned
1968
2050
# should be treated as unknown.
1969
unknown_nested_files.add((relpath, None, kind))
2051
files_to_backup.append(relpath)
1971
2053
for filename in files:
1972
2054
# Get file name into canonical form.
1973
2055
abspath = self.abspath(filename)
1974
2056
filename = self.relpath(abspath)
1975
2057
if len(filename) > 0:
1976
new_files.add(filename)
2058
all_files.add(filename)
1977
2059
recurse_directory_to_add_files(filename)
1979
files = list(new_files)
2061
files = list(all_files)
1981
2063
if len(files) == 0:
1982
2064
return # nothing to do
1987
2069
# Bail out if we are going to delete files we shouldn't
1988
2070
if not keep_files and not force:
1989
has_changed_files = len(unknown_nested_files) > 0
1990
if not has_changed_files:
1991
for (file_id, path, content_change, versioned, parent_id, name,
1992
kind, executable) in self.iter_changes(self.basis_tree(),
1993
include_unchanged=True, require_versioned=False,
1994
want_unversioned=True, specific_files=files):
1995
if versioned == (False, False):
1996
# The record is unknown ...
1997
if not self.is_ignored(path[1]):
1998
# ... but not ignored
1999
has_changed_files = True
2001
elif content_change and (kind[1] is not None):
2002
# Versioned and changed, but not deleted
2003
has_changed_files = True
2071
for (file_id, path, content_change, versioned, parent_id, name,
2072
kind, executable) in self.iter_changes(self.basis_tree(),
2073
include_unchanged=True, require_versioned=False,
2074
want_unversioned=True, specific_files=files):
2075
if versioned[0] == False:
2076
# The record is unknown or newly added
2077
files_to_backup.append(path[1])
2078
elif (content_change and (kind[1] is not None) and
2079
osutils.is_inside_any(files, path[1])):
2080
# Versioned and changed, but not deleted, and still
2081
# in one of the dirs to be deleted.
2082
files_to_backup.append(path[1])
2006
if has_changed_files:
2007
# Make delta show ALL applicable changes in error message.
2008
tree_delta = self.changes_from(self.basis_tree(),
2009
require_versioned=False, want_unversioned=True,
2010
specific_files=files)
2011
for unknown_file in unknown_nested_files:
2012
if unknown_file not in tree_delta.unversioned:
2013
tree_delta.unversioned.extend((unknown_file,))
2014
raise errors.BzrRemoveChangedFilesError(tree_delta)
2084
def backup(file_to_backup):
2085
backup_name = self.bzrdir._available_backup_name(file_to_backup)
2086
osutils.rename(abs_path, self.abspath(backup_name))
2087
return "removed %s (but kept a copy: %s)" % (file_to_backup,
2016
2090
# Build inv_delta and delete files where applicable,
2017
2091
# do this before any modifications to inventory.
2041
2115
len(os.listdir(abs_path)) > 0):
2043
2117
osutils.rmtree(abs_path)
2118
message = "deleted %s" % (f,)
2045
message = "%s is not an empty directory "\
2046
"and won't be deleted." % (f,)
2048
osutils.delete_any(abs_path)
2049
message = "deleted %s" % (f,)
2122
if f in files_to_backup:
2125
osutils.delete_any(abs_path)
2126
message = "deleted %s" % (f,)
2050
2127
elif message is not None:
2051
2128
# Only care if we haven't done anything yet.
2052
2129
message = "%s does not exist." % (f,)
2233
2310
if old_tip is self._marker:
2235
return self._update_tree(old_tip, change_reporter, revision)
2312
return self._update_tree(old_tip, change_reporter, revision, show_base)
2239
2316
@needs_tree_write_lock
2240
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,
2241
2319
"""Update a tree to the master branch.
2243
2321
:param old_tip: if supplied, the previous tip revision the branch,
2270
2348
other_tree = self.branch.repository.revision_tree(old_tip)
2271
2349
nb_conflicts = merge.merge_inner(self.branch, other_tree,
2272
2350
base_tree, this_tree=self,
2273
change_reporter=change_reporter)
2351
change_reporter=change_reporter,
2352
show_base=show_base)
2274
2353
if nb_conflicts:
2275
2354
self.add_parent_tree((old_tip, other_tree))
2276
2355
trace.note('Rerun update after fixing the conflicts.')
2608
2688
return ShelfManager(self, self._transport)
2611
class WorkingTree2(WorkingTree):
2612
"""This is the Format 2 working tree.
2614
This was the first weave based working tree.
2615
- uses os locks for locking.
2616
- uses the branch last-revision.
2619
def __init__(self, *args, **kwargs):
2620
super(WorkingTree2, self).__init__(*args, **kwargs)
2621
# WorkingTree2 has more of a constraint that self._inventory must
2622
# exist. Because this is an older format, we don't mind the overhead
2623
# caused by the extra computation here.
2625
# Newer WorkingTree's should only have self._inventory set when they
2627
if self._inventory is None:
2628
self.read_working_inventory()
2630
def _get_check_refs(self):
2631
"""Return the references needed to perform a check of this tree."""
2632
return [('trees', self.last_revision())]
2634
def lock_tree_write(self):
2635
"""See WorkingTree.lock_tree_write().
2637
In Format2 WorkingTrees we have a single lock for the branch and tree
2638
so lock_tree_write() degrades to lock_write().
2640
self.branch.lock_write()
2642
return self._control_files.lock_write()
2644
self.branch.unlock()
2648
# do non-implementation specific cleanup
2651
# we share control files:
2652
if self._control_files._lock_count == 3:
2653
# _inventory_is_modified is always False during a read lock.
2654
if self._inventory_is_modified:
2656
self._write_hashcache_if_dirty()
2658
# reverse order of locking.
2660
return self._control_files.unlock()
2662
self.branch.unlock()
2665
2691
class WorkingTree3(WorkingTree):
2666
2692
"""This is the Format 3 working tree.
2836
2862
del klass._formats[format.get_format_string()]
2839
class WorkingTreeFormat2(WorkingTreeFormat):
2840
"""The second working tree format.
2842
This format modified the hash cache from the format 1 hash cache.
2845
upgrade_recommended = True
2847
def get_format_description(self):
2848
"""See WorkingTreeFormat.get_format_description()."""
2849
return "Working tree format 2"
2851
def _stub_initialize_on_transport(self, transport, file_mode):
2852
"""Workaround: create control files for a remote working tree.
2854
This ensures that it can later be updated and dealt with locally,
2855
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2856
no working tree. (See bug #43064).
2859
inv = inventory.Inventory()
2860
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2862
transport.put_file('inventory', sio, file_mode)
2863
transport.put_bytes('pending-merges', '', file_mode)
2865
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2866
accelerator_tree=None, hardlink=False):
2867
"""See WorkingTreeFormat.initialize()."""
2868
if not isinstance(a_bzrdir.transport, LocalTransport):
2869
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2870
if from_branch is not None:
2871
branch = from_branch
2873
branch = a_bzrdir.open_branch()
2874
if revision_id is None:
2875
revision_id = _mod_revision.ensure_null(branch.last_revision())
2878
branch.generate_revision_history(revision_id)
2881
inv = inventory.Inventory()
2882
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2888
basis_tree = branch.repository.revision_tree(revision_id)
2889
if basis_tree.inventory.root is not None:
2890
wt.set_root_id(basis_tree.get_root_id())
2891
# set the parent list and cache the basis tree.
2892
if _mod_revision.is_null(revision_id):
2895
parent_trees = [(revision_id, basis_tree)]
2896
wt.set_parent_trees(parent_trees)
2897
transform.build_tree(basis_tree, wt)
2901
super(WorkingTreeFormat2, self).__init__()
2902
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2904
def open(self, a_bzrdir, _found=False):
2905
"""Return the WorkingTree object for a_bzrdir
2907
_found is a private parameter, do not use it. It is used to indicate
2908
if format probing has already been done.
2911
# we are being called directly and must probe.
2912
raise NotImplementedError
2913
if not isinstance(a_bzrdir.transport, LocalTransport):
2914
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2915
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2921
2865
class WorkingTreeFormat3(WorkingTreeFormat):
2922
2866
"""The second working tree format updated to record a format marker.