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
280
280
self._control_files.break_lock()
281
281
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.
283
293
def requires_rich_root(self):
284
294
return self._format.requires_rich_root
477
487
incorrectly attributed to CURRENT_REVISION (but after committing, the
478
488
attribution will be correct).
480
basis = self.basis_tree()
483
changes = self.iter_changes(basis, True, [self.id2path(file_id)],
484
require_versioned=True).next()
485
changed_content, kind = changes[2], changes[6]
486
if not changed_content:
487
return basis.annotate_iter(file_id)
491
if kind[0] != 'file':
494
old_lines = list(basis.annotate_iter(file_id))
496
for tree in self.branch.repository.revision_trees(
497
self.get_parent_ids()[1:]):
498
if file_id not in tree:
500
old.append(list(tree.annotate_iter(file_id)))
501
return annotate.reannotate(old, self.get_file(file_id).readlines(),
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)]
506
527
def _get_ancestors(self, default_revision):
507
528
ancestors = set([default_revision])
523
544
parents = [last_rev]
525
merges_file = self._transport.get('pending-merges')
546
merges_bytes = self._transport.get_bytes('pending-merges')
526
547
except errors.NoSuchFile:
529
for l in merges_file.readlines():
550
for l in osutils.split_lines(merges_bytes):
530
551
revision_id = l.rstrip('\n')
531
552
parents.append(revision_id)
613
636
def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
614
637
file_id = self.path2id(path)
639
# For unversioned files on win32, we just assume they are not
615
642
return self._inventory[file_id].executable
617
644
def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):
728
755
kind = _mapper(stat_result.st_mode)
729
756
if kind == 'file':
730
size = stat_result.st_size
731
# try for a stat cache lookup
732
executable = self._is_executable_from_path_and_stat(path, stat_result)
733
return (kind, size, executable, self._sha_from_stat(
757
return self._file_content_summary(path, stat_result)
735
758
elif kind == 'directory':
736
759
# perhaps it looks like a plain directory, but it's really a
745
768
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(
747
777
def _check_parents_for_ghosts(self, revision_ids, allow_leftmost_as_ghost):
748
778
"""Common ghost checking functionality from set_parent_*.
870
900
@needs_write_lock # because merge pulls data into the branch.
871
901
def merge_from_branch(self, branch, to_revision=None, from_revision=None,
902
merge_type=None, force=False):
873
903
"""Merge from a branch into this working tree.
875
905
:param branch: The branch to merge from.
884
914
merger = Merger(self.branch, this_tree=self, pb=pb)
885
915
merger.pp = ProgressPhase("Merge phase", 5, pb)
886
916
merger.pp.next_phase()
887
# check that there are no
889
merger.check_basis(check_clean=True, require_commits=False)
917
# check that there are no local alterations
918
if not force and self.has_changes():
919
raise errors.UncommittedChanges(self)
890
920
if to_revision is None:
891
921
to_revision = _mod_revision.ensure_null(branch.last_revision())
892
922
merger.other_rev_id = to_revision
1464
1494
from_tail = splitpath(from_rel)[-1]
1465
1495
from_id = inv.path2id(from_rel)
1466
1496
if from_id is None:
1467
raise errors.BzrRenameFailedError(from_rel,to_rel,
1468
errors.NotVersionedError(path=str(from_rel)))
1469
from_entry = inv[from_id]
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]
1470
1508
from_parent_id = from_entry.parent_id
1471
1509
to_dir, to_tail = os.path.split(to_rel)
1472
1510
to_dir_id = inv.path2id(to_dir)
1806
1844
def _reset_data(self):
1807
1845
"""Reset transient data that cannot be revalidated."""
1808
1846
self._inventory_is_modified = False
1809
result = self._deserialize(self._transport.get('inventory'))
1847
f = self._transport.get('inventory')
1849
result = self._deserialize(f)
1810
1852
self._set_inventory(result, dirty=False)
1812
1854
@needs_tree_write_lock
1863
1905
firstline = xml.split('\n', 1)[0]
1864
1906
if (not 'revision_id="' in firstline or
1865
1907
'format="7"' not in firstline):
1866
inv = self.branch.repository.deserialise_inventory(
1908
inv = self.branch.repository._serializer.read_inventory_from_string(
1868
1910
xml = self._create_basis_xml_from_inventory(new_revision, inv)
1869
1911
self._write_basis_inventory(xml)
1870
1912
except (errors.NoSuchRevision, errors.RevisionNotPresent):
1889
1931
if self._inventory_is_modified:
1890
1932
raise errors.InventoryModified(self)
1891
result = self._deserialize(self._transport.get('inventory'))
1933
f = self._transport.get('inventory')
1935
result = self._deserialize(f)
1892
1938
self._set_inventory(result, dirty=False)
1984
2032
new_status = 'I'
1986
2034
new_status = '?'
1987
textui.show_status(new_status, self.kind(fid), f,
2035
# XXX: Really should be a more abstract reporter interface
2036
kind_ch = osutils.kind_marker(self.kind(fid))
2037
to_file.write(new_status + ' ' + f + kind_ch + '\n')
1989
2038
# Unversion file
1990
2039
inv_delta.append((f, None, fid, None))
1991
2040
message = "removed %s" % (f,)
2516
2565
return un_resolved, resolved
2518
2567
@needs_read_lock
2568
def _check(self, references):
2569
"""Check the tree for consistency.
2571
:param references: A dict with keys matching the items returned by
2572
self._get_check_refs(), and values from looking those keys up in
2520
2575
tree_basis = self.basis_tree()
2521
2576
tree_basis.lock_read()
2523
repo_basis = self.branch.repository.revision_tree(
2524
self.last_revision())
2578
repo_basis = references[('trees', self.last_revision())]
2525
2579
if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2526
2580
raise errors.BzrCheckError(
2527
2581
"Mismatched basis inventory content.")
2573
2626
if self._inventory is None:
2574
2627
self.read_working_inventory()
2629
def _get_check_refs(self):
2630
"""Return the references needed to perform a check of this tree."""
2631
return [('trees', self.last_revision())]
2576
2633
def lock_tree_write(self):
2577
2634
"""See WorkingTree.lock_tree_write().
2635
2692
mode=self.bzrdir._get_file_mode())
2695
def _get_check_refs(self):
2696
"""Return the references needed to perform a check of this tree."""
2697
return [('trees', self.last_revision())]
2638
2699
@needs_tree_write_lock
2639
2700
def set_conflicts(self, conflicts):
2640
2701
self._put_rio('conflicts', conflicts.to_stanzas(),
2717
2778
"""Return the format for the working tree object in a_bzrdir."""
2719
2780
transport = a_bzrdir.get_workingtree_transport(None)
2720
format_string = transport.get("format").read()
2781
format_string = transport.get_bytes("format")
2721
2782
return klass._formats[format_string]
2722
2783
except errors.NoSuchFile:
2723
2784
raise errors.NoWorkingTree(base=transport.base)
2987
3048
return self.get_format_string()
2990
__default_format = WorkingTreeFormat4()
3051
__default_format = WorkingTreeFormat6()
2991
3052
WorkingTreeFormat.register_format(__default_format)
2992
WorkingTreeFormat.register_format(WorkingTreeFormat6())
2993
3053
WorkingTreeFormat.register_format(WorkingTreeFormat5())
3054
WorkingTreeFormat.register_format(WorkingTreeFormat4())
2994
3055
WorkingTreeFormat.register_format(WorkingTreeFormat3())
2995
3056
WorkingTreeFormat.set_default_format(__default_format)
2996
3057
# formats which have no format string are not discoverable