/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 breezy/rename_map.py

  • Committer: Martin
  • Date: 2018-11-16 16:38:22 UTC
  • mto: This revision was merged to the branch mainline in revision 7172.
  • Revision ID: gzlist@googlemail.com-20181116163822-yg1h1cdng6w7w9kn
Make --profile-imports work on Python 3

Also tweak heading to line up correctly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
18
 
from cStringIO import StringIO
19
 
 
20
 
from bzrlib import (
 
17
from __future__ import absolute_import
 
18
 
 
19
 
 
20
from . import (
21
21
    osutils,
22
22
    progress,
23
23
    trace,
24
 
)
25
 
from bzrlib.ui import ui_factory
26
 
 
 
24
    )
 
25
from .i18n import gettext
 
26
from .sixish import (
 
27
    BytesIO,
 
28
    viewitems,
 
29
    viewvalues,
 
30
    )
 
31
from .ui import ui_factory
27
32
 
28
33
class RenameMap(object):
29
34
    """Determine a mapping of renames."""
60
65
        :param tree: The tree containing the files.
61
66
        :param file_ids: A list of file_ids to perform the updates for.
62
67
        """
63
 
        desired_files = [(f, f) for f in file_ids]
64
 
        task = ui_factory.nested_progress_bar()
65
 
        try:
 
68
        desired_files = [(tree.id2path(f), f) for f in file_ids]
 
69
        with ui_factory.nested_progress_bar() as task:
66
70
            for num, (file_id, contents) in enumerate(
67
71
                tree.iter_files_bytes(desired_files)):
68
 
                task.update('Calculating hashes', num, len(file_ids))
69
 
                s = StringIO()
 
72
                task.update(gettext('Calculating hashes'), num, len(file_ids))
 
73
                s = BytesIO()
70
74
                s.writelines(contents)
71
75
                s.seek(0)
72
76
                self.add_edge_hashes(s.readlines(), file_id)
73
 
        finally:
74
 
            task.finished()
75
77
 
76
78
    def hitcounts(self, lines):
77
79
        """Count the number of hash hits for each tag, for the given lines.
100
102
        :return: A list of tuples of count, path, file_id.
101
103
        """
102
104
        all_hits = []
103
 
        task = ui_factory.nested_progress_bar()
104
 
        try:
 
105
        with ui_factory.nested_progress_bar() as task:
105
106
            for num, path in enumerate(paths):
106
 
                task.update('Determining hash hits', num, len(paths))
107
 
                hits = self.hitcounts(self.tree.get_file_lines(None,
108
 
                                                               path=path))
109
 
                all_hits.extend((v, path, k) for k, v in hits.items())
110
 
        finally:
111
 
            task.finished()
 
107
                task.update(gettext('Determining hash hits'), num, len(paths))
 
108
                hits = self.hitcounts(self.tree.get_file_lines(path))
 
109
                all_hits.extend((v, path, k) for k, v in viewitems(hits))
112
110
        return all_hits
113
111
 
114
112
    def file_match(self, paths):
143
141
            while True:
144
142
                child = path
145
143
                path = osutils.dirname(path)
146
 
                if self.tree.path2id(path) is not None:
 
144
                if self.tree.is_versioned(path):
147
145
                    break
148
146
                required_parents.setdefault(path, []).append(child)
149
147
        require_ids = {}
150
 
        for parent, children in required_parents.iteritems():
 
148
        for parent, children in viewitems(required_parents):
151
149
            child_file_ids = set()
152
150
            for child in children:
153
151
                file_id = matches.get(child)
164
162
        parent directories.
165
163
        """
166
164
        all_hits = []
167
 
        for file_id, file_id_children in missing_parents.iteritems():
168
 
            for path, path_children in required_parents.iteritems():
 
165
        for file_id, file_id_children in viewitems(missing_parents):
 
166
            for path, path_children in viewitems(required_parents):
169
167
                hits = len(path_children.intersection(file_id_children))
170
168
                if hits > 0:
171
169
                    all_hits.append((hits, path, file_id))
175
173
        missing_files = set()
176
174
        missing_parents = {}
177
175
        candidate_files = set()
178
 
        task = ui_factory.nested_progress_bar()
179
 
        iterator = self.tree.iter_changes(basis, want_unversioned=True,
180
 
                                          pb=task)
181
 
        try:
 
176
        with ui_factory.nested_progress_bar() as task:
 
