# HG changeset patch # User Yuya Nishihara # Date 2020-10-04 04:17:57 # Node ID 508dfd1c18df2d4875b7cb1b647b8d23527a1d7f # Parent c10c87c8fe79a7c1f7e6097928fa4de5e2fec953 scmutil: move walkchangerevs() from cmdutil It's no longer a command-level function, but a pure helper to walk revisions in a windowed way. This change will help eliminate reverse dependency of revset.py -> grep.py -> cmdutil.py in future patches. diff --git a/hgext/churn.py b/hgext/churn.py --- a/hgext/churn.py +++ b/hgext/churn.py @@ -23,6 +23,7 @@ from mercurial import ( patch, pycompat, registrar, + scmutil, ) cmdtable = {} @@ -98,7 +99,7 @@ def countrate(ui, repo, amap, *pats, **o exclude_pats=opts[b'exclude'], ) revs, makefilematcher = logcmdutil.makewalker(repo, wopts) - for ctx in cmdutil.walkchangerevs(repo, revs, makefilematcher, prep): + for ctx in scmutil.walkchangerevs(repo, revs, makefilematcher, prep): continue progress.complete() diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2240,55 +2240,6 @@ def finddate(ui, repo, date): return b'%d' % rev -def increasingwindows(windowsize=8, sizelimit=512): - while True: - yield windowsize - if windowsize < sizelimit: - windowsize *= 2 - - -def walkchangerevs(repo, revs, makefilematcher, prepare): - '''Iterate over files and the revs in a "windowed" way. - - Callers most commonly need to iterate backwards over the history - in which they are interested. Doing so has awful (quadratic-looking) - performance, so we use iterators in a "windowed" way. - - We walk a window of revisions in the desired order. Within the - window, we first walk forwards to gather data, then in the desired - order (usually backwards) to display it. - - This function returns an iterator yielding contexts. Before - yielding each context, the iterator will first call the prepare - function on each context in the window in forward order.''' - - if not revs: - return [] - change = repo.__getitem__ - - def iterate(): - it = iter(revs) - stopiteration = False - for windowsize in increasingwindows(): - nrevs = [] - for i in pycompat.xrange(windowsize): - rev = next(it, None) - if rev is None: - stopiteration = True - break - nrevs.append(rev) - for rev in sorted(nrevs): - ctx = change(rev) - prepare(ctx, makefilematcher(ctx)) - for rev in nrevs: - yield change(rev) - - if stopiteration: - break - - return iterate() - - def add(ui, repo, match, prefix, uipathfn, explicitonly, **opts): bad = [] diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -3532,7 +3532,7 @@ def grep(ui, repo, pattern, *pats, **opt ui.pager(b'grep') fm = ui.formatter(b'grep', opts) - for ctx in cmdutil.walkchangerevs( + for ctx in scmutil.walkchangerevs( repo, revs, makefilematcher, searcher._prep ): rev = ctx.rev() diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -760,6 +760,55 @@ def revrange(repo, specs, localalias=Non return repo.anyrevs(allspecs, user=True, localalias=localalias) +def increasingwindows(windowsize=8, sizelimit=512): + while True: + yield windowsize + if windowsize < sizelimit: + windowsize *= 2 + + +def walkchangerevs(repo, revs, makefilematcher, prepare): + '''Iterate over files and the revs in a "windowed" way. + + Callers most commonly need to iterate backwards over the history + in which they are interested. Doing so has awful (quadratic-looking) + performance, so we use iterators in a "windowed" way. + + We walk a window of revisions in the desired order. Within the + window, we first walk forwards to gather data, then in the desired + order (usually backwards) to display it. + + This function returns an iterator yielding contexts. Before + yielding each context, the iterator will first call the prepare + function on each context in the window in forward order.''' + + if not revs: + return [] + change = repo.__getitem__ + + def iterate(): + it = iter(revs) + stopiteration = False + for windowsize in increasingwindows(): + nrevs = [] + for i in pycompat.xrange(windowsize): + rev = next(it, None) + if rev is None: + stopiteration = True + break + nrevs.append(rev) + for rev in sorted(nrevs): + ctx = change(rev) + prepare(ctx, makefilematcher(ctx)) + for rev in nrevs: + yield change(rev) + + if stopiteration: + break + + return iterate() + + def meaningfulparents(repo, ctx): """Return list of meaningful (or all if debug) parentrevs for rev.