64
65
:param tree: The tree containing the files.
65
66
:param file_ids: A list of file_ids to perform the updates for.
67
desired_files = [(f, f) for f in file_ids]
68
task = ui_factory.nested_progress_bar()
68
desired_files = [(tree.id2path(f), f) for f in file_ids]
69
with ui_factory.nested_progress_bar() as task:
70
70
for num, (file_id, contents) in enumerate(
71
71
tree.iter_files_bytes(desired_files)):
72
72
task.update(gettext('Calculating hashes'), num, len(file_ids))
74
74
s.writelines(contents)
76
76
self.add_edge_hashes(s.readlines(), file_id)
80
78
def hitcounts(self, lines):
81
79
"""Count the number of hash hits for each tag, for the given lines.
104
102
:return: A list of tuples of count, path, file_id.
107
task = ui_factory.nested_progress_bar()
105
with ui_factory.nested_progress_bar() as task:
109
106
for num, path in enumerate(paths):
110
107
task.update(gettext('Determining hash hits'), num, len(paths))
111
hits = self.hitcounts(self.tree.get_file_lines(None,
108
hits = self.hitcounts(self.tree.get_file_lines(path))
113
109
all_hits.extend((v, path, k) for k, v in viewitems(hits))
118
112
def file_match(self, paths):
149
143
path = osutils.dirname(path)
150
if self.tree.path2id(path) is not None:
144
if self.tree.is_versioned(path):
152
146
required_parents.setdefault(path, []).append(child)
179
173
missing_files = set()
180
174
missing_parents = {}
181
175
candidate_files = set()
182
task = ui_factory.nested_progress_bar()
183
iterator = self.tree.iter_changes(basis, want_unversioned=True,
176
with ui_factory.nested_progress_bar() as task:
177
iterator = self.tree.iter_changes(basis, want_unversioned=True,
186
179
for (file_id, paths, changed_content, versioned, parent, name,
187
180
kind, executable) in iterator:
188
181
if kind[1] is None and versioned[1]:
189
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)
190
184
if kind[0] == 'file':
191
185
missing_files.add(file_id)
202
196
for child in children:
203
197
if child[2] == 'file':
204
198
candidate_files.add(child[0])
207
199
return missing_files, missing_parents, candidate_files
210
def guess_renames(klass, tree, dry_run=False):
202
def guess_renames(klass, from_tree, to_tree, dry_run=False):
211
203
"""Guess which files to rename, and perform the rename.
213
205
We assume that unversioned files and missing files indicate that
214
206
versioned files have been renamed outside of Bazaar.
216
: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.
218
211
required_parents = {}
219
task = ui_factory.nested_progress_bar()
212
with ui_factory.nested_progress_bar() as task:
221
213
pp = progress.ProgressPhase('Guessing renames', 4, task)
222
basis = tree.basis_tree()
214
with from_tree.lock_read():
227
217
missing_files, missing_parents, candidate_files = (
228
rn._find_missing_files(basis))
218
rn._find_missing_files(from_tree))
230
rn.add_file_edge_hashes(basis, missing_files)
220
rn.add_file_edge_hashes(from_tree, missing_files)
234
222
matches = rn.file_match(candidate_files)
235
223
parents_matches = matches
244
232
for old, new, file_id, entry in delta:
245
233
trace.note( gettext("{0} => {1}").format(old, new) )
247
tree.add(required_parents)
248
tree.apply_inventory_delta(delta)
235
to_tree.add(required_parents)
236
to_tree.apply_inventory_delta(delta)
252
238
def _make_inventory_delta(self, matches):
254
240
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):
242
for f in viewvalues(matches):
244
file_id_query.append(self.tree.id2path(f))
245
except errors.NoSuchId:
247
for old_path, entry in self.tree.iter_entries_by_dir(
248
specific_files=file_id_query):
256
249
new_path = file_id_matches[entry.file_id]
257
250
parent_path, new_name = osutils.split(new_path)
258
251
parent_id = matches.get(parent_path)
259
252
if parent_id is None:
260
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:
259
parent_id = self.tree.path2id(parent_path)
261
260
if entry.name == new_name and entry.parent_id == parent_id:
263
262
new_entry = entry.copy()