348
358
path = osutils.getcwd()
349
359
control, relpath = bzrdir.BzrDir.open_containing(path)
351
360
return control.open_workingtree(), relpath
363
def open_containing_paths(file_list, default_directory=None,
364
canonicalize=True, apply_view=True):
365
"""Open the WorkingTree that contains a set of paths.
367
Fail if the paths given are not all in a single tree.
369
This is used for the many command-line interfaces that take a list of
370
any number of files and that require they all be in the same tree.
372
if default_directory is None:
373
default_directory = u'.'
374
# recommended replacement for builtins.internal_tree_files
375
if file_list is None or len(file_list) == 0:
376
tree = WorkingTree.open_containing(default_directory)[0]
377
# XXX: doesn't really belong here, and seems to have the strange
378
# side effect of making it return a bunch of files, not the whole
379
# tree -- mbp 20100716
380
if tree.supports_views() and apply_view:
381
view_files = tree.views.lookup_view()
383
file_list = view_files
384
view_str = views.view_display_str(view_files)
385
note("Ignoring files outside view. View is %s" % view_str)
386
return tree, file_list
387
if default_directory == u'.':
390
seed = default_directory
391
file_list = [osutils.pathjoin(default_directory, f)
393
tree = WorkingTree.open_containing(seed)[0]
394
return tree, tree.safe_relpath_files(file_list, canonicalize,
395
apply_view=apply_view)
397
def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
398
"""Convert file_list into a list of relpaths in tree.
400
:param self: A tree to operate on.
401
:param file_list: A list of user provided paths or None.
402
:param apply_view: if True and a view is set, apply it or check that
403
specified files are within it
404
:return: A list of relative paths.
405
:raises errors.PathNotChild: When a provided path is in a different self
408
if file_list is None:
410
if self.supports_views() and apply_view:
411
view_files = self.views.lookup_view()
415
# self.relpath exists as a "thunk" to osutils, but canonical_relpath
416
# doesn't - fix that up here before we enter the loop.
418
fixer = lambda p: osutils.canonical_relpath(self.basedir, p)
421
for filename in file_list:
422
relpath = fixer(osutils.dereference_path(filename))
423
if view_files and not osutils.is_inside_any(view_files, relpath):
424
raise errors.FileOutsideView(filename, view_files)
425
new_list.append(relpath)
354
429
def open_downlevel(path=None):
355
430
"""Open an unsupported working tree.
1385
1458
# check the inventory for source and destination
1386
1459
if from_id is None:
1387
1460
raise errors.BzrMoveFailedError(from_rel,to_rel,
1388
errors.NotVersionedError(path=str(from_rel)))
1461
errors.NotVersionedError(path=from_rel))
1389
1462
if to_id is not None:
1390
1463
raise errors.BzrMoveFailedError(from_rel,to_rel,
1391
errors.AlreadyVersionedError(path=str(to_rel)))
1464
errors.AlreadyVersionedError(path=to_rel))
1393
1466
# try to determine the mode for rename (only change inv or change
1394
1467
# inv and file system)
1396
1469
if not self.has_filename(to_rel):
1397
1470
raise errors.BzrMoveFailedError(from_id,to_rel,
1398
errors.NoSuchFile(path=str(to_rel),
1471
errors.NoSuchFile(path=to_rel,
1399
1472
extra="New file has not been created yet"))
1400
1473
only_change_inv = True
1401
1474
elif not self.has_filename(from_rel) and self.has_filename(to_rel):
2034
all_files = set() # specified and nested files
1971
2035
unknown_nested_files=set()
1972
2036
if to_file is None:
1973
2037
to_file = sys.stdout
2039
files_to_backup = []
1975
2041
def recurse_directory_to_add_files(directory):
1976
2042
# Recurse directory and add all files
1977
2043
# so we can check if they have changed.
1978
2044
for parent_info, file_infos in self.walkdirs(directory):
1979
2045
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1980
2046
# Is it versioned or ignored?
1981
if self.path2id(relpath) or self.is_ignored(relpath):
2047
if self.path2id(relpath):
1982
2048
# Add nested content for deletion.
1983
new_files.add(relpath)
2049
all_files.add(relpath)
1985
# Files which are not versioned and not ignored
2051
# Files which are not versioned
1986
2052
# should be treated as unknown.
1987
unknown_nested_files.add((relpath, None, kind))
2053
files_to_backup.append(relpath)
1989
2055
for filename in files:
1990
2056
# Get file name into canonical form.
1991
2057
abspath = self.abspath(filename)
1992
2058
filename = self.relpath(abspath)
1993
2059
if len(filename) > 0:
1994
new_files.add(filename)
2060
all_files.add(filename)
1995
2061
recurse_directory_to_add_files(filename)
1997
files = list(new_files)
2063
files = list(all_files)
1999
2065
if len(files) == 0:
2000
2066
return # nothing to do
2005
2071
# Bail out if we are going to delete files we shouldn't
2006
2072
if not keep_files and not force:
2007
has_changed_files = len(unknown_nested_files) > 0
2008
if not has_changed_files:
2009
for (file_id, path, content_change, versioned, parent_id, name,
2010
kind, executable) in self.iter_changes(self.basis_tree(),
2011
include_unchanged=True, require_versioned=False,
2012
want_unversioned=True, specific_files=files):
2013
if versioned == (False, False):
2014
# The record is unknown ...
2015
if not self.is_ignored(path[1]):
2016
# ... but not ignored
2017
has_changed_files = True
2019
elif (content_change and (kind[1] is not None) and
2020
osutils.is_inside_any(files, path[1])):
2021
# Versioned and changed, but not deleted, and still
2022
# in one of the dirs to be deleted.
2023
has_changed_files = True
2073
for (file_id, path, content_change, versioned, parent_id, name,
2074
kind, executable) in self.iter_changes(self.basis_tree(),
2075
include_unchanged=True, require_versioned=False,
2076
want_unversioned=True, specific_files=files):
2077
if versioned[0] == False:
2078
# The record is unknown or newly added
2079
files_to_backup.append(path[1])
2080
elif (content_change and (kind[1] is not None) and
2081
osutils.is_inside_any(files, path[1])):
2082
# Versioned and changed, but not deleted, and still
2083
# in one of the dirs to be deleted.
2084
files_to_backup.append(path[1])
2026
if has_changed_files:
2027
# Make delta show ALL applicable changes in error message.
2028
tree_delta = self.changes_from(self.basis_tree(),
2029
require_versioned=False, want_unversioned=True,
2030
specific_files=files)
2031
for unknown_file in unknown_nested_files:
2032
if unknown_file not in tree_delta.unversioned:
2033
tree_delta.unversioned.extend((unknown_file,))
2034
raise errors.BzrRemoveChangedFilesError(tree_delta)
2086
def backup(file_to_backup):
2087
backup_name = self.bzrdir._available_backup_name(file_to_backup)
2088
osutils.rename(abs_path, self.abspath(backup_name))
2089
return "removed %s (but kept a copy: %s)" % (file_to_backup,
2036
2092
# Build inv_delta and delete files where applicable,
2037
2093
# do this before any modifications to inventory.
2367
2429
def add_conflicts(self, arg):
2368
2430
raise errors.UnsupportedOperation(self.add_conflicts, self)
2371
2432
def conflicts(self):
2372
conflicts = _mod_conflicts.ConflictList()
2373
for conflicted in self._iter_conflicts():
2376
if file_kind(self.abspath(conflicted)) != "file":
2378
except errors.NoSuchFile:
2381
for suffix in ('.THIS', '.OTHER'):
2383
kind = file_kind(self.abspath(conflicted+suffix))
2386
except errors.NoSuchFile:
2390
ctype = {True: 'text conflict', False: 'contents conflict'}[text]
2391
conflicts.append(_mod_conflicts.Conflict.factory(ctype,
2393
file_id=self.path2id(conflicted)))
2433
raise NotImplementedError(self.conflicts)
2396
2435
def walkdirs(self, prefix=""):
2397
2436
"""Walk the directories of this tree.
2658
def check_state(self):
2659
"""Check that the working state is/isn't valid."""
2660
check_refs = self._get_check_refs()
2662
for ref in check_refs:
2665
refs[ref] = self.branch.repository.revision_tree(value)
2668
@needs_tree_write_lock
2669
def reset_state(self, revision_ids=None):
2670
"""Reset the state of the working tree.
2672
This does a hard-reset to a last-known-good state. This is a way to
2673
fix if something got corrupted (like the .bzr/checkout/dirstate file)
2675
if revision_ids is None:
2676
revision_ids = self.get_parent_ids()
2677
if not revision_ids:
2678
rt = self.branch.repository.revision_tree(
2679
_mod_revision.NULL_REVISION)
2681
rt = self.branch.repository.revision_tree(revision_ids[0])
2682
self._write_inventory(rt.inventory)
2683
self.set_parent_ids(revision_ids)
2618
2685
def _get_rules_searcher(self, default_searcher):
2619
2686
"""See Tree._get_rules_searcher."""
2620
2687
if self._rules_searcher is None:
2628
2695
return ShelfManager(self, self._transport)
2631
class WorkingTree2(WorkingTree):
2632
"""This is the Format 2 working tree.
2634
This was the first weave based working tree.
2635
- uses os locks for locking.
2636
- uses the branch last-revision.
2639
def __init__(self, *args, **kwargs):
2640
super(WorkingTree2, self).__init__(*args, **kwargs)
2641
# WorkingTree2 has more of a constraint that self._inventory must
2642
# exist. Because this is an older format, we don't mind the overhead
2643
# caused by the extra computation here.
2645
# Newer WorkingTree's should only have self._inventory set when they
2647
if self._inventory is None:
2648
self.read_working_inventory()
2650
def _get_check_refs(self):
2651
"""Return the references needed to perform a check of this tree."""
2652
return [('trees', self.last_revision())]
2654
def lock_tree_write(self):
2655
"""See WorkingTree.lock_tree_write().
2657
In Format2 WorkingTrees we have a single lock for the branch and tree
2658
so lock_tree_write() degrades to lock_write().
2660
:return: An object with an unlock method which will release the lock
2663
self.branch.lock_write()
2665
self._control_files.lock_write()
2668
self.branch.unlock()
2672
# do non-implementation specific cleanup
2675
# we share control files:
2676
if self._control_files._lock_count == 3:
2677
# _inventory_is_modified is always False during a read lock.
2678
if self._inventory_is_modified:
2680
self._write_hashcache_if_dirty()
2682
# reverse order of locking.
2684
return self._control_files.unlock()
2686
self.branch.unlock()
2689
2698
class WorkingTree3(WorkingTree):
2690
2699
"""This is the Format 3 working tree.
2764
2773
self.branch.unlock()
2767
def get_conflicted_stem(path):
2768
for suffix in _mod_conflicts.CONFLICT_SUFFIXES:
2769
if path.endswith(suffix):
2770
return path[:-len(suffix)]
2773
class WorkingTreeFormat(object):
2776
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
2777
"""Registry for working tree formats."""
2779
def __init__(self, other_registry=None):
2780
super(WorkingTreeFormatRegistry, self).__init__(other_registry)
2781
self._default_format = None
2783
def get_default(self):
2784
"""Return the current default format."""
2785
return self._default_format
2787
def set_default(self, format):
2788
self._default_format = format
2791
format_registry = WorkingTreeFormatRegistry()
2794
class WorkingTreeFormat(controldir.ControlComponentFormat):
2774
2795
"""An encapsulation of the initialization and open routines for a format.
2776
2797
Formats provide three things:
2788
2809
object will be created every time regardless.
2791
_default_format = None
2792
"""The default format used for new trees."""
2795
"""The known formats."""
2797
2812
requires_rich_root = False
2799
2814
upgrade_recommended = False
2816
requires_normalized_unicode_filenames = False
2818
case_sensitive_filename = "FoRMaT"
2820
missing_parent_conflicts = False
2821
"""If this format supports missing parent conflicts."""
2802
2824
def find_format(klass, a_bzrdir):
2803
2825
"""Return the format for the working tree object in a_bzrdir."""
2805
2827
transport = a_bzrdir.get_workingtree_transport(None)
2806
2828
format_string = transport.get_bytes("format")
2807
return klass._formats[format_string]
2829
return format_registry.get(format_string)
2808
2830
except errors.NoSuchFile:
2809
2831
raise errors.NoWorkingTree(base=transport.base)
2810
2832
except KeyError:
2811
2833
raise errors.UnknownFormatError(format=format_string,
2812
2834
kind="working tree")
2836
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2837
accelerator_tree=None, hardlink=False):
2838
"""Initialize a new working tree in a_bzrdir.
2840
:param a_bzrdir: BzrDir to initialize the working tree in.
2841
:param revision_id: allows creating a working tree at a different
2842
revision than the branch is at.
2843
:param from_branch: Branch to checkout
2844
:param accelerator_tree: A tree which can be used for retrieving file
2845
contents more quickly than the revision tree, i.e. a workingtree.
2846
The revision tree will be used for cases where accelerator_tree's
2847
content is different.
2848
:param hardlink: If true, hard-link files from accelerator_tree,
2851
raise NotImplementedError(self.initialize)
2814
2853
def __eq__(self, other):
2815
2854
return self.__class__ is other.__class__
2892
@symbol_versioning.deprecated_method(
2893
symbol_versioning.deprecated_in((2, 4, 0)))
2851
2894
def register_format(klass, format):
2852
klass._formats[format.get_format_string()] = format
2895
format_registry.register(format)
2898
@symbol_versioning.deprecated_method(
2899
symbol_versioning.deprecated_in((2, 4, 0)))
2900
def register_extra_format(klass, format):
2901
format_registry.register_extra(format)
2904
@symbol_versioning.deprecated_method(
2905
symbol_versioning.deprecated_in((2, 4, 0)))
2906
def unregister_extra_format(klass, format):
2907
format_registry.unregister_extra(format)
2910
@symbol_versioning.deprecated_method(
2911
symbol_versioning.deprecated_in((2, 4, 0)))
2912
def get_formats(klass):
2913
return format_registry._get_all()
2916
@symbol_versioning.deprecated_method(
2917
symbol_versioning.deprecated_in((2, 4, 0)))
2855
2918
def set_default_format(klass, format):
2856
klass._default_format = format
2919
format_registry.set_default(format)
2922
@symbol_versioning.deprecated_method(
2923
symbol_versioning.deprecated_in((2, 4, 0)))
2859
2924
def unregister_format(klass, format):
2860
del klass._formats[format.get_format_string()]
2863
class WorkingTreeFormat2(WorkingTreeFormat):
2864
"""The second working tree format.
2866
This format modified the hash cache from the format 1 hash cache.
2869
upgrade_recommended = True
2871
def get_format_description(self):
2872
"""See WorkingTreeFormat.get_format_description()."""
2873
return "Working tree format 2"
2875
def _stub_initialize_on_transport(self, transport, file_mode):
2876
"""Workaround: create control files for a remote working tree.
2878
This ensures that it can later be updated and dealt with locally,
2879
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2880
no working tree. (See bug #43064).
2883
inv = inventory.Inventory()
2884
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2886
transport.put_file('inventory', sio, file_mode)
2887
transport.put_bytes('pending-merges', '', file_mode)
2889
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2890
accelerator_tree=None, hardlink=False):
2891
"""See WorkingTreeFormat.initialize()."""
2892
if not isinstance(a_bzrdir.transport, LocalTransport):
2893
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2894
if from_branch is not None:
2895
branch = from_branch
2897
branch = a_bzrdir.open_branch()
2898
if revision_id is None:
2899
revision_id = _mod_revision.ensure_null(branch.last_revision())
2902
branch.generate_revision_history(revision_id)
2905
inv = inventory.Inventory()
2906
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2912
basis_tree = branch.repository.revision_tree(revision_id)
2913
if basis_tree.inventory.root is not None:
2914
wt.set_root_id(basis_tree.get_root_id())
2915
# set the parent list and cache the basis tree.
2916
if _mod_revision.is_null(revision_id):
2919
parent_trees = [(revision_id, basis_tree)]
2920
wt.set_parent_trees(parent_trees)
2921
transform.build_tree(basis_tree, wt)
2925
super(WorkingTreeFormat2, self).__init__()
2926
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2928
def open(self, a_bzrdir, _found=False):
2929
"""Return the WorkingTree object for a_bzrdir
2931
_found is a private parameter, do not use it. It is used to indicate
2932
if format probing has already been done.
2935
# we are being called directly and must probe.
2936
raise NotImplementedError
2937
if not isinstance(a_bzrdir.transport, LocalTransport):
2938
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2939
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2925
format_registry.remove(format)
2945
2928
class WorkingTreeFormat3(WorkingTreeFormat):
2946
2929
"""The second working tree format updated to record a format marker.
3076
3061
__default_format = WorkingTreeFormat6()
3077
WorkingTreeFormat.register_format(__default_format)
3078
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3079
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3080
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3081
WorkingTreeFormat.set_default_format(__default_format)
3082
# formats which have no format string are not discoverable
3083
# and not independently creatable, so are not registered.
3084
_legacy_formats = [WorkingTreeFormat2(),
3062
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3063
"bzrlib.workingtree_4", "WorkingTreeFormat4")
3064
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
3065
"bzrlib.workingtree_4", "WorkingTreeFormat5")
3066
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
3067
"bzrlib.workingtree_4", "WorkingTreeFormat6")
3068
format_registry.register(WorkingTreeFormat3())
3069
format_registry.set_default(__default_format)