23
23
ExistingLimbo, ImmortalLimbo)
24
24
from bzrlib.inventory import InventoryEntry
25
25
from bzrlib.osutils import file_kind, supports_executable, pathjoin
26
from bzrlib.progress import DummyProgress
26
27
from bzrlib.trace import mutter, warning
61
62
* set_executability
63
def __init__(self, tree):
64
def __init__(self, tree, pb=DummyProgress()):
64
65
"""Note: a write lock is taken on the tree.
66
67
Use TreeTransform.finalize() to release the lock
677
679
tree_paths = list(self._tree_path_ids.iteritems())
678
680
tree_paths.sort(reverse=True)
679
for path, trans_id in tree_paths:
681
for num, data in enumerate(tree_paths):
682
path, trans_id = data
683
self._pb.update('removing file', num+1, len(tree_paths))
680
684
full_path = self._tree.abspath(path)
681
685
if trans_id in self._removed_contents:
682
686
self.delete_any(full_path)
705
710
limbo any files that needed renaming. This must be done in strict
706
711
parent-to-child order.
708
for path, trans_id in self.new_paths():
713
new_paths = self.new_paths()
714
for num, (path, trans_id) in enumerate(new_paths):
715
self._pb.update('adding file', num+1, len(new_paths))
710
717
kind = self._new_contents[trans_id]
736
743
# requires files and inventory entries to be in place
737
744
if trans_id in self._new_executability:
738
745
self._set_executability(path, inv, trans_id)
740
748
def _set_executability(self, path, inv, trans_id):
741
749
"""Set the executability of versioned files """
985
993
return has_contents, contents_mod, meta_mod
988
def revert(working_tree, target_tree, filenames, backups=False):
996
def revert(working_tree, target_tree, filenames, backups=False,
989
998
"""Revert a working tree's contents to those of a target tree."""
990
999
interesting_ids = find_interesting(working_tree, target_tree, filenames)
991
1000
def interesting(file_id):
992
1001
return interesting_ids is None or file_id in interesting_ids
994
tt = TreeTransform(working_tree)
1003
tt = TreeTransform(working_tree, pb)
997
1006
def trans_id_file_id(file_id):
1000
1009
except KeyError:
1001
1010
return tt.trans_id_tree_file_id(file_id)
1003
for file_id in topology_sorted_ids(target_tree):
1004
if not interesting(file_id):
1012
sorted_interesting = [i for i in topology_sorted_ids(target_tree) if
1014
for id_num, file_id in enumerate(sorted_interesting):
1015
pb.update("Reverting file", id_num+1, len(sorted_interesting))
1006
1016
if file_id not in working_tree.inventory:
1007
1017
entry = target_tree.inventory[file_id]
1008
1018
parent_id = trans_id_file_id(entry.parent_id)
1012
1022
change_entry(tt, file_id, working_tree, target_tree,
1013
1023
trans_id_file_id, backups, trans_id)
1014
for file_id in working_tree.inventory:
1015
if not interesting(file_id):
1024
wt_interesting = [i for i in working_tree.inventory if interesting(i)]
1025
for id_num, file_id in enumerate(wt_interesting):
1026
pb.update("New file check", id_num+1, len(sorted_interesting))
1017
1027
if file_id not in target_tree:
1018
1028
tt.unversion_file(tt.trans_id_tree_file_id(file_id))
1019
raw_conflicts = resolve_conflicts(tt)
1029
raw_conflicts = resolve_conflicts(tt, pb)
1020
1030
for line in conflicts_strings(cook_conflicts(raw_conflicts, tt)):
1027
def resolve_conflicts(tt):
1038
def resolve_conflicts(tt, pb=DummyProgress()):
1028
1039
"""Make many conflict-resolution attempts, but die if they fail"""
1029
1040
new_conflicts = set()
1031
conflicts = tt.find_conflicts()
1032
if len(conflicts) == 0:
1033
return new_conflicts
1034
new_conflicts.update(conflict_pass(tt, conflicts))
1035
raise MalformedTransform(conflicts=conflicts)
1043
pb.update('Resolution pass', n+1, 10)
1044
conflicts = tt.find_conflicts()
1045
if len(conflicts) == 0:
1046
return new_conflicts
1047
new_conflicts.update(conflict_pass(tt, conflicts))
1048
raise MalformedTransform(conflicts=conflicts)
1038
1053
def conflict_pass(tt, conflicts):