1336
1336
rev_tmp.seek(0)
1337
1337
return rev_tmp.getvalue()
1339
def get_deltas_for_revisions(self, revisions):
1339
def get_deltas_for_revisions(self, revisions, specific_fileids=None):
1340
1340
"""Produce a generator of revision deltas.
1342
1342
Note that the input is a sequence of REVISIONS, not revision_ids.
1343
1343
Trees will be held in memory until the generator exits.
1344
1344
Each delta is relative to the revision's lefthand predecessor.
1346
:param specific_fileids: if not None, the result is filtered
1347
so that only those file-ids, their parents and their
1348
children are included.
1350
# Get the revision-ids of interest
1346
1351
required_trees = set()
1347
1352
for revision in revisions:
1348
1353
required_trees.add(revision.revision_id)
1349
1354
required_trees.update(revision.parent_ids[:1])
1350
trees = dict((t.get_revision_id(), t) for
1351
t in self.revision_trees(required_trees))
1356
# Get the matching filtered trees. Note that it's more
1357
# efficient to pass filtered trees to changes_from() rather
1358
# than doing the filtering afterwards. changes_from() could
1359
# arguably do the filtering itself but it's path-based, not
1360
# file-id based, so filtering before or afterwards is
1362
if specific_fileids is None:
1363
trees = dict((t.get_revision_id(), t) for
1364
t in self.revision_trees(required_trees))
1366
trees = dict((t.get_revision_id(), t) for
1367
t in self._filtered_revision_trees(required_trees,
1370
# Calculate the deltas
1352
1371
for revision in revisions:
1353
1372
if not revision.parent_ids:
1354
1373
old_tree = self.revision_tree(_mod_revision.NULL_REVISION)
1357
1376
yield trees[revision.revision_id].changes_from(old_tree)
1359
1378
@needs_read_lock
1360
def get_revision_delta(self, revision_id):
1379
def get_revision_delta(self, revision_id, specific_fileids=None):
1361
1380
"""Return the delta for one revision.
1363
1382
The delta is relative to the left-hand predecessor of the
1385
:param specific_fileids: if not None, the result is filtered
1386
so that only those file-ids, their parents and their
1387
children are included.
1366
1389
r = self.get_revision(revision_id)
1367
return list(self.get_deltas_for_revisions([r]))[0]
1390
return list(self.get_deltas_for_revisions([r],
1391
specific_fileids=specific_fileids))[0]
1369
1393
@needs_write_lock
1370
1394
def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1882
1906
return RevisionTree(self, inv, revision_id)
1884
1908
def revision_trees(self, revision_ids):
1885
"""Return Tree for a revision on this branch.
1909
"""Return Trees for revisions in this repository.
1887
`revision_id` may not be None or 'null:'"""
1911
:param revision_ids: a sequence of revision-ids;
1912
a revision-id may not be None or 'null:'
1888
1914
inventories = self.iter_inventories(revision_ids)
1889
1915
for inv in inventories:
1890
1916
yield RevisionTree(self, inv, inv.revision_id)
1918
def _filtered_revision_trees(self, revision_ids, file_ids):
1919
"""Return Tree for a revision on this branch with only some files.
1921
:param revision_ids: a sequence of revision-ids;
1922
a revision-id may not be None or 'null:'
1923
:param file_ids: if not None, the result is filtered
1924
so that only those file-ids, their parents and their
1925
children are included.
1927
inventories = self.iter_inventories(revision_ids)
1928
for inv in inventories:
1929
# Should we introduce a FilteredRevisionTree class rather
1930
# than pre-filter the inventory here?
1931
filtered_inv = inv.filter(file_ids)
1932
yield RevisionTree(self, filtered_inv, filtered_inv.revision_id)
1892
1934
@needs_read_lock
1893
1935
def get_ancestry(self, revision_id, topo_sorted=True):
1894
1936
"""Return a list of revision-ids integrated by a revision.