177
            iterator = self.tree.iter_changes(basis, want_unversioned=True,
 
178
                                              pb=task)
182
179
            for (file_id, paths, changed_content, versioned, parent, name,
183
180
                 kind, executable) in iterator:
184
181
                if kind[1] is None and versioned[1]:
185
 
                    missing_parents.setdefault(parent[0], set()).add(file_id)
 
182
                    if not self.tree.has_filename(self.tree.id2path(parent[0])):
 
183
                        missing_parents.setdefault(parent[0], set()).add(file_id)
186
184
                    if kind[0] == 'file':
187
185
                        missing_files.add(file_id)
188
186
                    else:
198
196
                            for child in children:
199
197
                                if child[2] == 'file':
200
198
                                    candidate_files.add(child[0])
201
 
        finally:
202
 
            task.finished()
203
199
        return missing_files, missing_parents, candidate_files
204
200
 
205
201
    @classmethod
206
 
    def guess_renames(klass, tree, dry_run=False):
 
202
    def guess_renames(klass, from_tree, to_tree, dry_run=False):
207
203
        """Guess which files to rename, and perform the rename.
208
204
 
209
205
        We assume that unversioned files and missing files indicate that
210
206
        versioned files have been renamed outside of Bazaar.
211
207
 
212
 
        :param tree: A write-locked working tree.
 
208
        :param from_tree: A tree to compare from
 
209
        :param to_tree: A write-locked working tree.
213
210
        """
214
211
        required_parents = {}
215
 
        task = ui_factory.nested_progress_bar()
216
 
        try:
 
212
        with ui_factory.nested_progress_bar() as task:
217
213
            pp = progress.ProgressPhase('Guessing renames', 4, task)
218
 
            basis = tree.basis_tree()
219
 
            basis.lock_read()
220
 
            try:
221
 
                rn = klass(tree)
 
214
            with from_tree.lock_read():
 
215
                rn = klass(to_tree)
222
216
                pp.next_phase()
223
217
                missing_files, missing_parents, candidate_files = (
224
 
                    rn._find_missing_files(basis))
 
218
                    rn._find_missing_files(from_tree))
225
219
                pp.next_phase()
226
 
                rn.add_file_edge_hashes(basis, missing_files)
227
 
            finally:
228
 
                basis.unlock()
 
220
                rn.add_file_edge_hashes(from_tree, missing_files)
229
221
            pp.next_phase()
230
222
            matches = rn.file_match(candidate_files)
231
223
            parents_matches = matches
238
230
            pp.next_phase()
239
231
            delta = rn._make_inventory_delta(matches)
240
232
            for old, new, file_id, entry in delta:
241
 
                trace.note("%s => %s", old, new)
 
233
                trace.note( gettext("{0} => {1}").format(old, new) )
242
234
            if not dry_run:
243
 
                tree.add(required_parents)
244
 
                tree.apply_inventory_delta(delta)
245
 
        finally:
246
 
            task.finished()
 
235
                to_tree.add(required_parents)
 
236
                to_tree.apply_inventory_delta(delta)
247
237
 
248
238
    def _make_inventory_delta(self, matches):
249
239
        delta = []
250
 
        file_id_matches = dict((f, p) for p, f in matches.items())
251
 
        for old_path, entry in self.tree.iter_entries_by_dir(matches.values()):
 
240
        file_id_matches = dict((f, p) for p, f in viewitems(matches))
 
241
        file_id_query = []
 
242
        for f in viewvalues(matches):
 
243
            try:
 
244
                file_id_query.append(self.tree.id2path(f))
 
245
            except errors.NoSuchId:
 
246
                pass
 
247
        for old_path, entry in self.tree.iter_entries_by_dir(
 
248
                specific_files=file_id_query):
252
249
            new_path = file_id_matches[entry.file_id]
253
250
            parent_path, new_name = osutils.split(new_path)
254
251
            parent_id = matches.get(parent_path)
255
252
            if parent_id is None:
256
253
                parent_id = self.tree.path2id(parent_path)
 
254
                if parent_id is None:
 
255
                    added, ignored = self.tree.smart_add([parent_path], recurse=False)
 
256
                    if len(ignored) > 0 and ignored[0] == parent_path:
 
257
                        continue
 
258
                    else:
 
259
                        parent_id = self.tree.path2id(parent_path)
257
260
            if entry.name == new_name and entry.parent_id == parent_id:
258
261
                continue
259
262
            new_entry = entry.copy()