changeset 45457:d2b5a7659fff

cmdutil: reimplement finddate() without using walkchangerevs() It's simpler and slightly faster maybe because a fewer Python ops would run. Unscientific benchmark: $ python -m timeit \ -s 'from mercurial import hg, ui, cmdutil; repo = hg.repository(ui.ui())' \ 'cmdutil.finddate(repo.ui, repo, "<2008-01-01")' (orig) 10 loops, best of 3: 1.45 sec per loop (new) 10 loops, best of 3: 1.25 sec per loop Now "hg churn" and "hg grep" are the only users of walkchangerevs(), which I want to refactor and fix bugs.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 13 Sep 2020 17:52:24 +0900
parents 65960fe9a769
children 4532e7ebde4d
files mercurial/cmdutil.py
diffstat 1 files changed, 11 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Sun Sep 13 18:14:51 2020 +0900
+++ b/mercurial/cmdutil.py	Sun Sep 13 17:52:24 2020 +0900
@@ -2230,26 +2230,17 @@
 
 def finddate(ui, repo, date):
     """Find the tipmost changeset that matches the given date spec"""
-
-    df = dateutil.matchdate(date)
-    m = scmutil.matchall(repo)
-    results = {}
-
-    def prep(ctx, fns):
-        d = ctx.date()
-        if df(d[0]):
-            results[ctx.rev()] = d
-
-    for ctx in walkchangerevs(repo, m, {b'rev': None}, prep):
-        rev = ctx.rev()
-        if rev in results:
-            ui.status(
-                _(b"found revision %d from %s\n")
-                % (rev, dateutil.datestr(results[rev]))
-            )
-            return b'%d' % rev
-
-    raise error.Abort(_(b"revision matching date not found"))
+    mrevs = repo.revs(b'date(%s)', date)
+    try:
+        rev = mrevs.max()
+    except ValueError:
+        raise error.Abort(_(b"revision matching date not found"))
+
+    ui.status(
+        _(b"found revision %d from %s\n")
+        % (rev, dateutil.datestr(repo[rev].date()))
+    )
+    return b'%d' % rev
 
 
 def increasingwindows(windowsize=8, sizelimit=512):