348
355
path = osutils.getcwd()
349
356
control, relpath = bzrdir.BzrDir.open_containing(path)
351
357
return control.open_workingtree(), relpath
360
def open_containing_paths(file_list, default_directory=None,
361
canonicalize=True, apply_view=True):
362
"""Open the WorkingTree that contains a set of paths.
364
Fail if the paths given are not all in a single tree.
366
This is used for the many command-line interfaces that take a list of
367
any number of files and that require they all be in the same tree.
369
if default_directory is None:
370
default_directory = u'.'
371
# recommended replacement for builtins.internal_tree_files
372
if file_list is None or len(file_list) == 0:
373
tree = WorkingTree.open_containing(default_directory)[0]
374
# XXX: doesn't really belong here, and seems to have the strange
375
# side effect of making it return a bunch of files, not the whole
376
# tree -- mbp 20100716
377
if tree.supports_views() and apply_view:
378
view_files = tree.views.lookup_view()
380
file_list = view_files
381
view_str = views.view_display_str(view_files)
382
note("Ignoring files outside view. View is %s" % view_str)
383
return tree, file_list
384
if default_directory == u'.':
387
seed = default_directory
388
file_list = [osutils.pathjoin(default_directory, f)
390
tree = WorkingTree.open_containing(seed)[0]
391
return tree, tree.safe_relpath_files(file_list, canonicalize,
392
apply_view=apply_view)
394
def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
395
"""Convert file_list into a list of relpaths in tree.
397
:param self: A tree to operate on.
398
:param file_list: A list of user provided paths or None.
399
:param apply_view: if True and a view is set, apply it or check that
400
specified files are within it
401
:return: A list of relative paths.
402
:raises errors.PathNotChild: When a provided path is in a different self
405
if file_list is None:
407
if self.supports_views() and apply_view:
408
view_files = self.views.lookup_view()
412
# self.relpath exists as a "thunk" to osutils, but canonical_relpath
413
# doesn't - fix that up here before we enter the loop.
415
fixer = lambda p: osutils.canonical_relpath(self.basedir, p)
418
for filename in file_list:
419
relpath = fixer(osutils.dereference_path(filename))
420
if view_files and not osutils.is_inside_any(view_files, relpath):
421
raise errors.FileOutsideView(filename, view_files)
422
new_list.append(relpath)
354
426
def open_downlevel(path=None):
355
427
"""Open an unsupported working tree.
1381
1456
# check the inventory for source and destination
1382
1457
if from_id is None:
1383
1458
raise errors.BzrMoveFailedError(from_rel,to_rel,
1384
errors.NotVersionedError(path=str(from_rel)))
1459
errors.NotVersionedError(path=from_rel))
1385
1460
if to_id is not None:
1386
1461
raise errors.BzrMoveFailedError(from_rel,to_rel,
1387
errors.AlreadyVersionedError(path=str(to_rel)))
1462
errors.AlreadyVersionedError(path=to_rel))
1389
1464
# try to determine the mode for rename (only change inv or change
1390
1465
# inv and file system)
1392
1467
if not self.has_filename(to_rel):
1393
1468
raise errors.BzrMoveFailedError(from_id,to_rel,
1394
errors.NoSuchFile(path=str(to_rel),
1469
errors.NoSuchFile(path=to_rel,
1395
1470
extra="New file has not been created yet"))
1396
1471
only_change_inv = True
1397
1472
elif not self.has_filename(from_rel) and self.has_filename(to_rel):
2032
all_files = set() # specified and nested files
1967
2033
unknown_nested_files=set()
1968
2034
if to_file is None:
1969
2035
to_file = sys.stdout
2037
files_to_backup = []
1971
2039
def recurse_directory_to_add_files(directory):
1972
2040
# Recurse directory and add all files
1973
2041
# so we can check if they have changed.
1974
2042
for parent_info, file_infos in self.walkdirs(directory):
1975
2043
for relpath, basename, kind, lstat, fileid, kind in file_infos:
1976
2044
# Is it versioned or ignored?
1977
if self.path2id(relpath) or self.is_ignored(relpath):
2045
if self.path2id(relpath):
1978
2046
# Add nested content for deletion.
1979
new_files.add(relpath)
2047
all_files.add(relpath)
1981
# Files which are not versioned and not ignored
2049
# Files which are not versioned
1982
2050
# should be treated as unknown.
1983
unknown_nested_files.add((relpath, None, kind))
2051
files_to_backup.append(relpath)
1985
2053
for filename in files:
1986
2054
# Get file name into canonical form.
1987
2055
abspath = self.abspath(filename)
1988
2056
filename = self.relpath(abspath)
1989
2057
if len(filename) > 0:
1990
new_files.add(filename)
2058
all_files.add(filename)
1991
2059
recurse_directory_to_add_files(filename)
1993
files = list(new_files)
2061
files = list(all_files)
1995
2063
if len(files) == 0:
1996
2064
return # nothing to do
2001
2069
# Bail out if we are going to delete files we shouldn't
2002
2070
if not keep_files and not force:
2003
has_changed_files = len(unknown_nested_files) > 0
2004
if not has_changed_files:
2005
for (file_id, path, content_change, versioned, parent_id, name,
2006
kind, executable) in self.iter_changes(self.basis_tree(),
2007
include_unchanged=True, require_versioned=False,
2008
want_unversioned=True, specific_files=files):
2009
if versioned == (False, False):
2010
# The record is unknown ...
2011
if not self.is_ignored(path[1]):
2012
# ... but not ignored
2013
has_changed_files = True
2015
elif (content_change and (kind[1] is not None) and
2016
osutils.is_inside_any(files, path[1])):
2017
# Versioned and changed, but not deleted, and still
2018
# in one of the dirs to be deleted.
2019
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])
2022
if has_changed_files:
2023
# Make delta show ALL applicable changes in error message.
2024
tree_delta = self.changes_from(self.basis_tree(),
2025
require_versioned=False, want_unversioned=True,
2026
specific_files=files)
2027
for unknown_file in unknown_nested_files:
2028
if unknown_file not in tree_delta.unversioned:
2029
tree_delta.unversioned.extend((unknown_file,))
2030
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,
2032
2090
# Build inv_delta and delete files where applicable,
2033
2091
# do this before any modifications to inventory.
2363
2427
def add_conflicts(self, arg):
2364
2428
raise errors.UnsupportedOperation(self.add_conflicts, self)
2367
2430
def conflicts(self):
2368
conflicts = _mod_conflicts.ConflictList()
2369
for conflicted in self._iter_conflicts():
2372
if file_kind(self.abspath(conflicted)) != "file":
2374
except errors.NoSuchFile:
2377
for suffix in ('.THIS', '.OTHER'):
2379
kind = file_kind(self.abspath(conflicted+suffix))
2382
except errors.NoSuchFile:
2386
ctype = {True: 'text conflict', False: 'contents conflict'}[text]
2387
conflicts.append(_mod_conflicts.Conflict.factory(ctype,
2389
file_id=self.path2id(conflicted)))
2431
raise NotImplementedError(self.conflicts)
2392
2433
def walkdirs(self, prefix=""):
2393
2434
"""Walk the directories of this tree.
2656
def check_state(self):
2657
"""Check that the working state is/isn't valid."""
2658
check_refs = self._get_check_refs()
2660
for ref in check_refs:
2663
refs[ref] = self.branch.repository.revision_tree(value)
2666
@needs_tree_write_lock
2667
def reset_state(self, revision_ids=None):
2668
"""Reset the state of the working tree.
2670
This does a hard-reset to a last-known-good state. This is a way to
2671
fix if something got corrupted (like the .bzr/checkout/dirstate file)
2673
if revision_ids is None:
2674
revision_ids = self.get_parent_ids()
2675
if not revision_ids:
2676
rt = self.branch.repository.revision_tree(
2677
_mod_revision.NULL_REVISION)
2679
rt = self.branch.repository.revision_tree(revision_ids[0])
2680
self._write_inventory(rt.inventory)
2681
self.set_parent_ids(revision_ids)
2614
2683
def _get_rules_searcher(self, default_searcher):
2615
2684
"""See Tree._get_rules_searcher."""
2616
2685
if self._rules_searcher is None:
2624
2693
return ShelfManager(self, self._transport)
2627
class WorkingTree2(WorkingTree):
2628
"""This is the Format 2 working tree.
2630
This was the first weave based working tree.
2631
- uses os locks for locking.
2632
- uses the branch last-revision.
2635
def __init__(self, *args, **kwargs):
2636
super(WorkingTree2, self).__init__(*args, **kwargs)
2637
# WorkingTree2 has more of a constraint that self._inventory must
2638
# exist. Because this is an older format, we don't mind the overhead
2639
# caused by the extra computation here.
2641
# Newer WorkingTree's should only have self._inventory set when they
2643
if self._inventory is None:
2644
self.read_working_inventory()
2646
def _get_check_refs(self):
2647
"""Return the references needed to perform a check of this tree."""
2648
return [('trees', self.last_revision())]
2650
def lock_tree_write(self):
2651
"""See WorkingTree.lock_tree_write().
2653
In Format2 WorkingTrees we have a single lock for the branch and tree
2654
so lock_tree_write() degrades to lock_write().
2656
:return: An object with an unlock method which will release the lock
2659
self.branch.lock_write()
2661
self._control_files.lock_write()
2664
self.branch.unlock()
2668
# do non-implementation specific cleanup
2671
# we share control files:
2672
if self._control_files._lock_count == 3:
2673
# _inventory_is_modified is always False during a read lock.
2674
if self._inventory_is_modified:
2676
self._write_hashcache_if_dirty()
2678
# reverse order of locking.
2680
return self._control_files.unlock()
2682
self.branch.unlock()
2685
2696
class WorkingTree3(WorkingTree):
2686
2697
"""This is the Format 3 working tree.
2760
2772
self.branch.unlock()
2763
def get_conflicted_stem(path):
2764
for suffix in _mod_conflicts.CONFLICT_SUFFIXES:
2765
if path.endswith(suffix):
2766
return path[:-len(suffix)]
2769
class WorkingTreeFormat(object):
2775
class WorkingTreeFormatRegistry(controldir.ControlComponentFormatRegistry):
2776
"""Registry for working tree formats."""
2778
def __init__(self, other_registry=None):
2779
super(WorkingTreeFormatRegistry, self).__init__(other_registry)
2780
self._default_format = None
2782
def get_default(self):
2783
"""Return the current default format."""
2784
return self._default_format
2786
def set_default(self, format):
2787
self._default_format = format
2790
format_registry = WorkingTreeFormatRegistry()
2793
class WorkingTreeFormat(controldir.ControlComponentFormat):
2770
2794
"""An encapsulation of the initialization and open routines for a format.
2772
2796
Formats provide three things:
2784
2808
object will be created every time regardless.
2787
_default_format = None
2788
"""The default format used for new trees."""
2791
"""The known formats."""
2793
2811
requires_rich_root = False
2795
2813
upgrade_recommended = False
2815
requires_normalized_unicode_filenames = False
2817
case_sensitive_filename = "FoRMaT"
2819
missing_parent_conflicts = False
2820
"""If this format supports missing parent conflicts."""
2798
2823
def find_format(klass, a_bzrdir):
2799
2824
"""Return the format for the working tree object in a_bzrdir."""
2801
2826
transport = a_bzrdir.get_workingtree_transport(None)
2802
2827
format_string = transport.get_bytes("format")
2803
return klass._formats[format_string]
2828
return format_registry.get(format_string)
2804
2829
except errors.NoSuchFile:
2805
2830
raise errors.NoWorkingTree(base=transport.base)
2806
2831
except KeyError:
2807
2832
raise errors.UnknownFormatError(format=format_string,
2808
2833
kind="working tree")
2835
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2836
accelerator_tree=None, hardlink=False):
2837
"""Initialize a new working tree in a_bzrdir.
2839
:param a_bzrdir: BzrDir to initialize the working tree in.
2840
:param revision_id: allows creating a working tree at a different
2841
revision than the branch is at.
2842
:param from_branch: Branch to checkout
2843
:param accelerator_tree: A tree which can be used for retrieving file
2844
contents more quickly than the revision tree, i.e. a workingtree.
2845
The revision tree will be used for cases where accelerator_tree's
2846
content is different.
2847
:param hardlink: If true, hard-link files from accelerator_tree,
2850
raise NotImplementedError(self.initialize)
2810
2852
def __eq__(self, other):
2811
2853
return self.__class__ is other.__class__
2891
@symbol_versioning.deprecated_method(
2892
symbol_versioning.deprecated_in((2, 4, 0)))
2847
2893
def register_format(klass, format):
2848
klass._formats[format.get_format_string()] = format
2894
format_registry.register(format)
2897
@symbol_versioning.deprecated_method(
2898
symbol_versioning.deprecated_in((2, 4, 0)))
2899
def register_extra_format(klass, format):
2900
format_registry.register_extra(format)
2903
@symbol_versioning.deprecated_method(
2904
symbol_versioning.deprecated_in((2, 4, 0)))
2905
def unregister_extra_format(klass, format):
2906
format_registry.unregister_extra(format)
2909
@symbol_versioning.deprecated_method(
2910
symbol_versioning.deprecated_in((2, 4, 0)))
2911
def get_formats(klass):
2912
return format_registry._get_all()
2915
@symbol_versioning.deprecated_method(
2916
symbol_versioning.deprecated_in((2, 4, 0)))
2851
2917
def set_default_format(klass, format):
2852
klass._default_format = format
2918
format_registry.set_default(format)
2921
@symbol_versioning.deprecated_method(
2922
symbol_versioning.deprecated_in((2, 4, 0)))
2855
2923
def unregister_format(klass, format):
2856
del klass._formats[format.get_format_string()]
2859
class WorkingTreeFormat2(WorkingTreeFormat):
2860
"""The second working tree format.
2862
This format modified the hash cache from the format 1 hash cache.
2865
upgrade_recommended = True
2867
def get_format_description(self):
2868
"""See WorkingTreeFormat.get_format_description()."""
2869
return "Working tree format 2"
2871
def _stub_initialize_on_transport(self, transport, file_mode):
2872
"""Workaround: create control files for a remote working tree.
2874
This ensures that it can later be updated and dealt with locally,
2875
since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
2876
no working tree. (See bug #43064).
2879
inv = inventory.Inventory()
2880
xml5.serializer_v5.write_inventory(inv, sio, working=True)
2882
transport.put_file('inventory', sio, file_mode)
2883
transport.put_bytes('pending-merges', '', file_mode)
2885
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2886
accelerator_tree=None, hardlink=False):
2887
"""See WorkingTreeFormat.initialize()."""
2888
if not isinstance(a_bzrdir.transport, LocalTransport):
2889
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2890
if from_branch is not None:
2891
branch = from_branch
2893
branch = a_bzrdir.open_branch()
2894
if revision_id is None:
2895
revision_id = _mod_revision.ensure_null(branch.last_revision())
2898
branch.generate_revision_history(revision_id)
2901
inv = inventory.Inventory()
2902
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2908
basis_tree = branch.repository.revision_tree(revision_id)
2909
if basis_tree.inventory.root is not None:
2910
wt.set_root_id(basis_tree.get_root_id())
2911
# set the parent list and cache the basis tree.
2912
if _mod_revision.is_null(revision_id):
2915
parent_trees = [(revision_id, basis_tree)]
2916
wt.set_parent_trees(parent_trees)
2917
transform.build_tree(basis_tree, wt)
2921
super(WorkingTreeFormat2, self).__init__()
2922
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2924
def open(self, a_bzrdir, _found=False):
2925
"""Return the WorkingTree object for a_bzrdir
2927
_found is a private parameter, do not use it. It is used to indicate
2928
if format probing has already been done.
2931
# we are being called directly and must probe.
2932
raise NotImplementedError
2933
if not isinstance(a_bzrdir.transport, LocalTransport):
2934
raise errors.NotLocalUrl(a_bzrdir.transport.base)
2935
wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
2924
format_registry.remove(format)
2941
2927
class WorkingTreeFormat3(WorkingTreeFormat):
2942
2928
"""The second working tree format updated to record a format marker.
3072
3060
__default_format = WorkingTreeFormat6()
3073
WorkingTreeFormat.register_format(__default_format)
3074
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3075
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3076
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3077
WorkingTreeFormat.set_default_format(__default_format)
3078
# formats which have no format string are not discoverable
3079
# and not independently creatable, so are not registered.
3080
_legacy_formats = [WorkingTreeFormat2(),
3061
format_registry.register_lazy("Bazaar Working Tree Format 4 (bzr 0.15)\n",
3062
"bzrlib.workingtree_4", "WorkingTreeFormat4")
3063
format_registry.register_lazy("Bazaar Working Tree Format 5 (bzr 1.11)\n",
3064
"bzrlib.workingtree_4", "WorkingTreeFormat5")
3065
format_registry.register_lazy("Bazaar Working Tree Format 6 (bzr 1.14)\n",
3066
"bzrlib.workingtree_4", "WorkingTreeFormat6")
3067
format_registry.register(WorkingTreeFormat3())
3068
format_registry.set_default(__default_format)