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

  • Committer: Marius Kruger
  • Date: 2010-07-10 21:28:56 UTC
  • mto: (5384.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5385.
  • Revision ID: marius.kruger@enerweb.co.za-20100710212856-uq4ji3go0u5se7hx
* Update documentation
* add NEWS

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