/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/merge.py

  • Committer: Martin Pool
  • Date: 2010-04-23 00:44:15 UTC
  • mto: This revision was merged to the branch mainline in revision 5189.
  • Revision ID: mbp@canonical.com-20100423004415-py8ozrtkjo6tphj2
Update more code to use user_transport when it should

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
import warnings
18
18
 
19
 
from bzrlib.lazy_import import lazy_import
20
 
lazy_import(globals(), """
21
19
from bzrlib import (
22
20
    branch as _mod_branch,
23
21
    conflicts as _mod_conflicts,
24
22
    debug,
 
23
    decorators,
25
24
    errors,
26
25
    graph as _mod_graph,
 
26
    hooks,
27
27
    merge3,
28
28
    osutils,
29
29
    patiencediff,
34
34
    tree as _mod_tree,
35
35
    tsort,
36
36
    ui,
37
 
    versionedfile,
 
37
    versionedfile
38
38
    )
39
39
from bzrlib.cleanup import OperationWithCleanups
40
 
""")
41
 
from bzrlib import (
42
 
    decorators,
43
 
    hooks,
44
 
    )
45
40
from bzrlib.symbol_versioning import (
46
41
    deprecated_in,
47
42
    deprecated_method,
98
93
        return ('not applicable', None)
99
94
 
100
95
 
101
 
class PerFileMerger(AbstractPerFileMerger):
102
 
    """Merge individual files when self.file_matches returns True.
103
 
 
104
 
    This class is intended to be subclassed.  The file_matches and
105
 
    merge_matching methods should be overridden with concrete implementations.
106
 
    """
107
 
 
108
 
    def file_matches(self, params):
109
 
        """Return True if merge_matching should be called on this file.
110
 
 
111
 
        Only called with merges of plain files with no clear winner.
112
 
 
113
 
        Subclasses must override this.
114
 
        """
115
 
        raise NotImplementedError(self.file_matches)
116
 
 
117
 
    def get_filename(self, params, tree):
118
 
        """Lookup the filename (i.e. basename, not path), given a Tree (e.g.
119
 
        self.merger.this_tree) and a MergeHookParams.
120
 
        """
121
 
        return osutils.basename(tree.id2path(params.file_id))
122
 
 
123
 
    def get_filepath(self, params, tree):
124
 
        """Calculate the path to the file in a tree.
125
 
 
126
 
        :param params: A MergeHookParams describing the file to merge
127
 
        :param tree: a Tree, e.g. self.merger.this_tree.
128
 
        """
129
 
        return tree.id2path(params.file_id)
130
 
 
131
 
    def merge_contents(self, params):
132
 
        """Merge the contents of a single file."""
133
 
        # Check whether this custom merge logic should be used.
134
 
        if (
135
 
            # OTHER is a straight winner, rely on default merge.
136
 
            params.winner == 'other' or
137
 
            # THIS and OTHER aren't both files.
138
 
            not params.is_file_merge() or
139
 
            # The filename doesn't match *.xml
140
 
            not self.file_matches(params)):
141
 
            return 'not_applicable', None
142
 
        return self.merge_matching(params)
143
 
 
144
 
    def merge_matching(self, params):
145
 
        """Merge the contents of a single file that has matched the criteria
146
 
        in PerFileMerger.merge_contents (is a conflict, is a file,
147
 
        self.file_matches is True).
148
 
 
149
 
        Subclasses must override this.
150
 
        """
151
 
        raise NotImplementedError(self.merge_matching)
152
 
 
153
 
 
154
 
class ConfigurableFileMerger(PerFileMerger):
 
96
class ConfigurableFileMerger(AbstractPerFileMerger):
155
97
    """Merge individual files when configured via a .conf file.
156
98
 
157
99
    This is a base class for concrete custom file merging logic. Concrete
180
122
        if self.name_prefix is None:
181
123
            raise ValueError("name_prefix must be set.")
182
124
 
183
 
    def file_matches(self, params):
 
125
    def filename_matches_config(self, params):
184
126
        """Check whether the file should call the merge hook.
185
127
 
186
128
        <name_prefix>_merge_files configuration variable is a list of files
200
142
                affected_files = self.default_files
201
143
            self.affected_files = affected_files
202
144
        if affected_files:
203
 
            filepath = self.get_filepath(params, self.merger.this_tree)
204
 
            if filepath in affected_files:
 
145
            filename = self.merger.this_tree.id2path(params.file_id)
 
146
            if filename in affected_files:
205
147
                return True
206
148
        return False
207
149
 
208
 
    def merge_matching(self, params):
 
150
    def merge_contents(self, params):
 
151
        """Merge the contents of a single file."""
 
152
        # First, check whether this custom merge logic should be used.  We
 
153
        # expect most files should not be merged by this handler.
 
154
        if (
 
155
            # OTHER is a straight winner, rely on default merge.
 
156
            params.winner == 'other' or
 
157
            # THIS and OTHER aren't both files.
 
158
            not params.is_file_merge() or
 
159
            # The filename isn't listed in the 'NAME_merge_files' config
 
160
            # option.
 
161
            not self.filename_matches_config(params)):
 
162
            return 'not_applicable', None
209
163
        return self.merge_text(params)
210
164
 
211
165
    def merge_text(self, params):
750
704
        :param this_tree: The local tree in the merge operation
751
705
        :param base_tree: The common tree in the merge operation
752
706
        :param other_tree: The other tree to merge changes from
753
 
        :param this_branch: The branch associated with this_tree.  Defaults to
754
 
            this_tree.branch if not supplied.
 
707
        :param this_branch: The branch associated with this_tree
755
708
        :param interesting_ids: The file_ids of files that should be
756
709
            participate in the merge.  May not be combined with
757
710
            interesting_files.
775
728
        if interesting_files is not None and interesting_ids is not None:
776
729
            raise ValueError(
777
730
                'specify either interesting_ids or interesting_files')
778
 
        if this_branch is None:
779
 
            this_branch = this_tree.branch
780
731
        self.interesting_ids = interesting_ids
781
732
        self.interesting_files = interesting_files
782
733
        self.this_tree = working_tree
1091
1042
        other_root = self.tt.trans_id_file_id(other_root_file_id)
1092
1043
        if other_root == self.tt.root:
1093
1044
            return
1094
 
        if self.other_tree.inventory.root.file_id in self.this_tree.inventory:
1095
 
            # the other tree's root is a non-root in the current tree (as when
1096
 
            # a previously unrelated branch is merged into another)
1097
 
            return
1098
1045
        try:
1099
1046
            self.tt.final_kind(other_root)
1100
 
            other_root_is_present = True
1101
1047
        except errors.NoSuchFile:
1102
 
            # other_root doesn't have a physical representation. We still need
1103
 
            # to move any references to the actual root of the tree.
1104
 
            other_root_is_present = False
1105
 
        # 'other_tree.inventory.root' is not present in this tree. We are
1106
 
        # calling adjust_path for children which *want* to be present with a
1107
 
        # correct place to go.
1108
 
        for thing, child in self.other_tree.inventory.root.children.iteritems():
 
1048
            return
 
1049
        if self.this_tree.has_id(self.other_tree.inventory.root.file_id):
 
1050
            # the other tree's root is a non-root in the current tree
 
1051
            return
 
1052
        self.reparent_children(self.other_tree.inventory.root, self.tt.root)
 
1053
        self.tt.cancel_creation(other_root)
 
1054
        self.tt.cancel_versioning(other_root)
 
1055
 
 
1056
    def reparent_children(self, ie, target):
 
1057
        for thing, child in ie.children.iteritems():
1109
1058
            trans_id = self.tt.trans_id_file_id(child.file_id)
1110
 
            if not other_root_is_present:
1111
 
                # FIXME: Make final_kind returns None instead of raising
1112
 
                # NoSuchFile to avoid the ugly construct below -- vila 20100402
1113
 
                try:
1114
 
                    self.tt.final_kind(trans_id)
1115
 
                    # The item exist in the final tree and has a defined place
1116
 
                    # to go already.
1117
 
                    continue
1118
 
                except errors.NoSuchFile, e:
1119
 
                    pass
1120
 
            # Move the item into the root
1121
 
            self.tt.adjust_path(self.tt.final_name(trans_id),
1122
 
                                self.tt.root, trans_id)
1123
 
        if other_root_is_present:
1124
 
            self.tt.cancel_creation(other_root)
1125
 
            self.tt.cancel_versioning(other_root)
 
1059
            self.tt.adjust_path(self.tt.final_name(trans_id), target, trans_id)
1126
1060
 
1127
1061
    def write_modified(self, results):
1128
1062
        modified_hashes = {}
1460
1394
    def get_lines(self, tree, file_id):
1461
1395
        """Return the lines in a file, or an empty list."""
1462
1396
        if tree.has_id(file_id):
1463
 
            return tree.get_file_lines(file_id)
 
1397
            return tree.get_file(file_id).readlines()
1464
1398
        else:
1465
1399
            return []
1466
1400