/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-17 17:11:16 UTC
  • mfrom: (4797.2.17 2.1)
  • mto: (4797.2.18 2.1)
  • mto: This revision was merged to the branch mainline in revision 5055.
  • Revision ID: john@arbash-meinel.com-20100217171116-h7t9223ystbnx5h8
merge bzr.2.1 in preparation for NEWS entry.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    annotate,
26
26
    bencode,
27
27
    bzrdir,
28
 
    commit,
29
28
    delta,
30
29
    errors,
31
30
    inventory,
32
31
    multiparent,
33
32
    osutils,
34
33
    revision as _mod_revision,
35
 
    ui,
36
34
    )
37
35
""")
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
51
49
    splitpath,
52
50
    supports_executable,
53
51
)
54
 
from bzrlib.progress import ProgressPhase
 
52
from bzrlib.progress import DummyProgress, ProgressPhase
55
53
from bzrlib.symbol_versioning import (
56
54
        deprecated_function,
57
55
        deprecated_in,
81
79
class TreeTransformBase(object):
82
80
    """The base class for TreeTransform and its kin."""
83
81
 
84
 
    def __init__(self, tree, pb=None,
 
82
    def __init__(self, tree, pb=DummyProgress(),
85
83
                 case_sensitive=True):
86
84
        """Constructor.
87
85
 
88
86
        :param tree: The tree that will be transformed, but not necessarily
89
87
            the output tree.
90
 
        :param pb: ignored
 
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.
93
91
        """
928
926
        """
929
927
        return _PreviewTree(self)
930
928
 
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.
935
931
 
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
939
 
            pending merges.
940
 
        :param strict: If True, abort the commit if there are unversioned
941
 
            files.
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
945
 
            seconds.
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.
953
936
        """
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,
976
 
                                            timestamp=timestamp,
977
 
                                            timezone=timezone,
978
 
                                            committer=committer,
979
 
                                            revprops=revprops,
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."""
1087
1064
 
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
1095
 
        :param pb: ignored
 
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.
1098
1075
        """
1362
1339
    FileMover does not delete files until it is sure that a rollback will not
1363
1340
    happen.
1364
1341
    """
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.
1367
1344
 
1368
1345
        Use TreeTransform.finalize() to release the lock (can be omitted if
1657
1634
                      or trans_id in self._new_parent):
1658
1635
                    try:
1659
1636
                        mover.rename(full_path, self._limbo_name(trans_id))
1660
 
                    except errors.TransformRenameFailed, e:
 
1637
                    except OSError, e:
1661
1638
                        if e.errno != errno.ENOENT:
1662
1639
                            raise
1663
1640
                    else:
1688
1665
                if trans_id in self._needs_rename:
1689
1666
                    try:
1690
1667
                        mover.rename(self._limbo_name(trans_id), full_path)
1691
 
                    except errors.TransformRenameFailed, e:
 
1668
                    except OSError, e:
1692
1669
                        # We may be renaming a dangling inventory id
1693
1670
                        if e.errno != errno.ENOENT:
1694
1671
                            raise
1714
1691
    unversioned files in the input tree.
1715
1692
    """
1716
1693
 
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)
1792
1769
        parent_keys = [(file_id, self._file_revision(t, file_id)) for t in
1793
1770
                       self._iter_parent_trees()]
1794
1771
        vf.add_lines((file_id, tree_revision), parent_keys,
1795
 
                     self.get_file_lines(file_id))
 
1772
                     self.get_file(file_id).readlines())
1796
1773
        repo = self._get_repository()
1797
1774
        base_vf = repo.texts
1798
1775
        if base_vf not in vf.fallback_versionedfiles:
1820
1797
            executable = self.is_executable(file_id, path)
1821
1798
        return kind, executable, None
1822
1799
 
1823
 
    def is_locked(self):
1824
 
        return False
1825
 
 
1826
1800
    def lock_read(self):
1827
1801
        # Perhaps in theory, this should lock the TreeTransform?
1828
 
        return self
 
1802
        pass
1829
1803
 
1830
1804
    def unlock(self):
1831
1805
        pass
2291
2265
    for num, _unused in enumerate(wt.all_file_ids()):
2292
2266
        if num > 0:  # more than just a root
2293
2267
            raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
 
2268
    existing_files = set()
 
2269
    for dir, files in wt.walkdirs():
 
2270
        existing_files.update(f[0] for f in files)
2294
2271
    file_trans_id = {}
2295
2272
    top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2296
2273
    pp = ProgressPhase("Build phase", 2, top_pb)
2320
2297
                precomputed_delta = []
2321
2298
            else:
2322
2299
                precomputed_delta = None
2323
 
            # Check if tree inventory has content. If so, we populate
2324
 
            # existing_files with the directory content. If there are no
2325
 
            # entries we skip populating existing_files as its not used.
2326
 
            # This improves performance and unncessary work on large
2327
 
            # directory trees. (#501307)
2328
 
            if total > 0:
2329
 
                existing_files = set()
2330
 
                for dir, files in wt.walkdirs():
2331
 
                    existing_files.update(f[0] for f in files)
2332
2300
            for num, (tree_path, entry) in \
2333
2301
                enumerate(tree.inventory.iter_entries_by_dir()):
2334
2302
                pb.update("Building tree", num - len(deferred_contents), total)
2466
2434
    if entry.kind == "directory":
2467
2435
        return True
2468
2436
    if entry.kind == "file":
2469
 
        f = file(target_path, 'rb')
2470
 
        try:
2471
 
            if tree.get_file_text(file_id) == f.read():
2472
 
                return True
2473
 
        finally:
2474
 
            f.close()
 
2437
        if tree.get_file(file_id).read() == file(target_path, 'rb').read():
 
2438
            return True
2475
2439
    elif entry.kind == "symlink":
2476
2440
        if tree.get_symlink_target(file_id) == os.readlink(target_path):
2477
2441
            return True
2625
2589
 
2626
2590
 
2627
2591
def revert(working_tree, target_tree, filenames, backups=False,
2628
 
           pb=None, change_reporter=None):
 
2592
           pb=DummyProgress(), change_reporter=None):
2629
2593
    """Revert a working tree's contents to those of a target tree."""
