34
33
revision as _mod_revision,
38
36
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
39
ReusingTransform, CantMoveRoot,
37
ReusingTransform, NotVersionedError, CantMoveRoot,
40
38
ExistingLimbo, ImmortalLimbo, NoFinalPath,
41
39
UnableCreateSymlink)
42
40
from bzrlib.filters import filtered_output_bytes, ContentFilterContext
81
79
class TreeTransformBase(object):
82
80
"""The base class for TreeTransform and its kin."""
84
def __init__(self, tree, pb=None,
82
def __init__(self, tree, pb=DummyProgress(),
85
83
case_sensitive=True):
88
86
:param tree: The tree that will be transformed, but not necessarily
88
:param pb: A ProgressTask indicating how much progress is being made
91
89
:param case_sensitive: If True, the target of the transform is
92
90
case sensitive, not just case preserving.
929
927
return _PreviewTree(self)
931
def commit(self, branch, message, merge_parents=None, strict=False,
932
timestamp=None, timezone=None, committer=None, authors=None,
933
revprops=None, revision_id=None):
929
def commit(self, branch, message, merge_parents=None, strict=False):
934
930
"""Commit the result of this TreeTransform to a branch.
936
932
:param branch: The branch to commit to.
937
933
:param message: The message to attach to the commit.
938
:param merge_parents: Additional parent revision-ids specified by
940
:param strict: If True, abort the commit if there are unversioned
942
:param timestamp: if not None, seconds-since-epoch for the time and
943
date. (May be a float.)
944
:param timezone: Optional timezone for timestamp, as an offset in
946
:param committer: Optional committer in email-id format.
947
(e.g. "J Random Hacker <jrandom@example.com>")
948
:param authors: Optional list of authors in email-id format.
949
:param revprops: Optional dictionary of revision properties.
950
:param revision_id: Optional revision id. (Specifying a revision-id
951
may reduce performance for some non-native formats.)
934
:param merge_parents: Additional parents specified by pending merges.
952
935
:return: The revision_id of the revision committed.
954
937
self._check_malformed()
971
954
if self._tree.get_revision_id() != last_rev_id:
972
955
raise ValueError('TreeTransform not based on branch basis: %s' %
973
956
self._tree.get_revision_id())
974
revprops = commit.Commit.update_revprops(revprops, branch, authors)
975
builder = branch.get_commit_builder(parent_ids,
980
revision_id=revision_id)
957
builder = branch.get_commit_builder(parent_ids)
981
958
preview = self.get_preview_tree()
982
959
list(builder.record_iter_changes(preview, last_rev_id,
983
960
self.iter_changes()))
1085
1062
class DiskTreeTransform(TreeTransformBase):
1086
1063
"""Tree transform storing its contents on disk."""
1088
def __init__(self, tree, limbodir, pb=None,
1065
def __init__(self, tree, limbodir, pb=DummyProgress(),
1089
1066
case_sensitive=True):
1090
1067
"""Constructor.
1091
1068
:param tree: The tree that will be transformed, but not necessarily
1092
1069
the output tree.
1093
1070
:param limbodir: A directory where new files can be stored until
1094
1071
they are installed in their proper places
1072
:param pb: A ProgressBar indicating how much progress is being made
1096
1073
:param case_sensitive: If True, the target of the transform is
1097
1074
case sensitive, not just case preserving.
1182
1159
if trans_id not in self._new_contents:
1184
1161
new_path = self._limbo_name(trans_id)
1185
osutils.rename(old_path, new_path)
1162
os.rename(old_path, new_path)
1186
1163
for descendant in self._limbo_descendants(trans_id):
1187
1164
desc_path = self._limbo_files[descendant]
1188
1165
desc_path = new_path + desc_path[len(old_path):]
1362
1339
FileMover does not delete files until it is sure that a rollback will not
1365
def __init__(self, tree, pb=None):
1342
def __init__(self, tree, pb=DummyProgress()):
1366
1343
"""Note: a tree_write lock is taken on the tree.
1368
1345
Use TreeTransform.finalize() to release the lock (can be omitted if
1714
1691
unversioned files in the input tree.
1717
def __init__(self, tree, pb=None, case_sensitive=True):
1694
def __init__(self, tree, pb=DummyProgress(), case_sensitive=True):
1718
1695
tree.lock_read()
1719
1696
limbodir = osutils.mkdtemp(prefix='bzr-limbo-')
1720
1697
DiskTreeTransform.__init__(self, tree, limbodir, pb, case_sensitive)
1820
1797
executable = self.is_executable(file_id, path)
1821
1798
return kind, executable, None
1823
def is_locked(self):
1826
1800
def lock_read(self):
1827
1801
# Perhaps in theory, this should lock the TreeTransform?
1830
1804
def unlock(self):
2617
2591
def revert(working_tree, target_tree, filenames, backups=False,
2618
pb=None, change_reporter=None):
2592
pb=DummyProgress(), change_reporter=None):
2619
2593
"""Revert a working tree's contents to those of a target tree."""
2620
2594
target_tree.lock_read()
2621
pb = ui.ui_factory.nested_progress_bar()
2622
2595
tt = TreeTransform(working_tree, pb)
2624
2597
pp = ProgressPhase("Revert phase", 3, pb)
2643
2616
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2644
2617
backups, pp, basis_tree=None,
2645
2618
merge_modified=None):
2646
2620
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2648
2622
if merge_modified is None:
2652
2626
merge_modified, basis_tree)
2654
2628
child_pb.finished()
2655
2630
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2657
2632
raw_conflicts = resolve_conflicts(tt, child_pb,
2779
2754
return merge_modified
2782
def resolve_conflicts(tt, pb=None, pass_func=None):
2757
def resolve_conflicts(tt, pb=DummyProgress(), pass_func=None):
2783
2758
"""Make many conflict-resolution attempts, but die if they fail"""
2784
2759
if pass_func is None:
2785
2760
pass_func = conflict_pass
2786
2761
new_conflicts = set()
2787
pb = ui.ui_factory.nested_progress_bar()
2789
2763
for n in range(10):
2790
2764
pb.update('Resolution pass', n+1, 10)
2794
2768
new_conflicts.update(pass_func(tt, conflicts))
2795
2769
raise MalformedTransform(conflicts=conflicts)
2800
2774
def conflict_pass(tt, conflicts, path_tree=None):
2923
2897
self.pending_deletions = []
2925
2899
def rename(self, from_, to):
2926
"""Rename a file from one path to another."""
2900
"""Rename a file from one path to another. Functions like os.rename"""
2928
osutils.rename(from_, to)
2902
os.rename(from_, to)
2929
2903
except OSError, e:
2930
2904
if e.errno in (errno.EEXIST, errno.ENOTEMPTY):
2931
2905
raise errors.FileExists(to, str(e))
2945
2919
def rollback(self):
2946
2920
"""Reverse all renames that have been performed"""
2947
2921
for from_, to in reversed(self.past_renames):
2948
osutils.rename(to, from_)
2922
os.rename(to, from_)
2949
2923
# after rollback, don't reuse _FileMover
2950
2924
past_renames = None
2951
2925
pending_deletions = None