299
307
self.get_transaction())
301
def fileid_involved_between_revs(self, from_revid, to_revid):
302
"""Find file_id(s) which are involved in the changes between revisions.
304
This determines the set of revisions which are involved, and then
305
finds all file ids affected by those revisions.
307
w = self.get_inventory_weave()
308
from_set = set(w.get_ancestry(from_revid))
309
to_set = set(w.get_ancestry(to_revid))
310
changed = to_set.difference(from_set)
311
return self._fileid_involved_by_set(changed)
313
def fileid_involved(self, last_revid=None):
314
"""Find all file_ids modified in the ancestry of last_revid.
316
:param last_revid: If None, last_revision() will be used.
318
w = self.get_inventory_weave()
320
changed = set(w.versions())
322
changed = set(w.get_ancestry(last_revid))
323
return self._fileid_involved_by_set(changed)
325
def fileid_involved_by_set(self, changes):
326
"""Find all file_ids modified by the set of revisions passed in.
328
:param changes: A set() of revision ids
330
# TODO: jam 20060119 This line does *nothing*, remove it.
331
# or better yet, change _fileid_involved_by_set so
332
# that it takes the inventory weave, rather than
333
# pulling it out by itself.
334
return self._fileid_involved_by_set(changes)
336
def _fileid_involved_by_set(self, changes):
337
"""Find the set of file-ids affected by the set of revisions.
339
:param changes: A set() of revision ids.
340
:return: A set() of file ids.
342
This peaks at the Weave, interpreting each line, looking to
343
see if it mentions one of the revisions. And if so, includes
344
the file id mentioned.
345
This expects both the Weave format, and the serialization
346
to have a single line per file/directory, and to have
347
fileid="" and revision="" on that line.
309
def fileids_altered_by_revision_ids(self, revision_ids):
310
"""Find the file ids and versions affected by revisions.
312
:param revisions: an iterable containing revision ids.
313
:return: a dictionary mapping altered file-ids to an iterable of
314
revision_ids. Each altered file-ids has the exact revision_ids that
315
altered it listed explicitly.
349
317
assert isinstance(self._format, (RepositoryFormat5,
350
318
RepositoryFormat6,
351
319
RepositoryFormat7,
352
320
RepositoryFormatKnit1)), \
353
321
"fileid_involved only supported for branches which store inventory as unnested xml"
322
selected_revision_ids = set(revision_ids)
355
323
w = self.get_inventory_weave()
358
# this code needs to read every line in every inventory for the
359
# inventories [changes]. Seeing a line twice is ok. Seeing a line
360
# not pesent in one of those inventories is unnecessary and not
326
# this code needs to read every new line in every inventory for the
327
# inventories [revision_ids]. Seeing a line twice is ok. Seeing a line
328
# not pesent in one of those inventories is unnecessary but not
361
329
# harmful because we are filtering by the revision id marker in the
362
# inventory lines to only select file ids altered in one of those
330
# inventory lines : we only select file ids altered in one of those
363
331
# revisions. We dont need to see all lines in the inventory because
364
332
# only those added in an inventory in rev X can contain a revision=X
366
for line in w.iter_lines_added_or_present_in_versions(changes):
334
for line in w.iter_lines_added_or_present_in_versions(selected_revision_ids):
367
335
start = line.find('file_id="')+9
368
336
if start < 9: continue
369
337
end = line.find('"', start)
371
339
file_id = _unescape_xml(line[start:end])
373
# check if file_id is already present
374
if file_id in file_ids: continue
376
341
start = line.find('revision="')+10
377
342
if start < 10: continue
378
343
end = line.find('"', start)
380
345
revision_id = _unescape_xml(line[start:end])
381
if revision_id in changes:
382
file_ids.add(file_id)
346
if revision_id in selected_revision_ids:
347
result.setdefault(file_id, set()).add(revision_id)
386
351
def get_inventory_weave(self):