summaryrefslogtreecommitdiffstats
path: root/subcmds/grep.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/grep.py')
-rw-r--r--subcmds/grep.py84
1 files changed, 58 insertions, 26 deletions
diff --git a/subcmds/grep.py b/subcmds/grep.py
index 5cd33763..9ebd776c 100644
--- a/subcmds/grep.py
+++ b/subcmds/grep.py
@@ -17,8 +17,10 @@ import sys
17 17
18from color import Coloring 18from color import Coloring
19from command import DEFAULT_LOCAL_JOBS, PagedCommand 19from command import DEFAULT_LOCAL_JOBS, PagedCommand
20from error import GitError 20from error import GitError, InvalidArgumentsError, SilentRepoExitError
21from git_command import GitCommand 21from git_command import GitCommand
22from typing import NamedTuple
23from project import Project
22 24
23 25
24class GrepColoring(Coloring): 26class GrepColoring(Coloring):
@@ -28,6 +30,22 @@ class GrepColoring(Coloring):
28 self.fail = self.printer("fail", fg="red") 30 self.fail = self.printer("fail", fg="red")
29 31
30 32
33class ExecuteOneResult(NamedTuple):
34 """Result from an execute instance."""
35
36 project: Project
37 rc: int
38 stdout: str
39 stderr: str
40 error: GitError
41
42
43class GrepCommandError(SilentRepoExitError):
44 """Grep command failure. Since Grep command
45 output already outputs errors ensure that
46 aggregate errors exit silently."""
47
48
31class Grep(PagedCommand): 49class Grep(PagedCommand):
32 COMMON = True 50 COMMON = True
33 helpSummary = "Print lines matching a pattern" 51 helpSummary = "Print lines matching a pattern"
@@ -246,11 +264,18 @@ contain a line that matches both expressions:
246 bare=False, 264 bare=False,
247 capture_stdout=True, 265 capture_stdout=True,
248 capture_stderr=True, 266 capture_stderr=True,
267 verify_command=True,
249 ) 268 )
250 except GitError as e: 269 except GitError as e:
251 return (project, -1, None, str(e)) 270 return ExecuteOneResult(project, -1, None, str(e), e)
252 271
253 return (project, p.Wait(), p.stdout, p.stderr) 272 try:
273 error = None
274 rc = p.Wait()
275 except GitError as e:
276 rc = 1
277 error = e
278 return ExecuteOneResult(project, rc, p.stdout, p.stderr, error)
254 279
255 @staticmethod 280 @staticmethod
256 def _ProcessResults(full_name, have_rev, opt, _pool, out, results): 281 def _ProcessResults(full_name, have_rev, opt, _pool, out, results):
@@ -258,31 +283,40 @@ contain a line that matches both expressions:
258 bad_rev = False 283 bad_rev = False
259 have_match = False 284 have_match = False
260 _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only) 285 _RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)
286 errors = []
261 287
262 for project, rc, stdout, stderr in results: 288 for result in results:
263 if rc < 0: 289 if result.rc < 0:
264 git_failed = True 290 git_failed = True
265 out.project("--- project %s ---" % _RelPath(project)) 291 out.project("--- project %s ---" % _RelPath(result.project))
266 out.nl() 292 out.nl()
267 out.fail("%s", stderr) 293 out.fail("%s", result.stderr)
268 out.nl() 294 out.nl()
295 errors.append(result.error)
269 continue 296 continue
270 297
271 if rc: 298 if result.rc:
272 # no results 299 # no results
273 if stderr: 300 if result.stderr:
274 if have_rev and "fatal: ambiguous argument" in stderr: 301 if (
302 have_rev
303 and "fatal: ambiguous argument" in result.stderr
304 ):
275 bad_rev = True 305 bad_rev = True
276 else: 306 else:
277 out.project("--- project %s ---" % _RelPath(project)) 307 out.project(
308 "--- project %s ---" % _RelPath(result.project)
309 )
278 out.nl() 310 out.nl()
279 out.fail("%s", stderr.strip()) 311 out.fail("%s", result.stderr.strip())
280 out.nl() 312 out.nl()
313 if result.error is not None:
314 errors.append(result.error)
281 continue 315 continue
282 have_match = True 316 have_match = True
283 317
284 # We cut the last element, to avoid a blank line. 318 # We cut the last element, to avoid a blank line.
285 r = stdout.split("\n") 319 r = result.stdout.split("\n")
286 r = r[0:-1] 320 r = r[0:-1]
287 321
288 if have_rev and full_name: 322 if have_rev and full_name:
@@ -290,13 +324,13 @@ contain a line that matches both expressions:
290 rev, line = line.split(":", 1) 324 rev, line = line.split(":", 1)
291 out.write("%s", rev) 325 out.write("%s", rev)
292 out.write(":") 326 out.write(":")
293 out.project(_RelPath(project)) 327 out.project(_RelPath(result.project))
294 out.write("/") 328 out.write("/")
295 out.write("%s", line) 329 out.write("%s", line)
296 out.nl() 330 out.nl()
297 elif full_name: 331 elif full_name:
298 for line in r: 332 for line in r:
299 out.project(_RelPath(project)) 333 out.project(_RelPath(result.project))
300 out.write("/") 334 out.write("/")
301 out.write("%s", line) 335 out.write("%s", line)
302 out.nl() 336 out.nl()
@@ -304,7 +338,7 @@ contain a line that matches both expressions:
304 for line in r: 338 for line in r:
305 print(line) 339 print(line)
306 340
307 return (git_failed, bad_rev, have_match) 341 return (git_failed, bad_rev, have_match, errors)
308 342
309 def Execute(self, opt, args): 343 def Execute(self, opt, args):
310 out = GrepColoring(self.manifest.manifestProject.config) 344 out = GrepColoring(self.manifest.manifestProject.config)
@@ -333,16 +367,14 @@ contain a line that matches both expressions:
333 have_rev = False 367 have_rev = False
334 if opt.revision: 368 if opt.revision:
335 if "--cached" in cmd_argv: 369 if "--cached" in cmd_argv:
336 print( 370 msg = "fatal: cannot combine --cached and --revision"
337 "fatal: cannot combine --cached and --revision", 371 print(msg, file=sys.stderr)
338 file=sys.stderr, 372 raise InvalidArgumentsError(msg)
339 )
340 sys.exit(1)
341 have_rev = True 373 have_rev = True
342 cmd_argv.extend(opt.revision) 374 cmd_argv.extend(opt.revision)
343 cmd_argv.append("--") 375 cmd_argv.append("--")
344 376
345 git_failed, bad_rev, have_match = self.ExecuteInParallel( 377 git_failed, bad_rev, have_match, errors = self.ExecuteInParallel(
346 opt.jobs, 378 opt.jobs,
347 functools.partial(self._ExecuteOne, cmd_argv), 379 functools.partial(self._ExecuteOne, cmd_argv),
348 projects, 380 projects,
@@ -354,12 +386,12 @@ contain a line that matches both expressions:
354 ) 386 )
355 387
356 if git_failed: 388 if git_failed:
357 sys.exit(1) 389 raise GrepCommandError(
390 "error: git failures", aggregate_errors=errors
391 )
358 elif have_match: 392 elif have_match:
359 sys.exit(0) 393 sys.exit(0)
360 elif have_rev and bad_rev: 394 elif have_rev and bad_rev:
361 for r in opt.revision: 395 for r in opt.revision:
362 print("error: can't search revision %s" % r, file=sys.stderr) 396 print("error: can't search revision %s" % r, file=sys.stderr)
363 sys.exit(1) 397 raise GrepCommandError(aggregate_errors=errors)
364 else:
365 sys.exit(1)