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()
1380
1445
# check the inventory for source and destination
1381
1446
if from_id is None:
1382
1447
raise errors.BzrMoveFailedError(from_rel,to_rel,
1383
errors.NotVersionedError(path=str(from_rel)))
1448
errors.NotVersionedError(path=from_rel))
1384
1449
if to_id is not None:
1385
1450
raise errors.BzrMoveFailedError(from_rel,to_rel,
1386
errors.AlreadyVersionedError(path=str(to_rel)))
1451
errors.AlreadyVersionedError(path=to_rel))
1388
1453
# try to determine the mode for rename (only change inv or change
1389
1454
# inv and file system)
1391
1456
if not self.has_filename(to_rel):
1392
1457
raise errors.BzrMoveFailedError(from_id,to_rel,
1393
errors.NoSuchFile(path=str(to_rel),
1458
errors.NoSuchFile(path=to_rel,
1394
1459
extra="New file has not been created yet"))
1395
1460
only_change_inv = True
1396
1461
elif not self.has_filename(from_rel) and self.has_filename(to_rel):
1587
1652
# - RBC 20060907
1588
1653
self._write_inventory(self._inventory)
1590
def _iter_conflicts(self):
1592
for info in self.list_files():
1594
stem = get_conflicted_stem(path)
1597
if stem not in conflicted:
1598
conflicted.add(stem)
1601
1655
@needs_write_lock
1602
1656
def pull(self, source, overwrite=False, stop_revision=None,
1603
change_reporter=None, possible_transports=None, local=False):
1657
change_reporter=None, possible_transports=None, local=False,
1604
1659
source.lock_read()
1606
1661
old_revision_info = self.branch.last_revision_info()
1798
1854
raise errors.ObjectNotLocked(self)
1800
1856
def lock_read(self):
1801
"""See Branch.lock_read, and WorkingTree.unlock."""
1857
"""Lock the tree for reading.
1859
This also locks the branch, and can be unlocked via self.unlock().
1861
:return: A bzrlib.lock.LogicalLockResult.
1802
1863
if not self.is_locked():
1803
1864
self._reset_data()
1804
1865
self.branch.lock_read()
1806
return self._control_files.lock_read()
1867
self._control_files.lock_read()
1868
return LogicalLockResult(self.unlock)
1808
1870
self.branch.unlock()
1811
1873
def lock_tree_write(self):
1812
"""See MutableTree.lock_tree_write, and WorkingTree.unlock."""
1874
"""See MutableTree.lock_tree_write, and WorkingTree.unlock.
1876
:return: A bzrlib.lock.LogicalLockResult.
1813
1878
if not self.is_locked():
1814
1879
self._reset_data()
1815
1880
self.branch.lock_read()
1817
return self._control_files.lock_write()
1882
self._control_files.lock_write()
1883
return LogicalLockResult(self.unlock)
1819
1885
self.branch.unlock()
1822
1888
def lock_write(self):
1823
"""See MutableTree.lock_write, and WorkingTree.unlock."""
1889
"""See MutableTree.lock_write, and WorkingTree.unlock.
1891
:return: A bzrlib.lock.LogicalLockResult.
1824
1893
if not self.is_locked():
1825
1894
self._reset_data()
1826
1895
self.branch.lock_write()
1828
return self._control_files.lock_write()
1897
self._control_files.lock_write()
1898
return LogicalLockResult(self.unlock)
1830
1900
self.branch.unlock()
2021
all_files = set() # specified and nested files
1952
2022
unknown_nested_files=set()
1953
2023
if to_file is None:
1954
2024
to_file = sys.stdout
2026
files_to_backup = []
1956
2028
def recurse_directory_to_add_files(directory):
1957
2029
# Recurse directory and add all files
1958
2030
# so we can check if they have changed.
1959
for parent_info, file_infos in\
1960
self.walkdirs(directory):
2031
for parent_info, file_infos in self.walkdirs(directory):
1961
2032
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1962
2033
# Is it versioned or ignored?
1963
if self.path2id(relpath) or self.is_ignored(relpath):
2034
if self.path2id(relpath):
1964
2035
# Add nested content for deletion.
1965
new_files.add(relpath)
2036
all_files.add(relpath)
1967
# Files which are not versioned and not ignored
2038
# Files which are not versioned
1968
2039
# should be treated as unknown.
1969
unknown_nested_files.add((relpath, None, kind))
2040
files_to_backup.append(relpath)
1971
2042
for filename in files:
1972
2043
# Get file name into canonical form.
1973
2044
abspath = self.abspath(filename)
1974
2045
filename = self.relpath(abspath)
1975
2046
if len(filename) > 0:
1976
new_files.add(filename)
2047
all_files.add(filename)
1977
2048
recurse_directory_to_add_files(filename)
1979
files = list(new_files)
2050
files = list(all_files)
1981
2052
if len(files) == 0:
1982
2053
return # nothing to do
1987
2058
# Bail out if we are going to delete files we shouldn't
1988
2059
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
2060
for (file_id, path, content_change, versioned, parent_id, name,
2061
kind, executable) in self.iter_changes(self.basis_tree(),
2062
include_unchanged=True, require_versioned=False,
2063
want_unversioned=True, specific_files=files):
2064
if versioned[0] == False:
2065
# The record is unknown or newly added
2066
files_to_backup.append(path[1])
2067
elif (content_change and (kind[1] is not None) and
2068
osutils.is_inside_any(files, path[1])):
2069
# Versioned and changed, but not deleted, and still
2070
# in one of the dirs to be deleted.
2071
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)
2073
def backup(file_to_backup):
2074
backup_name = self.bzrdir._available_backup_name(file_to_backup)
2075
osutils.rename(abs_path, self.abspath(backup_name))
2076
return "removed %s (but kept a copy: %s)" % (file_to_backup,
2016
2079
# Build inv_delta and delete files where applicable,
2017
2080
# do this before any modifications to inventory.
2041
2104
len(os.listdir(abs_path)) > 0):
2043
2106
osutils.rmtree(abs_path)
2107
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,)
2111
if f in files_to_backup:
2114
osutils.delete_any(abs_path)
2115
message = "deleted %s" % (f,)
2050
2116
elif message is not None:
2051
2117
# Only care if we haven't done anything yet.
2052
2118
message = "%s does not exist." % (f,)
2233
2299
if old_tip is self._marker:
2235
return self._update_tree(old_tip, change_reporter, revision)
2301
return self._update_tree(old_tip, change_reporter, revision, show_base)
2239
2305
@needs_tree_write_lock
2240
def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2306
def _update_tree(self, old_tip=None, change_reporter=None, revision=None,
2241
2308
"""Update a tree to the master branch.
2243
2310
:param old_tip: if supplied, the previous tip revision the branch,
2270
2337
other_tree = self.branch.repository.revision_tree(old_tip)
2271
2338
nb_conflicts = merge.merge_inner(self.branch, other_tree,
2272
2339
base_tree, this_tree=self,
2273
change_reporter=change_reporter)
2340
change_reporter=change_reporter,
2341
show_base=show_base)
2274
2342
if nb_conflicts:
2275
2343
self.add_parent_tree((old_tip, other_tree))
2276
2344
trace.note('Rerun update after fixing the conflicts.')
2347
2416
def add_conflicts(self, arg):
2348
2417
raise errors.UnsupportedOperation(self.add_conflicts, self)
2351
2419
def conflicts(self):
2352
conflicts = _mod_conflicts.ConflictList()
2353
for conflicted in self._iter_conflicts():
2356
if file_kind(self.abspath(conflicted)) != "file":
2358
except errors.NoSuchFile:
2361
for suffix in ('.THIS', '.OTHER'):
2363
kind = file_kind(self.abspath(conflicted+suffix))
2366
except errors.NoSuchFile:
2370
ctype = {True: 'text conflict', False: 'contents conflict'}[text]
2371
conflicts.append(_mod_conflicts.Conflict.factory(ctype,
2373
file_id=self.path2id(conflicted)))
2420
raise NotImplementedError(self.conflicts)
2376
2422
def walkdirs(self, prefix=""):
2377
2423
"""Walk the directories of this tree.
2645
def check_state(self):
2646
"""Check that the working state is/isn't valid."""
2647
check_refs = self._get_check_refs()
2649
for ref in check_refs:
2652
refs[ref] = self.branch.repository.revision_tree(value)
2655
@needs_tree_write_lock
2656
def reset_state(self, revision_ids=None):
2657
"""Reset the state of the working tree.
2659
This does a hard-reset to a last-known-good state. This is a way to
2660
fix if something got corrupted (like the .bzr/checkout/dirstate file)
2662
if revision_ids is None:
2663
revision_ids = self.get_parent_ids()
2664
if not revision_ids:
2665
rt = self.branch.repository.revision_tree(
2666
_mod_revision.NULL_REVISION)
2668
rt = self.branch.repository.revision_tree(revision_ids[0])
2669
self._write_inventory(rt.inventory)
2670
self.set_parent_ids(revision_ids)
2598
2672
def _get_rules_searcher(self, default_searcher):
2599
2673
"""See Tree._get_rules_searcher."""
2600
2674
if self._rules_searcher is None:
2608
2682
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
2685
class WorkingTree3(WorkingTree):
2666
2686
"""This is the Format 3 working tree.
2771
2785
"""The known formats."""
2788
"""Extra formats that can not be used in a metadir."""
2773
2790
requires_rich_root = False
2775
2792
upgrade_recommended = False
2794
requires_normalized_unicode_filenames = False
2796
case_sensitive_filename = "FoRMaT"
2798
missing_parent_conflicts = False
2799
"""If this format supports missing parent conflicts."""
2778
2802
def find_format(klass, a_bzrdir):
2779
2803
"""Return the format for the working tree object in a_bzrdir."""
2828
2852
klass._formats[format.get_format_string()] = format
2855
def register_extra_format(klass, format):
2856
klass._extra_formats.append(format)
2859
def unregister_extra_format(klass, format):
2860
klass._extra_formats.remove(format)
2863
def get_formats(klass):
2864
return klass._formats.values() + klass._extra_formats
2831
2867
def set_default_format(klass, format):
2832
2868
klass._default_format = format
2836
2872
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
2875
class WorkingTreeFormat3(WorkingTreeFormat):
2922
2876
"""The second working tree format updated to record a format marker.