1461
1461
a SearchResult from a smart server, in which case the keys list is
1462
1462
not necessarily immediately available.
1464
self._recipe = (start_keys, exclude_keys, key_count)
1464
self._recipe = ('search', start_keys, exclude_keys, key_count)
1465
1465
self._keys = frozenset(keys)
1467
1467
def get_recipe(self):
1474
1474
added to the exclude list (or else ghost filling may alter the
1477
:return: A tuple (start_keys_set, exclude_keys_set, revision_count). To
1478
recreate the results of this search, create a breadth first
1479
searcher on the same graph starting at start_keys. Then call next()
1480
(or next_with_ghosts()) repeatedly, and on every result, call
1481
stop_searching_any on any keys from the exclude_keys set. The
1482
revision_count value acts as a trivial cross-check - the found
1483
revisions of the new search should have as many elements as
1477
:return: A tuple ('search', start_keys_set, exclude_keys_set,
1478
revision_count). To recreate the results of this search, create a
1479
breadth first searcher on the same graph starting at start_keys.
1480
Then call next() (or next_with_ghosts()) repeatedly, and on every
1481
result, call stop_searching_any on any keys from the exclude_keys
1482
set. The revision_count value acts as a trivial cross-check - the
1483
found revisions of the new search should have as many elements as
1484
1484
revision_count. If it does not, then additional revisions have been
1485
1485
ghosted since the search was executed the first time and the second
1495
1495
return self._keys
1498
"""Return true if the search lists 1 or more revisions."""
1499
return self._recipe[3] == 0
1501
def refine(self, seen, referenced):
1502
"""Create a new search by refining this search.
1504
:param seen: Revisions that have been satisfied.
1505
:param referenced: Revision references observed while satisfying some
1508
start = self._recipe[1]
1509
exclude = self._recipe[2]
1510
count = self._recipe[3]
1511
keys = self.get_keys()
1512
# New heads = referenced + old heads - seen things - exclude
1513
pending_refs = set(referenced)
1514
pending_refs.update(start)
1515
pending_refs.difference_update(seen)
1516
pending_refs.difference_update(exclude)
1517
# New exclude = old exclude + satisfied heads
1518
seen_heads = start.intersection(seen)
1519
exclude.update(seen_heads)
1520
# keys gets seen removed
1522
# length is reduced by len(seen)
1524
return SearchResult(pending_refs, exclude, count, keys)
1498
1527
class PendingAncestryResult(object):
1499
1528
"""A search result that will reconstruct the ancestry for some graph heads.
1509
1538
:param repo: a repository to use to generate the ancestry for the given
1541
self.heads = frozenset(heads)
1513
1542
self.repo = repo
1515
1544
def get_recipe(self):
1516
raise NotImplementedError(self.get_recipe)
1545
"""Return a recipe that can be used to replay this search.
1547
The recipe allows reconstruction of the same results at a later date.
1549
:seealso SearchResult.get_recipe:
1551
:return: A tuple ('proxy-search', start_keys_set, set(), -1)
1552
To recreate this result, create a PendingAncestryResult with the
1555
return ('proxy-search', self.heads, set(), -1)
1518
1557
def get_keys(self):
1519
"""See SearchResult.get_keys."""
1520
keys = [key for (key, parents) in
1521
self.repo.get_graph().iter_ancestry(self.heads)]
1522
if keys[-1] != 'null:':
1523
raise AssertionError(
1524
"Ancestry ends with %r, not null." % (keys[-1],))
1558
"""See SearchResult.get_keys.
1560
Returns all the keys for the ancestry of the heads, excluding
1563
return self._get_keys(self.repo.get_graph())
1565
def _get_keys(self, graph):
1566
NULL_REVISION = revision.NULL_REVISION
1567
keys = [key for (key, parents) in graph.iter_ancestry(self.heads)
1568
if key != NULL_REVISION]
1572
"""Return true if the search lists 1 or more revisions."""
1573
if revision.NULL_REVISION in self.heads:
1574
return len(self.heads) == 1
1576
return len(self.heads) == 0
1578
def refine(self, seen, referenced):
1579
"""Create a new search by refining this search.
1581
:param seen: Revisions that have been satisfied.
1582
:param referenced: Revision references observed while satisfying some
1585
referenced = self.heads.union(referenced)
1586
return PendingAncestryResult(referenced - seen, self.repo)
1529
1589
def collapse_linear_regions(parent_map):
1530
1590
"""Collapse regions of the graph that are 'linear'.