1293
1293
value = self._bisect_nodes[candidate_key]
1294
1294
yield (self, candidate_key, value)
1296
_original_make_search_filter = None
1299
def make_disable_search_filter(branch, generate_delta, search, log_rev_iterator):
1300
"""Disable search filtering if bzr-search will be active.
1302
This filter replaces the default search filter, using the original filter
1303
if a bzr-search filter cannot be used.
1305
:param branch: The branch being logged.
1306
:param generate_delta: Whether to generate a delta for each revision.
1307
:param search: A user text search string.
1308
:param log_rev_iterator: An input iterator containing all revisions that
1309
could be displayed, in lists.
1310
:return: An iterator over ((rev_id, revno, merge_depth), rev, delta).
1313
open_index_branch(branch)
1314
query = query_from_regex(search)
1316
return log_rev_iterator
1317
except errors.NoSearchIndex:
1319
return _original_make_search_filter(branch, generate_delta, search,
1323
def make_log_search_filter(branch, generate_delta, search, log_rev_iterator):
1324
"""Filter revisions by using a search index.
1326
This filter looks up revids in the search index along with the search
1327
string, if the search string regex can be converted into a bzr-search
1330
:param branch: The branch being logged.
1331
:param generate_delta: Whether to generate a delta for each revision.
1332
:param search: A user text search string.
1333
:param log_rev_iterator: An input iterator containing all revisions that
1334
could be displayed, in lists.
1335
:return: An iterator over ((rev_id, revno, merge_depth), rev, delta).
1337
# Can we possibly search on this regex?
1338
query = query_from_regex(search)
1340
return log_rev_iterator
1342
index = open_index_branch(branch)
1343
except errors.NoSearchIndex:
1344
return log_rev_iterator
1345
return _filter_log(index, query, log_rev_iterator)
1348
def _filter_log(index, query, log_rev_iterator):
1349
"""Filter log_rev_iterator's revision ids on query in index."""
1351
# TODO: we could lazy evaluate the search, for each revision we see - this
1352
# would allow searches that hit everything to be less-than-completely
1353
# evaluated before the first result is shown. OTOH knowing a miss will
1354
# require reading the entire search anyhow. Note that we can do better -
1355
# if we looked up the document id of the revision, we could search explicitly
1356
# for the document id in the search up front, and do many small searches. This is
1357
# likely better in terms of memory use. Needs refactoring etc.
1358
for result in index.search(query):
1359
if type(result) != RevisionHit:
1361
rev_ids.add(result.revision_key[0])
1362
for batch in log_rev_iterator:
1365
if item[0][0] in rev_ids:
1366
new_revs.append(item)
1370
def query_from_regex(regex):
1371
"""Convert a regex into a bzr-search query."""
1372
# Most trivial implementation ever
1373
if regex.count("\\b") != 2:
1376
if regex.count("\\b") != 0:
1378
# Any additional whitespace implies something we can't search on:
1380
if _tokeniser_re.search(regex):