2630
2594
    target_tree.lock_read()
2631
 
    pb = ui.ui_factory.nested_progress_bar()
2632
2595
    tt = TreeTransform(working_tree, pb)
2633
2596
    try:
2634
2597
        pp = ProgressPhase("Revert phase", 3, pb)
2653
2616
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2654
2617
                              backups, pp, basis_tree=None,
2655
2618
                              merge_modified=None):
 
2619
    pp.next_phase()
2656
2620
    child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2657
2621
    try:
2658
2622
        if merge_modified is None:
2662
2626
                                      merge_modified, basis_tree)
2663
2627
    finally:
2664
2628
        child_pb.finished()
 
2629
    pp.next_phase()
2665
2630
    child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2666
2631
    try:
2667
2632
        raw_conflicts = resolve_conflicts(tt, child_pb,
2789
2754
    return merge_modified
2790
2755
 
2791
2756
 
2792
 
def resolve_conflicts(tt, pb=None, pass_func=None):
 
2757
def resolve_conflicts(tt, pb=DummyProgress(), pass_func=None):
2793
2758
    """Make many conflict-resolution attempts, but die if they fail"""
2794
2759
    if pass_func is None:
2795
2760
        pass_func = conflict_pass
2796
2761
    new_conflicts = set()
2797
 
    pb = ui.ui_factory.nested_progress_bar()
2798
2762
    try:
2799
2763
        for n in range(10):
2800
2764
            pb.update('Resolution pass', n+1, 10)
2804
2768
            new_conflicts.update(pass_func(tt, conflicts))
2805
2769
        raise MalformedTransform(conflicts=conflicts)
2806
2770
    finally:
2807
 
        pb.finished()
 
2771
        pb.clear()
2808
2772
 
2809
2773
 
2810
2774
def conflict_pass(tt, conflicts, path_tree=None):
2859
2823
                        # special-case the other tree root (move its
2860
2824
                        # children to current root)
2861
2825
                        if entry.parent_id is None:
2862
 
                            create = False
 
2826
                            create=False
2863
2827
                            moved = _reparent_transform_children(
2864
2828
                                tt, trans_id, tt.root)
2865
2829
                            for child in moved:
2933
2897
        self.pending_deletions = []
2934
2898
 
2935
2899
    def rename(self, from_, to):
2936
 
        """Rename a file from one path to another."""
 
2900
        """Rename a file from one path to another.  Functions like os.rename"""
2937
2901
        try:
2938
2902
            os.rename(from_, to)
2939
2903
        except OSError, e:
2940
2904
            if e.errno in (errno.EEXIST, errno.ENOTEMPTY):
2941
2905
                raise errors.FileExists(to, str(e))
2942
 
            # normal OSError doesn't include filenames so it's hard to see where
2943
 
            # the problem is, see https://bugs.launchpad.net/bzr/+bug/491763
2944
 
            raise errors.TransformRenameFailed(from_, to, str(e), e.errno)
 
2906
            raise
2945
2907
        self.past_renames.append((from_, to))
2946
2908
 
2947
2909
    def pre_delete(self, from_, to):
2957
2919
    def rollback(self):
2958
2920
        """Reverse all renames that have been performed"""
2959
2921
        for from_, to in reversed(self.past_renames):
2960
 
            try:
2961
 
                os.rename(to, from_)
2962
 
            except OSError, e:
2963
 
                raise errors.TransformRenameFailed(to, from_, str(e), e.errno)                
 
2922
            os.rename(to, from_)
2964
2923
        # after rollback, don't reuse _FileMover
2965
2924
        past_renames = None
2966
2925
        pending_deletions = None