Patchwork [3,of,7] grep: extract main search loop as searcher method

login
register
mail settings
Submitter Yuya Nishihara
Date Oct. 14, 2020, 2:13 p.m.
Message ID <5b3013b8e40a903e7d31.1602684813@mimosa>
Download mbox | patch
Permalink /patch/47458/
State Accepted
Headers show

Comments

Yuya Nishihara - Oct. 14, 2020, 2:13 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1599639458 -32400
#      Wed Sep 09 17:17:38 2020 +0900
# Node ID 5b3013b8e40a903e7d31196c1e00877120339242
# Parent  09a598f9d9790918f47f66b6ce5e51f198510289
grep: extract main search loop as searcher method

Still displayer part is in commands.grep(), the core grep logic is now
reusable. I'll revisit the displayer stuff later since it will be another
long series.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3403,8 +3403,6 @@  def grep(ui, repo, pattern, *pats, **opt
     )
 
     getfile = searcher._getfile
-    matches = searcher._matches
-    copies = searcher._copies
 
     uipathfn = scmutil.getuipathfn(repo)
 
@@ -3514,8 +3512,6 @@  def grep(ui, repo, pattern, *pats, **opt
             fm.data(matched=False)
         fm.end()
 
-    skip = searcher._skip
-    revfiles = searcher._revfiles
     found = False
 
     wopts = logcmdutil.walkopts(
@@ -3532,29 +3528,11 @@  def grep(ui, repo, pattern, *pats, **opt
 
     ui.pager(b'grep')
     fm = ui.formatter(b'grep', opts)
-    for ctx in scmutil.walkchangerevs(
-        repo, revs, makefilematcher, searcher._prep
-    ):
-        rev = ctx.rev()
-        parent = ctx.p1().rev()
-        for fn in sorted(revfiles.get(rev, [])):
-            states = matches[rev][fn]
-            copy = copies.get(rev, {}).get(fn)
-            if fn in skip:
-                if copy:
-                    skip.add(copy)
-                continue
-            pstates = matches.get(parent, {}).get(copy or fn, [])
-            if pstates or states:
-                r = display(fm, fn, ctx, pstates, states)
-                found = found or r
-                if r and not diff and not all_files:
-                    searcher.skipfile(fn, rev)
-        del revfiles[rev]
-        # We will keep the matches dict for the duration of the window
-        # clear the matches dict once the window is over
-        if not revfiles:
-            matches.clear()
+    for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
+        r = display(fm, fn, ctx, pstates, states)
+        found = found or r
+        if r and not diff and not all_files:
+            searcher.skipfile(fn, ctx.rev())
     fm.end()
 
     return not found
diff --git a/mercurial/grep.py b/mercurial/grep.py
--- a/mercurial/grep.py
+++ b/mercurial/grep.py
@@ -115,6 +115,34 @@  class grepsearcher(object):
         if copy:
             self._skip.add(copy)
 
+    def searchfiles(self, revs, makefilematcher):
+        """Walk files and revisions to yield (fn, ctx, pstates, states)
+        matches
+
+        states is a list of linestate objects. pstates may be empty unless
+        diff is True.
+        """
+        for ctx in scmutil.walkchangerevs(
+            self._repo, revs, makefilematcher, self._prep
+        ):
+            rev = ctx.rev()
+            parent = ctx.p1().rev()
+            for fn in sorted(self._revfiles.get(rev, [])):
+                states = self._matches[rev][fn]
+                copy = self._copies.get(rev, {}).get(fn)
+                if fn in self._skip:
+                    if copy:
+                        self._skip.add(copy)
+                    continue
+                pstates = self._matches.get(parent, {}).get(copy or fn, [])
+                if pstates or states:
+                    yield fn, ctx, pstates, states
+            del self._revfiles[rev]
+            # We will keep the matches dict for the duration of the window
+            # clear the matches dict once the window is over
+            if not self._revfiles:
+                self._matches.clear()
+
     def _grepbody(self, fn, rev, body):
         self._matches[rev].setdefault(fn, [])
         m = self._matches[rev][fn]