Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 1 | # Copyright (C) 2009 The Android Open Source Project |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
| 14 | |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 15 | import functools |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 16 | import sys |
Mike Frysinger | 6447733 | 2023-08-21 21:20:32 -0400 | [diff] [blame] | 17 | from typing import NamedTuple |
Mike Frysinger | 72ab852 | 2019-10-01 00:18:46 -0400 | [diff] [blame] | 18 | |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 19 | from color import Coloring |
Mike Frysinger | 6447733 | 2023-08-21 21:20:32 -0400 | [diff] [blame] | 20 | from command import DEFAULT_LOCAL_JOBS |
| 21 | from command import PagedCommand |
| 22 | from error import GitError |
| 23 | from error import InvalidArgumentsError |
| 24 | from error import SilentRepoExitError |
Mike Frysinger | 6f1c626 | 2020-02-04 00:09:23 -0500 | [diff] [blame] | 25 | from git_command import GitCommand |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 26 | from project import Project |
Aravind Vasudevan | c993c50 | 2023-09-14 08:46:44 +0000 | [diff] [blame] | 27 | from repo_logging import RepoLogger |
| 28 | |
| 29 | |
| 30 | logger = RepoLogger(__file__) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 31 | |
David Pursehouse | 819827a | 2020-02-12 15:20:19 +0900 | [diff] [blame] | 32 | |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 33 | class GrepColoring(Coloring): |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 34 | def __init__(self, config): |
| 35 | Coloring.__init__(self, config, "grep") |
| 36 | self.project = self.printer("project", attr="bold") |
| 37 | self.fail = self.printer("fail", fg="red") |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 38 | |
David Pursehouse | 819827a | 2020-02-12 15:20:19 +0900 | [diff] [blame] | 39 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 40 | class ExecuteOneResult(NamedTuple): |
| 41 | """Result from an execute instance.""" |
| 42 | |
| 43 | project: Project |
| 44 | rc: int |
| 45 | stdout: str |
| 46 | stderr: str |
| 47 | error: GitError |
| 48 | |
| 49 | |
| 50 | class GrepCommandError(SilentRepoExitError): |
| 51 | """Grep command failure. Since Grep command |
| 52 | output already outputs errors ensure that |
| 53 | aggregate errors exit silently.""" |
| 54 | |
| 55 | |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 56 | class Grep(PagedCommand): |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 57 | COMMON = True |
| 58 | helpSummary = "Print lines matching a pattern" |
| 59 | helpUsage = """ |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 60 | %prog {pattern | -e pattern} [<project>...] |
| 61 | """ |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 62 | helpDescription = """ |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 63 | Search for the specified patterns in all project files. |
| 64 | |
Mike Frysinger | b8f7bb0 | 2018-10-10 01:05:11 -0400 | [diff] [blame] | 65 | # Boolean Options |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 66 | |
| 67 | The following options can appear as often as necessary to express |
| 68 | the pattern to locate: |
| 69 | |
| 70 | -e PATTERN |
| 71 | --and, --or, --not, -(, -) |
| 72 | |
| 73 | Further, the -r/--revision option may be specified multiple times |
| 74 | in order to scan multiple trees. If the same file matches in more |
| 75 | than one tree, only the first result is reported, prefixed by the |
| 76 | revision name it was found under. |
| 77 | |
Mike Frysinger | b8f7bb0 | 2018-10-10 01:05:11 -0400 | [diff] [blame] | 78 | # Examples |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 79 | |
| 80 | Look for a line that has '#define' and either 'MAX_PATH or 'PATH_MAX': |
| 81 | |
David Pursehouse | 1d947b3 | 2012-10-25 12:23:11 +0900 | [diff] [blame] | 82 | repo grep -e '#define' --and -\\( -e MAX_PATH -e PATH_MAX \\) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 83 | |
| 84 | Look for a line that has 'NODE' or 'Unexpected' in files that |
| 85 | contain a line that matches both expressions: |
| 86 | |
| 87 | repo grep --all-match -e NODE -e Unexpected |
| 88 | |
| 89 | """ |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 90 | PARALLEL_JOBS = DEFAULT_LOCAL_JOBS |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 91 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 92 | @staticmethod |
| 93 | def _carry_option(_option, opt_str, value, parser): |
| 94 | pt = getattr(parser.values, "cmd_argv", None) |
| 95 | if pt is None: |
| 96 | pt = [] |
| 97 | setattr(parser.values, "cmd_argv", pt) |
Mike Frysinger | 45ad154 | 2021-02-24 12:47:01 -0500 | [diff] [blame] | 98 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 99 | if opt_str == "-(": |
| 100 | pt.append("(") |
| 101 | elif opt_str == "-)": |
| 102 | pt.append(")") |
| 103 | else: |
| 104 | pt.append(opt_str) |
Mike Frysinger | 45ad154 | 2021-02-24 12:47:01 -0500 | [diff] [blame] | 105 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 106 | if value is not None: |
| 107 | pt.append(value) |
Mike Frysinger | 45ad154 | 2021-02-24 12:47:01 -0500 | [diff] [blame] | 108 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 109 | def _CommonOptions(self, p): |
| 110 | """Override common options slightly.""" |
| 111 | super()._CommonOptions(p, opt_v=False) |
Mike Frysinger | 9180a07 | 2021-04-13 14:57:40 -0400 | [diff] [blame] | 112 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 113 | def _Options(self, p): |
| 114 | g = p.add_option_group("Sources") |
| 115 | g.add_option( |
| 116 | "--cached", |
| 117 | action="callback", |
| 118 | callback=self._carry_option, |
| 119 | help="Search the index, instead of the work tree", |
| 120 | ) |
| 121 | g.add_option( |
| 122 | "-r", |
| 123 | "--revision", |
| 124 | dest="revision", |
| 125 | action="append", |
| 126 | metavar="TREEish", |
| 127 | help="Search TREEish, instead of the work tree", |
| 128 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 129 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 130 | g = p.add_option_group("Pattern") |
| 131 | g.add_option( |
| 132 | "-e", |
| 133 | action="callback", |
| 134 | callback=self._carry_option, |
| 135 | metavar="PATTERN", |
| 136 | type="str", |
| 137 | help="Pattern to search for", |
| 138 | ) |
| 139 | g.add_option( |
| 140 | "-i", |
| 141 | "--ignore-case", |
| 142 | action="callback", |
| 143 | callback=self._carry_option, |
| 144 | help="Ignore case differences", |
| 145 | ) |
| 146 | g.add_option( |
| 147 | "-a", |
| 148 | "--text", |
| 149 | action="callback", |
| 150 | callback=self._carry_option, |
| 151 | help="Process binary files as if they were text", |
| 152 | ) |
| 153 | g.add_option( |
| 154 | "-I", |
| 155 | action="callback", |
| 156 | callback=self._carry_option, |
| 157 | help="Don't match the pattern in binary files", |
| 158 | ) |
| 159 | g.add_option( |
| 160 | "-w", |
| 161 | "--word-regexp", |
| 162 | action="callback", |
| 163 | callback=self._carry_option, |
| 164 | help="Match the pattern only at word boundaries", |
| 165 | ) |
| 166 | g.add_option( |
| 167 | "-v", |
| 168 | "--invert-match", |
| 169 | action="callback", |
| 170 | callback=self._carry_option, |
| 171 | help="Select non-matching lines", |
| 172 | ) |
| 173 | g.add_option( |
| 174 | "-G", |
| 175 | "--basic-regexp", |
| 176 | action="callback", |
| 177 | callback=self._carry_option, |
| 178 | help="Use POSIX basic regexp for patterns (default)", |
| 179 | ) |
| 180 | g.add_option( |
| 181 | "-E", |
| 182 | "--extended-regexp", |
| 183 | action="callback", |
| 184 | callback=self._carry_option, |
| 185 | help="Use POSIX extended regexp for patterns", |
| 186 | ) |
| 187 | g.add_option( |
| 188 | "-F", |
| 189 | "--fixed-strings", |
| 190 | action="callback", |
| 191 | callback=self._carry_option, |
| 192 | help="Use fixed strings (not regexp) for pattern", |
| 193 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 194 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 195 | g = p.add_option_group("Pattern Grouping") |
| 196 | g.add_option( |
| 197 | "--all-match", |
| 198 | action="callback", |
| 199 | callback=self._carry_option, |
| 200 | help="Limit match to lines that have all patterns", |
| 201 | ) |
| 202 | g.add_option( |
| 203 | "--and", |
| 204 | "--or", |
| 205 | "--not", |
| 206 | action="callback", |
| 207 | callback=self._carry_option, |
| 208 | help="Boolean operators to combine patterns", |
| 209 | ) |
| 210 | g.add_option( |
| 211 | "-(", |
| 212 | "-)", |
| 213 | action="callback", |
| 214 | callback=self._carry_option, |
| 215 | help="Boolean operator grouping", |
| 216 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 217 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 218 | g = p.add_option_group("Output") |
| 219 | g.add_option( |
| 220 | "-n", |
| 221 | action="callback", |
| 222 | callback=self._carry_option, |
| 223 | help="Prefix the line number to matching lines", |
| 224 | ) |
| 225 | g.add_option( |
| 226 | "-C", |
| 227 | action="callback", |
| 228 | callback=self._carry_option, |
| 229 | metavar="CONTEXT", |
| 230 | type="str", |
| 231 | help="Show CONTEXT lines around match", |
| 232 | ) |
| 233 | g.add_option( |
| 234 | "-B", |
| 235 | action="callback", |
| 236 | callback=self._carry_option, |
| 237 | metavar="CONTEXT", |
| 238 | type="str", |
| 239 | help="Show CONTEXT lines before match", |
| 240 | ) |
| 241 | g.add_option( |
| 242 | "-A", |
| 243 | action="callback", |
| 244 | callback=self._carry_option, |
| 245 | metavar="CONTEXT", |
| 246 | type="str", |
| 247 | help="Show CONTEXT lines after match", |
| 248 | ) |
| 249 | g.add_option( |
| 250 | "-l", |
| 251 | "--name-only", |
| 252 | "--files-with-matches", |
| 253 | action="callback", |
| 254 | callback=self._carry_option, |
| 255 | help="Show only file names containing matching lines", |
| 256 | ) |
| 257 | g.add_option( |
| 258 | "-L", |
| 259 | "--files-without-match", |
| 260 | action="callback", |
| 261 | callback=self._carry_option, |
| 262 | help="Show only file names not containing matching lines", |
| 263 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 264 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 265 | def _ExecuteOne(self, cmd_argv, project): |
| 266 | """Process one project.""" |
| 267 | try: |
| 268 | p = GitCommand( |
| 269 | project, |
| 270 | cmd_argv, |
| 271 | bare=False, |
| 272 | capture_stdout=True, |
| 273 | capture_stderr=True, |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 274 | verify_command=True, |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 275 | ) |
| 276 | except GitError as e: |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 277 | return ExecuteOneResult(project, -1, None, str(e), e) |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 278 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 279 | try: |
| 280 | error = None |
| 281 | rc = p.Wait() |
| 282 | except GitError as e: |
| 283 | rc = 1 |
| 284 | error = e |
| 285 | return ExecuteOneResult(project, rc, p.stdout, p.stderr, error) |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 286 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 287 | @staticmethod |
| 288 | def _ProcessResults(full_name, have_rev, opt, _pool, out, results): |
| 289 | git_failed = False |
| 290 | bad_rev = False |
| 291 | have_match = False |
| 292 | _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only) |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 293 | errors = [] |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 294 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 295 | for result in results: |
| 296 | if result.rc < 0: |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 297 | git_failed = True |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 298 | out.project("--- project %s ---" % _RelPath(result.project)) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 299 | out.nl() |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 300 | out.fail("%s", result.stderr) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 301 | out.nl() |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 302 | errors.append(result.error) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 303 | continue |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 304 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 305 | if result.rc: |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 306 | # no results |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 307 | if result.stderr: |
| 308 | if ( |
| 309 | have_rev |
| 310 | and "fatal: ambiguous argument" in result.stderr |
| 311 | ): |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 312 | bad_rev = True |
| 313 | else: |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 314 | out.project( |
| 315 | "--- project %s ---" % _RelPath(result.project) |
| 316 | ) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 317 | out.nl() |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 318 | out.fail("%s", result.stderr.strip()) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 319 | out.nl() |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 320 | if result.error is not None: |
| 321 | errors.append(result.error) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 322 | continue |
| 323 | have_match = True |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 324 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 325 | # We cut the last element, to avoid a blank line. |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 326 | r = result.stdout.split("\n") |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 327 | r = r[0:-1] |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 328 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 329 | if have_rev and full_name: |
| 330 | for line in r: |
| 331 | rev, line = line.split(":", 1) |
| 332 | out.write("%s", rev) |
| 333 | out.write(":") |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 334 | out.project(_RelPath(result.project)) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 335 | out.write("/") |
| 336 | out.write("%s", line) |
| 337 | out.nl() |
| 338 | elif full_name: |
| 339 | for line in r: |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 340 | out.project(_RelPath(result.project)) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 341 | out.write("/") |
| 342 | out.write("%s", line) |
| 343 | out.nl() |
| 344 | else: |
| 345 | for line in r: |
| 346 | print(line) |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 347 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 348 | return (git_failed, bad_rev, have_match, errors) |
Mike Frysinger | d246d1f | 2021-02-24 12:50:30 -0500 | [diff] [blame] | 349 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 350 | def Execute(self, opt, args): |
| 351 | out = GrepColoring(self.manifest.manifestProject.config) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 352 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 353 | cmd_argv = ["grep"] |
| 354 | if out.is_on: |
| 355 | cmd_argv.append("--color") |
| 356 | cmd_argv.extend(getattr(opt, "cmd_argv", [])) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 357 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 358 | if "-e" not in cmd_argv: |
| 359 | if not args: |
| 360 | self.Usage() |
| 361 | cmd_argv.append("-e") |
| 362 | cmd_argv.append(args[0]) |
| 363 | args = args[1:] |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 364 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 365 | projects = self.GetProjects( |
| 366 | args, all_manifests=not opt.this_manifest_only |
| 367 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 368 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 369 | full_name = False |
| 370 | if len(projects) > 1: |
| 371 | cmd_argv.append("--full-name") |
| 372 | full_name = True |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 373 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 374 | have_rev = False |
| 375 | if opt.revision: |
| 376 | if "--cached" in cmd_argv: |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 377 | msg = "fatal: cannot combine --cached and --revision" |
Aravind Vasudevan | c993c50 | 2023-09-14 08:46:44 +0000 | [diff] [blame] | 378 | logger.error(msg) |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 379 | raise InvalidArgumentsError(msg) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 380 | have_rev = True |
| 381 | cmd_argv.extend(opt.revision) |
| 382 | cmd_argv.append("--") |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 383 | |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 384 | git_failed, bad_rev, have_match, errors = self.ExecuteInParallel( |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 385 | opt.jobs, |
| 386 | functools.partial(self._ExecuteOne, cmd_argv), |
| 387 | projects, |
| 388 | callback=functools.partial( |
| 389 | self._ProcessResults, full_name, have_rev, opt |
| 390 | ), |
| 391 | output=out, |
| 392 | ordered=True, |
| 393 | ) |
Shawn O. Pearce | b812a36 | 2009-04-10 20:37:47 -0700 | [diff] [blame] | 394 | |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 395 | if git_failed: |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 396 | raise GrepCommandError( |
| 397 | "error: git failures", aggregate_errors=errors |
| 398 | ) |
Gavin Mak | ea2e330 | 2023-03-11 06:46:20 +0000 | [diff] [blame] | 399 | elif have_match: |
| 400 | sys.exit(0) |
| 401 | elif have_rev and bad_rev: |
| 402 | for r in opt.revision: |
Aravind Vasudevan | c993c50 | 2023-09-14 08:46:44 +0000 | [diff] [blame] | 403 | logger.error("error: can't search revision %s", r) |
Jason Chang | 1a3612f | 2023-08-08 14:12:53 -0700 | [diff] [blame] | 404 | raise GrepCommandError(aggregate_errors=errors) |