60
64
:param tree: The tree containing the files.
61
65
:param file_ids: A list of file_ids to perform the updates for.
63
desired_files = [(tree.id2path(f), f) for f in file_ids]
64
with ui_factory.nested_progress_bar() as task:
67
desired_files = [(f, f) for f in file_ids]
68
task = ui_factory.nested_progress_bar()
65
70
for num, (file_id, contents) in enumerate(
66
tree.iter_files_bytes(desired_files)):
71
tree.iter_files_bytes(desired_files)):
67
72
task.update(gettext('Calculating hashes'), num, len(file_ids))
69
74
s.writelines(contents)
71
76
self.add_edge_hashes(s.readlines(), file_id)
73
80
def hitcounts(self, lines):
74
81
"""Count the number of hash hits for each tag, for the given lines.
97
104
:return: A list of tuples of count, path, file_id.
100
with ui_factory.nested_progress_bar() as task:
107
task = ui_factory.nested_progress_bar()
101
109
for num, path in enumerate(paths):
102
110
task.update(gettext('Determining hash hits'), num, len(paths))
103
111
hits = self.hitcounts(self.tree.get_file_lines(path))
104
all_hits.extend((v, path, k) for k, v in hits.items())
112
all_hits.extend((v, path, k) for k, v in viewitems(hits))
107
117
def file_match(self, paths):
168
178
missing_files = set()
169
179
missing_parents = {}
170
180
candidate_files = set()
171
with ui_factory.nested_progress_bar() as task:
172
iterator = self.tree.iter_changes(basis, want_unversioned=True,
174
for change in iterator:
175
if change.kind[1] is None and change.versioned[1]:
176
if not self.tree.has_filename(
177
self.tree.id2path(change.parent_id[0])):
178
missing_parents.setdefault(
179
change.parent_id[0], set()).add(change.file_id)
180
if change.kind[0] == 'file':
181
missing_files.add(change.file_id)
181
task = ui_factory.nested_progress_bar()
182
iterator = self.tree.iter_changes(basis, want_unversioned=True,
185
for (file_id, paths, changed_content, versioned, parent, name,
186
kind, executable) in iterator:
187
if kind[1] is None and versioned[1]:
188
if not self.tree.has_filename(self.tree.id2path(parent[0])):
189
missing_parents.setdefault(parent[0], set()).add(file_id)
190
if kind[0] == 'file':
191
missing_files.add(file_id)
183
# other kinds are not handled
193
#other kinds are not handled
185
if change.versioned == (False, False):
186
if self.tree.is_ignored(change.path[1]):
195
if versioned == (False, False):
196
if self.tree.is_ignored(paths[1]):
188
if change.kind[1] == 'file':
189
candidate_files.add(change.path[1])
190
if change.kind[1] == 'directory':
191
for _dir, children in self.tree.walkdirs(change.path[1]):
198
if kind[1] == 'file':
199
candidate_files.add(paths[1])
200
if kind[1] == 'directory':
201
for _dir, children in self.tree.walkdirs(paths[1]):
192
202
for child in children:
193
203
if child[2] == 'file':
194
204
candidate_files.add(child[0])
195
207
return missing_files, missing_parents, candidate_files
198
def guess_renames(klass, from_tree, to_tree, dry_run=False):
210
def guess_renames(klass, tree, dry_run=False):
199
211
"""Guess which files to rename, and perform the rename.
201
213
We assume that unversioned files and missing files indicate that
202
214
versioned files have been renamed outside of Bazaar.
204
:param from_tree: A tree to compare from
205
:param to_tree: A write-locked working tree.
216
:param tree: A write-locked working tree.
207
218
required_parents = {}
208
with ui_factory.nested_progress_bar() as task:
219
task = ui_factory.nested_progress_bar()
209
221
pp = progress.ProgressPhase('Guessing renames', 4, task)
210
with from_tree.lock_read():
222
basis = tree.basis_tree()
213
227
missing_files, missing_parents, candidate_files = (
214
rn._find_missing_files(from_tree))
228
rn._find_missing_files(basis))
216
rn.add_file_edge_hashes(from_tree, missing_files)
230
rn.add_file_edge_hashes(basis, missing_files)
218
234
matches = rn.file_match(candidate_files)
219
235
parents_matches = matches
227
243
delta = rn._make_inventory_delta(matches)
228
244
for old, new, file_id, entry in delta:
229
trace.note(gettext("{0} => {1}").format(old, new))
245
trace.note( gettext("{0} => {1}").format(old, new) )
231
to_tree.add(required_parents)
232
to_tree.apply_inventory_delta(delta)
247
tree.add(required_parents)
248
tree.apply_inventory_delta(delta)
234
252
def _make_inventory_delta(self, matches):
236
file_id_matches = dict((f, p) for p, f in matches.items())
238
for f in matches.values():
240
file_id_query.append(self.tree.id2path(f))
241
except errors.NoSuchId:
243
for old_path, entry in self.tree.iter_entries_by_dir(
244
specific_files=file_id_query):
254
file_id_matches = dict((f, p) for p, f in viewitems(matches))
255
for old_path, entry in self.tree.iter_entries_by_dir(file_id_matches):
245
256
new_path = file_id_matches[entry.file_id]
246
257
parent_path, new_name = osutils.split(new_path)
247
258
parent_id = matches.get(parent_path)
248
259
if parent_id is None:
249
260
parent_id = self.tree.path2id(parent_path)
250
261
if parent_id is None:
251
added, ignored = self.tree.smart_add(
252
[parent_path], recurse=False)
262
added, ignored = self.tree.smart_add([parent_path], recurse=False)
253
263
if len(ignored) > 0 and ignored[0] == parent_path: