diff mercurial/grep.py @ 45721:f9d3ff23bfc0

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.
author Yuya Nishihara <yuya@tcha.org>
date Wed, 09 Sep 2020 17:17:38 +0900
parents c10c87c8fe79
children d4ba4d51f85f
line wrap: on
line diff
--- a/mercurial/grep.py	Sun Oct 04 13:17:57 2020 +0900
+++ b/mercurial/grep.py	Wed Sep 09 17:17:38 2020 +0900
@@ -115,6 +115,34 @@
         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]