1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
90
85
from bzrlib import symbol_versioning
91
86
from bzrlib.decorators import needs_read_lock, needs_write_lock
92
from bzrlib.inventory import InventoryEntry, Inventory, ROOT_ID, TreeReference
93
87
from bzrlib.lockable_files import LockableFiles
94
88
from bzrlib.lockdir import LockDir
95
89
import bzrlib.mutabletree
96
90
from bzrlib.mutabletree import needs_tree_write_lock
97
91
from bzrlib import osutils
98
92
from bzrlib.osutils import (
111
103
from bzrlib.trace import mutter, note
112
104
from bzrlib.transport.local import LocalTransport
113
105
from bzrlib.progress import DummyProgress, ProgressPhase
114
from bzrlib.revision import NULL_REVISION, CURRENT_REVISION
106
from bzrlib.revision import CURRENT_REVISION
115
107
from bzrlib.rio import RioReader, rio_file, Stanza
116
from bzrlib.symbol_versioning import (deprecated_passed,
119
DEPRECATED_PARAMETER,
108
from bzrlib.symbol_versioning import (
110
DEPRECATED_PARAMETER,
123
114
MERGE_MODIFIED_HEADER_1 = "BZR merge-modified list format 1"
290
281
self._control_files.break_lock()
291
282
self.branch.break_lock()
284
def _get_check_refs(self):
285
"""Return the references needed to perform a check of this tree.
287
The default implementation returns no refs, and is only suitable for
288
trees that have no local caching and can commit on ghosts at any time.
290
:seealso: bzrlib.check for details about check_refs.
293
294
def requires_rich_root(self):
294
295
return self._format.requires_rich_root
487
488
incorrectly attributed to CURRENT_REVISION (but after committing, the
488
489
attribution will be correct).
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(),
491
maybe_file_parent_keys = []
492
for parent_id in self.get_parent_ids():
494
parent_tree = self.revision_tree(parent_id)
495
except errors.NoSuchRevisionInTree:
496
parent_tree = self.branch.repository.revision_tree(parent_id)
497
parent_tree.lock_read()
499
if file_id not in parent_tree:
501
ie = parent_tree.inventory[file_id]
502
if ie.kind != 'file':
503
# Note: this is slightly unnecessary, because symlinks and
504
# directories have a "text" which is the empty text, and we
505
# know that won't mess up annotations. But it seems cleaner
507
parent_text_key = (file_id, ie.revision)
508
if parent_text_key not in maybe_file_parent_keys:
509
maybe_file_parent_keys.append(parent_text_key)
512
graph = _mod_graph.Graph(self.branch.repository.texts)
513
heads = graph.heads(maybe_file_parent_keys)
514
file_parent_keys = []
515
for key in maybe_file_parent_keys:
517
file_parent_keys.append(key)
519
# Now we have the parents of this content
520
annotator = self.branch.repository.texts.get_annotator()
521
text = self.get_file(file_id).read()
522
this_key =(file_id, default_revision)
523
annotator.add_special_text(this_key, file_parent_keys, text)
524
annotations = [(key[-1], line)
525
for key, line in annotator.annotate_flat(this_key)]
516
528
def _get_ancestors(self, default_revision):
517
529
ancestors = set([default_revision])
738
752
kind = _mapper(stat_result.st_mode)
739
753
if kind == 'file':
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(
754
return self._file_content_summary(path, stat_result)
745
755
elif kind == 'directory':
746
756
# perhaps it looks like a plain directory, but it's really a
755
765
return (kind, None, None, None)
767
def _file_content_summary(self, path, stat_result):
768
size = stat_result.st_size
769
executable = self._is_executable_from_path_and_stat(path, stat_result)
770
# try for a stat cache lookup
771
return ('file', size, executable, self._sha_from_stat(
757
774
def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
758
775
"""Common ghost checking functionality from set_parent_*.
889
906
branch.last_revision().
891
908
from bzrlib.merge import Merger, Merge3Merger
892
pb = bzrlib.ui.ui_factory.nested_progress_bar()
909
pb = ui.ui_factory.nested_progress_bar()
894
911
merger = Merger(self.branch, this_tree=self, pb=pb)
895
912
merger.pp = ProgressPhase("Merge phase", 5, pb)
1081
1098
branch.BranchReferenceFormat().initialize(tree_bzrdir, new_branch)
1083
1100
tree_bzrdir = branch_bzrdir
1084
wt = tree_bzrdir.create_workingtree(NULL_REVISION)
1101
wt = tree_bzrdir.create_workingtree(_mod_revision.NULL_REVISION)
1085
1102
wt.set_parent_ids(self.get_parent_ids())
1086
1103
my_inv = self.inventory
1087
child_inv = Inventory(root_id=None)
1104
child_inv = inventory.Inventory(root_id=None)
1088
1105
new_root = my_inv[file_id]
1089
1106
my_inv.remove_recursive_id(file_id)
1090
1107
new_root.parent_id = None
1115
1132
def _kind(self, relpath):
1116
1133
return osutils.file_kind(self.abspath(relpath))
1118
def list_files(self, include_root=False):
1119
"""Recursively list all files as (path, class, kind, id, entry).
1135
def list_files(self, include_root=False, from_dir=None, recursive=True):
1136
"""List all files as (path, class, kind, id, entry).
1121
1138
Lists, but does not descend into unversioned directories.
1123
1139
This does not include files that have been deleted in this
1140
tree. Skips the control directory.
1126
Skips the control directory.
1142
:param include_root: if True, do not return an entry for the root
1143
:param from_dir: start from this directory or None for the root
1144
:param recursive: whether to recurse into subdirectories or not
1128
1146
# list_files is an iterator, so @needs_read_lock doesn't work properly
1129
1147
# with it. So callers should be careful to always read_lock the tree.
1131
1149
raise errors.ObjectNotLocked(self)
1133
1151
inv = self.inventory
1134
if include_root is True:
1152
if from_dir is None and include_root is True:
1135
1153
yield ('', 'V', 'directory', inv.root.file_id, inv.root)
1136
1154
# Convert these into local objects to save lookup times
1137
1155
pathjoin = osutils.pathjoin
1144
1162
fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
1146
1164
# directory file_id, relative path, absolute path, reverse sorted children
1147
children = os.listdir(self.basedir)
1165
if from_dir is not None:
1166
from_dir_id = inv.path2id(from_dir)
1167
if from_dir_id is None:
1168
# Directory not versioned
1170
from_dir_abspath = pathjoin(self.basedir, from_dir)
1172
from_dir_id = inv.root.file_id
1173
from_dir_abspath = self.basedir
1174
children = os.listdir(from_dir_abspath)
1148
1175
children.sort()
1149
1176
# jam 20060527 The kernel sized tree seems equivalent whether we
1150
1177
# use a deque and popleft to keep them sorted, or if we use a plain
1151
1178
# list and just reverse() them.
1152
1179
children = collections.deque(children)
1153
stack = [(inv.root.file_id, u'', self.basedir, children)]
1180
stack = [(from_dir_id, u'', from_dir_abspath, children)]
1155
1182
from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
1214
1241
if fk != 'directory':
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
1244
# But do this child first if recursing down
1246
new_children = os.listdir(fap)
1248
new_children = collections.deque(new_children)
1249
stack.append((f_ie.file_id, fp, fap, new_children))
1250
# Break out of inner loop,
1251
# so that we start outer loop with child
1226
1254
# if we finished all children, pop it off the stack
1405
1433
inv = self.inventory
1406
1434
for entry in moved:
1408
self._move_entry(_RenameEntry(entry.to_rel, entry.from_id,
1436
self._move_entry(WorkingTree._RenameEntry(
1437
entry.to_rel, entry.from_id,
1409
1438
entry.to_tail, entry.to_parent_id, entry.from_rel,
1410
1439
entry.from_tail, entry.from_parent_id,
1411
1440
entry.only_change_inv))
1462
1491
from_tail = splitpath(from_rel)[-1]
1463
1492
from_id = inv.path2id(from_rel)
1464
1493
if from_id is None:
1465
raise errors.BzrRenameFailedError(from_rel,to_rel,
1466
errors.NotVersionedError(path=str(from_rel)))
1467
from_entry = inv[from_id]
1494
# if file is missing in the inventory maybe it's in the basis_tree
1495
basis_tree = self.branch.basis_tree()
1496
from_id = basis_tree.path2id(from_rel)
1498
raise errors.BzrRenameFailedError(from_rel,to_rel,
1499
errors.NotVersionedError(path=str(from_rel)))
1500
# put entry back in the inventory so we can rename it
1501
from_entry = basis_tree.inventory[from_id].copy()
1504
from_entry = inv[from_id]
1468
1505
from_parent_id = from_entry.parent_id
1469
1506
to_dir, to_tail = os.path.split(to_rel)
1470
1507
to_dir_id = inv.path2id(to_dir)
1562
1599
@needs_write_lock
1563
1600
def pull(self, source, overwrite=False, stop_revision=None,
1564
1601
change_reporter=None, possible_transports=None, local=False):
1565
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1602
top_pb = ui.ui_factory.nested_progress_bar()
1566
1603
source.lock_read()
1568
1605
pp = ProgressPhase("Pull phase", 2, top_pb)
1861
1898
firstline = xml.split('\n', 1)[0]
1862
1899
if (not 'revision_id="' in firstline or
1863
1900
'format="7"' not in firstline):
1864
inv = self.branch.repository.deserialise_inventory(
1901
inv = self.branch.repository._serializer.read_inventory_from_string(
1866
1903
xml = self._create_basis_xml_from_inventory(new_revision, inv)
1867
1904
self._write_basis_inventory(xml)
1868
1905
except (errors.NoSuchRevision, errors.RevisionNotPresent):
2515
2551
return un_resolved, resolved
2517
2553
@needs_read_lock
2554
def _check(self, references):
2555
"""Check the tree for consistency.
2557
:param references: A dict with keys matching the items returned by
2558
self._get_check_refs(), and values from looking those keys up in
2519
2561
tree_basis = self.basis_tree()
2520
2562
tree_basis.lock_read()
2522
repo_basis = self.branch.repository.revision_tree(
2523
self.last_revision())
2564
repo_basis = references[('trees', self.last_revision())]
2524
2565
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2525
2566
raise errors.BzrCheckError(
2526
2567
"Mismatched basis inventory content.")
2572
2613
if self._inventory is None:
2573
2614
self.read_working_inventory()
2616
def _get_check_refs(self):
2617
"""Return the references needed to perform a check of this tree."""
2618
return [('trees', self.last_revision())]
2575
2620
def lock_tree_write(self):
2576
2621
"""See WorkingTree.lock_tree_write().
2624
2669
def _change_last_revision(self, revision_id):
2625
2670
"""See WorkingTree._change_last_revision."""
2626
if revision_id is None or revision_id == NULL_REVISION:
2671
if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
2628
2673
self._transport.delete('last-revision')
2629
2674
except errors.NoSuchFile:
2634
2679
mode=self.bzrdir._get_file_mode())
2682
def _get_check_refs(self):
2683
"""Return the references needed to perform a check of this tree."""
2684
return [('trees', self.last_revision())]
2637
2686
@needs_tree_write_lock
2638
2687
def set_conflicts(self, conflicts):
2639
2688
self._put_rio('conflicts', conflicts.to_stanzas(),
2938
2987
# only set an explicit root id if there is one to set.
2939
2988
if basis_tree.inventory.root is not None:
2940
2989
wt.set_root_id(basis_tree.get_root_id())
2941
if revision_id == NULL_REVISION:
2990
if revision_id == _mod_revision.NULL_REVISION:
2942
2991
wt.set_parent_trees([])
2944
2993
wt.set_parent_trees([(revision_id, basis_tree)])
2986
3035
return self.get_format_string()
2989
__default_format = WorkingTreeFormat4()
3038
__default_format = WorkingTreeFormat6()
2990
3039
WorkingTreeFormat.register_format(__default_format)
2991
WorkingTreeFormat.register_format(WorkingTreeFormat6())
2992
3040
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3041
WorkingTreeFormat.register_format(WorkingTreeFormat4())
2993
3042
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2994
3043
WorkingTreeFormat.set_default_format(__default_format)
2995
3044
# formats which have no format string are not discoverable