84
90
from bzrlib import symbol_versioning
85
91
from bzrlib.decorators import needs_read_lock, needs_write_lock
92
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
86
93
from bzrlib.lockable_files import LockableFiles
87
94
from bzrlib.lockdir import LockDir
88
95
import bzrlib.mutabletree
89
96
from bzrlib.mutabletree import needs_tree_write_lock
90
97
from bzrlib import osutils
91
98
from bzrlib.osutils import (
102
111
from bzrlib.trace import mutter, note
103
112
from bzrlib.transport.local import LocalTransport
104
113
from bzrlib.progress import DummyProgress, ProgressPhase
105
from bzrlib.revision import CURRENT_REVISION
114
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
106
115
from bzrlib.rio import RioReader, rio_file, Stanza
107
from bzrlib.symbol_versioning import (
109
DEPRECATED_PARAMETER,
116
from bzrlib.symbol_versioning import (deprecated_passed,
119
DEPRECATED_PARAMETER,
113
123
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
280
290
self._control_files.break_lock()
281
291
self.branch.break_lock()
283
def _get_check_refs(self):
284
"""Return the references needed to perform a check of this tree.
286
The default implementation returns no refs, and is only suitable for
287
trees that have no local caching and can commit on ghosts at any time.
289
:seealso: bzrlib.check for details about check_refs.
293
293
def requires_rich_root(self):
294
294
return self._format.requires_rich_root
447
447
def get_file_with_stat(self, file_id, path=None, filtered=True,
448
448
_fstat=os.fstat):
449
"""See Tree.get_file_with_stat."""
449
"""See MutableTree.get_file_with_stat."""
451
451
path = self.id2path(file_id)
452
452
file_obj = self.get_file_byname(path, filtered=False)
453
453
stat_value = _fstat(file_obj.fileno())
454
if filtered and self.supports_content_filtering():
454
if self.supports_content_filtering() and filtered:
455
455
filters = self._content_filter_stack(path)
456
456
file_obj = filtered_input_file(file_obj, filters)
457
457
return (file_obj, stat_value)
462
462
def get_file_byname(self, filename, filtered=True):
463
463
path = self.abspath(filename)
464
464
f = file(path, 'rb')
465
if filtered and self.supports_content_filtering():
465
if self.supports_content_filtering() and filtered:
466
466
filters = self._content_filter_stack(filename)
467
467
return filtered_input_file(f, filters)
487
487
incorrectly attributed to CURRENT_REVISION (but after committing, the
488
488
attribution will be correct).
490
maybe_file_parent_keys = []
491
for parent_id in self.get_parent_ids():
493
parent_tree = self.revision_tree(parent_id)
494
except errors.NoSuchRevisionInTree:
495
parent_tree = self.branch.repository.revision_tree(parent_id)
496
parent_tree.lock_read()
498
if file_id not in parent_tree:
500
ie = parent_tree.inventory[file_id]
501
if ie.kind != 'file':
502
# Note: this is slightly unnecessary, because symlinks and
503
# directories have a "text" which is the empty text, and we
504
# know that won't mess up annotations. But it seems cleaner
506
parent_text_key = (file_id, ie.revision)
507
if parent_text_key not in maybe_file_parent_keys:
508
maybe_file_parent_keys.append(parent_text_key)
511
graph = _mod_graph.Graph(self.branch.repository.texts)
512
heads = graph.heads(maybe_file_parent_keys)
513
file_parent_keys = []
514
for key in maybe_file_parent_keys:
516
file_parent_keys.append(key)
518
# Now we have the parents of this content
519
annotator = self.branch.repository.texts.get_annotator()
520
text = self.get_file(file_id).read()
521
this_key =(file_id, default_revision)
522
annotator.add_special_text(this_key, file_parent_keys, text)
523
annotations = [(key[-1], line)
524
for key, line in annotator.annotate_flat(this_key)]
490
basis = self.basis_tree()
493
changes = self.iter_changes(basis, True, [self.id2path(file_id)],
494
require_versioned=True).next()
495
changed_content, kind = changes[2], changes[6]
496
if not changed_content:
497
return basis.annotate_iter(file_id)
501
if kind[0] != 'file':
504
old_lines = list(basis.annotate_iter(file_id))
506
for tree in self.branch.repository.revision_trees(
507
self.get_parent_ids()[1:]):
508
if file_id not in tree:
510
old.append(list(tree.annotate_iter(file_id)))
511
return annotate.reannotate(old, self.get_file(file_id).readlines(),
527
516
def _get_ancestors(self, default_revision):
528
517
ancestors = set([default_revision])
544
533
parents = [last_rev]
546
merges_bytes = self._transport.get_bytes('pending-merges')
535
merges_file = self._transport.get('pending-merges')
547
536
except errors.NoSuchFile:
550
for l in osutils.split_lines(merges_bytes):
539
for l in merges_file.readlines():
551
540
revision_id = l.rstrip('\n')
552
541
parents.append(revision_id)
636
623
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
637
624
file_id = self.path2id(path)
639
# For unversioned files on win32, we just assume they are not
642
625
return self._inventory[file_id].executable
644
627
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
755
738
kind = _mapper(stat_result.st_mode)
756
739
if kind == 'file':
757
return self._file_content_summary(path, stat_result)
740
size = stat_result.st_size
741
# try for a stat cache lookup
742
executable = self._is_executable_from_path_and_stat(path, stat_result)
743
return (kind, size, executable, self._sha_from_stat(
758
745
elif kind == 'directory':
759
746
# perhaps it looks like a plain directory, but it's really a
768
755
return (kind, None, None, None)
770
def _file_content_summary(self, path, stat_result):
771
size = stat_result.st_size
772
executable = self._is_executable_from_path_and_stat(path, stat_result)
773
# try for a stat cache lookup
774
return ('file', size, executable, self._sha_from_stat(
777
757
def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
778
758
"""Common ghost checking functionality from set_parent_*.
900
880
@needs_write_lock # because merge pulls data into the branch.
901
881
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
902
merge_type=None, force=False):
903
883
"""Merge from a branch into this working tree.
905
885
:param branch: The branch to merge from.
909
889
branch.last_revision().
911
891
from bzrlib.merge import Merger, Merge3Merger
912
pb = ui.ui_factory.nested_progress_bar()
892
pb = bzrlib.ui.ui_factory.nested_progress_bar()
914
894
merger = Merger(self.branch, this_tree=self, pb=pb)
915
895
merger.pp = ProgressPhase("Merge phase", 5, pb)
916
896
merger.pp.next_phase()
917
# check that there are no local alterations
918
if not force and self.has_changes():
919
raise errors.UncommittedChanges(self)
897
# check that there are no
899
merger.check_basis(check_clean=True, require_commits=False)
920
900
if to_revision is None:
921
901
to_revision = _mod_revision.ensure_null(branch.last_revision())
922
902
merger.other_rev_id = to_revision
1101
1081
branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1103
1083
tree_bzrdir = branch_bzrdir
1104
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1084
wt = tree_bzrdir.create_workingtree(NULL_REVISION)
1105
1085
wt.set_parent_ids(self.get_parent_ids())
1106
1086
my_inv = self.inventory
1107
child_inv = inventory.Inventory(root_id=None)
1087
child_inv = Inventory(root_id=None)
1108
1088
new_root = my_inv[file_id]
1109
1089
my_inv.remove_recursive_id(file_id)
1110
1090
new_root.parent_id = None
1135
1115
def _kind(self, relpath):
1136
1116
return osutils.file_kind(self.abspath(relpath))
1138
def list_files(self, include_root=False, from_dir=None, recursive=True):
1139
"""List all files as (path, class, kind, id, entry).
1118
def list_files(self, include_root=False):
1119
"""Recursively list all files as (path, class, kind, id, entry).
1141
1121
Lists, but does not descend into unversioned directories.
1142
1123
This does not include files that have been deleted in this
1143
tree. Skips the control directory.
1145
:param include_root: if True, do not return an entry for the root
1146
:param from_dir: start from this directory or None for the root
1147
:param recursive: whether to recurse into subdirectories or not
1126
Skips the control directory.
1149
1128
# list_files is an iterator, so @needs_read_lock doesn't work properly
1150
1129
# with it. So callers should be careful to always read_lock the tree.
1152
1131
raise errors.ObjectNotLocked(self)
1154
1133
inv = self.inventory
1155
if from_dir is None and include_root is True:
1134
if include_root is True:
1156
1135
yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1157
1136
# Convert these into local objects to save lookup times
1158
1137
pathjoin = osutils.pathjoin
1165
1144
fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1167
1146
# directory file_id, relative path, absolute path, reverse sorted children
1168
if from_dir is not None:
1169
from_dir_id = inv.path2id(from_dir)
1170
if from_dir_id is None:
1171
# Directory not versioned
1173
from_dir_abspath = pathjoin(self.basedir, from_dir)
1175
from_dir_id = inv.root.file_id
1176
from_dir_abspath = self.basedir
1177
children = os.listdir(from_dir_abspath)
1147
children = os.listdir(self.basedir)
1178
1148
children.sort()
1179
1149
# jam 20060527 The kernel sized tree seems equivalent whether we
1180
1150
# use a deque and popleft to keep them sorted, or if we use a plain
1181
1151
# list and just reverse() them.
1182
1152
children = collections.deque(children)
1183
stack = [(from_dir_id, u'', from_dir_abspath, children)]
1153
stack = [(inv.root.file_id, u'', self.basedir, children)]
1185
1155
from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1244
1214
if fk != 'directory':
1247
# But do this child first if recursing down
1249
new_children = os.listdir(fap)
1251
new_children = collections.deque(new_children)
1252
stack.append((f_ie.file_id, fp, fap, new_children))
1253
# Break out of inner loop,
1254
# so that we start outer loop with child
1217
# But do this child first
1218
new_children = os.listdir(fap)
1220
new_children = collections.deque(new_children)
1221
stack.append((f_ie.file_id, fp, fap, new_children))
1222
# Break out of inner loop,
1223
# so that we start outer loop with child
1257
1226
# if we finished all children, pop it off the stack
1436
1405
inv = self.inventory
1437
1406
for entry in moved:
1439
self._move_entry(WorkingTree._RenameEntry(
1440
entry.to_rel, entry.from_id,
1408
self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
1441
1409
entry.to_tail, entry.to_parent_id, entry.from_rel,
1442
1410
entry.from_tail, entry.from_parent_id,
1443
1411
entry.only_change_inv))
1494
1462
from_tail = splitpath(from_rel)[-1]
1495
1463
from_id = inv.path2id(from_rel)
1496
1464
if from_id is None:
1497
# if file is missing in the inventory maybe it's in the basis_tree
1498
basis_tree = self.branch.basis_tree()
1499
from_id = basis_tree.path2id(from_rel)
1501
raise errors.BzrRenameFailedError(from_rel,to_rel,
1502
errors.NotVersionedError(path=str(from_rel)))
1503
# put entry back in the inventory so we can rename it
1504
from_entry = basis_tree.inventory[from_id].copy()
1507
from_entry = inv[from_id]
1465
raise errors.BzrRenameFailedError(from_rel,to_rel,
1466
errors.NotVersionedError(path=str(from_rel)))
1467
from_entry = inv[from_id]
1508
1468
from_parent_id = from_entry.parent_id
1509
1469
to_dir, to_tail = os.path.split(to_rel)
1510
1470
to_dir_id = inv.path2id(to_dir)
1602
1562
@needs_write_lock
1603
1563
def pull(self, source, overwrite=False, stop_revision=None,
1604
1564
change_reporter=None, possible_transports=None, local=False):
1605
top_pb = ui.ui_factory.nested_progress_bar()
1565
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1606
1566
source.lock_read()
1608
1568
pp = ProgressPhase("Pull phase", 2, top_pb)
1627
1587
this_tree=self,
1629
1589
change_reporter=change_reporter)
1630
basis_root_id = basis_tree.get_root_id()
1631
new_root_id = new_basis_tree.get_root_id()
1632
if basis_root_id != new_root_id:
1633
self.set_root_id(new_root_id)
1590
if (basis_tree.inventory.root is None and
1591
new_basis_tree.inventory.root is not None):
1592
self.set_root_id(new_basis_tree.get_root_id())
1636
1595
basis_tree.unlock()
1742
1701
r"""Check whether the filename matches an ignore pattern.
1744
1703
Patterns containing '/' or '\' need to match the whole path;
1745
others match against only the last component. Patterns starting
1746
with '!' are ignore exceptions. Exceptions take precedence
1747
over regular patterns and cause the filename to not be ignored.
1704
others match against only the last component.
1749
1706
If the file is ignored, returns the pattern which caused it to
1750
1707
be ignored, otherwise None. So this can simply be used as a
1751
1708
boolean if desired."""
1752
1709
if getattr(self, '_ignoreglobster', None) is None:
1753
self._ignoreglobster = globbing.ExceptionGlobster(self.get_ignore_list())
1710
self._ignoreglobster = globbing.Globster(self.get_ignore_list())
1754
1711
return self._ignoreglobster.match(filename)
1756
1713
def kind(self, file_id):
1847
1804
def _reset_data(self):
1848
1805
"""Reset transient data that cannot be revalidated."""
1849
1806
self._inventory_is_modified = False
1850
f = self._transport.get('inventory')
1852
result = self._deserialize(f)
1807
result = self._deserialize(self._transport.get('inventory'))
1855
1808
self._set_inventory(result, dirty=False)
1857
1810
@needs_tree_write_lock
1904
1857
# revision_id is set. We must check for this full string, because a
1905
1858
# root node id can legitimately look like 'revision_id' but cannot
1906
1859
# contain a '"'.
1907
xml = self.branch.repository._get_inventory_xml(new_revision)
1860
xml = self.branch.repository.get_inventory_xml(new_revision)
1908
1861
firstline = xml.split('\n', 1)[0]
1909
1862
if (not 'revision_id="' in firstline or
1910
1863
'format="7"' not in firstline):
1911
inv = self.branch.repository._serializer.read_inventory_from_string(
1864
inv = self.branch.repository.deserialise_inventory(
1913
1866
xml = self._create_basis_xml_from_inventory(new_revision, inv)
1914
1867
self._write_basis_inventory(xml)
1915
1868
except (errors.NoSuchRevision, errors.RevisionNotPresent):
1934
1887
if self._inventory_is_modified:
1935
1888
raise errors.InventoryModified(self)
1936
f = self._transport.get('inventory')
1938
result = self._deserialize(f)
1889
result = self._deserialize(self._transport.get('inventory'))
1941
1890
self._set_inventory(result, dirty=False)
2035
1982
new_status = 'I'
2037
1984
new_status = '?'
2038
# XXX: Really should be a more abstract reporter interface
2039
kind_ch = osutils.kind_marker(self.kind(fid))
2040
to_file.write(new_status + ' ' + f + kind_ch + '\n')
1985
textui.show_status(new_status, self.kind(fid), f,
2041
1987
# Unversion file
2042
1988
inv_delta.append((f, None, fid, None))
2043
1989
message = "removed %s" % (f,)
2195
2142
raise NotImplementedError(self.unlock)
2199
def update(self, change_reporter=None, possible_transports=None,
2200
revision=None, old_tip=_marker):
2144
def update(self, change_reporter=None, possible_transports=None):
2201
2145
"""Update a working tree along its branch.
2203
2147
This will update the branch if its bound too, which means we have
2221
2165
- Merge current state -> basis tree of the master w.r.t. the old tree
2223
2167
- Do a 'normal' merge of the old branch basis if it is relevant.
2225
:param revision: The target revision to update to. Must be in the
2227
:param old_tip: If branch.update() has already been run, the value it
2228
returned (old tip of the branch or None). _marker is used
2231
2169
if self.branch.get_bound_location() is not None:
2232
2170
self.lock_write()
2233
update_branch = (old_tip is self._marker)
2171
update_branch = True
2235
2173
self.lock_tree_write()
2236
2174
update_branch = False
2238
2176
if update_branch:
2239
2177
old_tip = self.branch.update(possible_transports)
2241
if old_tip is self._marker:
2243
return self._update_tree(old_tip, change_reporter, revision)
2180
return self._update_tree(old_tip, change_reporter)
2247
2184
@needs_tree_write_lock
2248
def _update_tree(self, old_tip=None, change_reporter=None, revision=None):
2185
def _update_tree(self, old_tip=None, change_reporter=None):
2249
2186
"""Update a tree to the master branch.
2251
2188
:param old_tip: if supplied, the previous tip revision the branch,
2266
2203
last_rev = self.get_parent_ids()[0]
2267
2204
except IndexError:
2268
2205
last_rev = _mod_revision.NULL_REVISION
2269
if revision is None:
2270
revision = self.branch.last_revision()
2272
if revision not in self.branch.revision_history():
2273
raise errors.NoSuchRevision(self.branch, revision)
2274
if last_rev != _mod_revision.ensure_null(revision):
2275
# merge tree state up to specified revision.
2206
if last_rev != _mod_revision.ensure_null(self.branch.last_revision()):
2207
# merge tree state up to new branch tip.
2276
2208
basis = self.basis_tree()
2277
2209
basis.lock_read()
2279
to_tree = self.branch.repository.revision_tree(revision)
2280
to_root_id = to_tree.get_root_id()
2281
if (basis.inventory.root is None
2282
or basis.inventory.root.file_id != to_root_id):
2283
self.set_root_id(to_root_id)
2211
to_tree = self.branch.basis_tree()
2212
if basis.inventory.root is None:
2213
self.set_root_id(to_tree.get_root_id())
2285
2215
result += merge.merge_inner(
2289
2219
this_tree=self,
2290
2220
change_reporter=change_reporter)
2291
self.set_last_revision(revision)
2294
2223
# TODO - dedup parents list with things merged by pull ?
2295
2224
# reuse the tree we've updated to to set the basis:
2296
parent_trees = [(revision, to_tree)]
2225
parent_trees = [(self.branch.last_revision(), to_tree)]
2297
2226
merges = self.get_parent_ids()[1:]
2298
2227
# Ideally we ask the tree for the trees here, that way the working
2299
2228
# tree can decide whether to give us the entire tree or give us a
2329
2258
# should be able to remove this extra flush.
2331
2260
graph = self.branch.repository.get_graph()
2332
base_rev_id = graph.find_unique_lca(revision, old_tip)
2261
base_rev_id = graph.find_unique_lca(self.branch.last_revision(),
2333
2263
base_tree = self.branch.repository.revision_tree(base_rev_id)
2334
2264
other_tree = self.branch.repository.revision_tree(old_tip)
2335
2265
result += merge.merge_inner(
2585
2515
return un_resolved, resolved
2587
2517
@needs_read_lock
2588
def _check(self, references):
2589
"""Check the tree for consistency.
2591
:param references: A dict with keys matching the items returned by
2592
self._get_check_refs(), and values from looking those keys up in
2595
2519
tree_basis = self.basis_tree()
2596
2520
tree_basis.lock_read()
2598
repo_basis = references[('trees', self.last_revision())]
2522
repo_basis = self.branch.repository.revision_tree(
2523
self.last_revision())
2599
2524
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2600
2525
raise errors.BzrCheckError(
2601
2526
"Mismatched basis inventory content.")
2646
2572
if self._inventory is None:
2647
2573
self.read_working_inventory()
2649
def _get_check_refs(self):
2650
"""Return the references needed to perform a check of this tree."""
2651
return [('trees', self.last_revision())]
2653
2575
def lock_tree_write(self):
2654
2576
"""See WorkingTree.lock_tree_write().
2702
2624
def _change_last_revision(self, revision_id):
2703
2625
"""See WorkingTree._change_last_revision."""
2704
if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2626
if revision_id is None or revision_id == NULL_REVISION:
2706
2628
self._transport.delete('last-revision')
2707
2629
except errors.NoSuchFile:
2712
2634
mode=self.bzrdir._get_file_mode())
2715
def _get_check_refs(self):
2716
"""Return the references needed to perform a check of this tree."""
2717
return [('trees', self.last_revision())]
2719
2637
@needs_tree_write_lock
2720
2638
def set_conflicts(self, conflicts):
2721
2639
self._put_rio('conflicts', conflicts.to_stanzas(),
2798
2716
"""Return the format for the working tree object in a_bzrdir."""
2800
2718
transport = a_bzrdir.get_workingtree_transport(None)
2801
format_string = transport.get_bytes("format")
2719
format_string = transport.get("format").read()
2802
2720
return klass._formats[format_string]
2803
2721
except errors.NoSuchFile:
2804
2722
raise errors.NoWorkingTree(base=transport.base)
3020
2938
# only set an explicit root id if there is one to set.
3021
2939
if basis_tree.inventory.root is not None:
3022
2940
wt.set_root_id(basis_tree.get_root_id())
3023
if revision_id == _mod_revision.NULL_REVISION:
2941
if revision_id == NULL_REVISION:
3024
2942
wt.set_parent_trees([])
3026
2944
wt.set_parent_trees([(revision_id, basis_tree)])
3068
2986
return self.get_format_string()
3071
__default_format = WorkingTreeFormat6()
2989
__default_format = WorkingTreeFormat4()
3072
2990
WorkingTreeFormat.register_format(__default_format)
2991
WorkingTreeFormat.register_format(WorkingTreeFormat6())
3073
2992
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3074
WorkingTreeFormat.register_format(WorkingTreeFormat4())
3075
2993
WorkingTreeFormat.register_format(WorkingTreeFormat3())
3076
2994
WorkingTreeFormat.set_default_format(__default_format)
3077
2995
# formats which have no format string are not discoverable