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