[python] return more errors when external commands fail

Summary:
Better to bail early than have mysterious failures. These used to have the wrong error messages:

```
$ cd examples/android_hello/
$ infer -- ./gradlew rubbish
Capturing in gradle mode...
Running and capturing gradle compilation...
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] FAILURE: Build failed with an exception.
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * What went wrong:
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Task 'rubbish' not found in root project 'android_hello'.
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * Try:
10:46:56.730 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace.
Nothing to compile. Try running `./gradlew clean` first.
ERROR: (Unix.Exit_or_signal (Exit_non_zero 66))
$ cd -
$ infer --flavors --Xbuck --keep-going -- buck build //toto:toto
Capturing in buck mode...
moving files in buck-out to buck-out/.trash/buck-outwiiL6N
Not using buckd because watchman isn't installed.
BUILD FAILED: No build file at toto/BUCK when resolving target //toto:toto#infer.
Buck failed, but continuing the analysis because --keep-going was passed
Not using buckd because watchman isn't installed.
No build file at toto/BUCK when resolving target //toto:toto#infer.
Traceback (most recent call last):
  File "/home/jul/infer/infer/bin/../lib/python/infer.py", line 186, in <module>
    main()
  File "/home/jul/infer/infer/bin/../lib/python/infer.py", line 168, in main
    capture_exitcode = imported_module.gen_instance(args, cmd).capture()
  File "/home/jul/infer/infer/lib/python/inferlib/capture/buck.py", line 89, in capture
    return self.capture_with_flavors()
  File "/home/jul/infer/infer/lib/python/inferlib/capture/buck.py", line 242, in capture_with_flavors
    result_paths = self._get_analysis_result_paths()
  File "/home/jul/infer/infer/lib/python/inferlib/capture/buck.py", line 148, in _get_analysis_result_paths
    out = [x.split(None, 1)[1] for x in buck_output.strip().split('\n')]
IndexError: list index out of range
ERROR: (Unix.Exit_or_signal (Exit_non_zero 1))
$ cd infer/build_systems/ant/ && infer -- ant rubbish
Capturing in ant mode...

BUILD FAILED
Target "rubbish" does not exist in the project "null".
        at org.apache.tools.ant.Project.tsort(Project.java:1929)
        at org.apache.tools.ant.Project.topoSort(Project.java:1837)
        at org.apache.tools.ant.Project.topoSort(Project.java:1800)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
        at org.apache.tools.ant.Main.runBuild(Main.java:857)
        at org.apache.tools.ant.Main.startAnt(Main.java:236)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:287)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:113)

Total time: 0 seconds
Nothing to compile. Try running `ant clean` first.
ERROR: (Unix.Exit_or_signal (Exit_non_zero 66))
```

Now we fail better, for instance:
```
$ infer --flavors --Xbuck --keep-going -- buck build //toto:toto
Capturing in buck mode...
moving files in buck-out to buck-out/.trash/buck-outHag8Ji
Not using buckd because watchman isn't installed.
BUILD FAILED: No build file at toto/BUCK when resolving target //toto:toto#infer.
Buck failed, but continuing the analysis because --keep-going was passed
Not using buckd because watchman isn't installed.
No build file at toto/BUCK when resolving target //toto:toto#infer.
ERROR: (Unix.Exit_or_signal (Exit_non_zero 70))
$ cd infer/build_systems/ant/ && infer -- ant rubbish
Capturing in ant mode...

BUILD FAILED
Target "rubbish" does not exist in the project "null".
        at org.apache.tools.ant.Project.tsort(Project.java:1929)
        at org.apache.tools.ant.Project.topoSort(Project.java:1837)
        at org.apache.tools.ant.Project.topoSort(Project.java:1800)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
        at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
        at org.apache.tools.ant.Main.runBuild(Main.java:857)
        at org.apache.tools.ant.Main.startAnt(Main.java:236)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:287)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:113)

Total time: 0 seconds
ERROR: couldn't run compilation command `['ant', '-verbose', u'rubbish']`
ERROR: (Unix.Exit_or_signal (Exit_non_zero 1))
```

Reviewed By: jeremydubreil

Differential Revision: D5469607

fbshipit-source-id: a3eb05c
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent c4f153947b
commit fb2fa5c5ce

@ -6,6 +6,7 @@
# of patent rights can be found in the PATENTS file in the same directory.
import logging
import os
from . import util
from inferlib import jwlib
@ -78,6 +79,9 @@ class AntCapture:
return calls
def capture(self):
cmds = self.get_infer_commands(util.get_build_output(self.build_cmd))
clean_cmd = '%s clean' % self.build_cmd[0]
(code, verbose_out) = util.get_build_output(self.build_cmd)
if code != os.EX_OK:
return code
clean_cmd = '\'{}\' clean'.format(self.build_cmd[0])
cmds = self.get_infer_commands(verbose_out)
return util.run_compilation_commands(cmds, clean_cmd)

@ -144,6 +144,8 @@ class BuckAnalyzer:
[x for x in buck_results_cmd if x != KEEP_GOING_OPTION]
proc = subprocess.Popen(buck_results_cmd, stdout=subprocess.PIPE)
(buck_output, _) = proc.communicate()
if proc.returncode != 0:
return None
# remove target name prefixes from each line and split them into a list
out = [x.split(None, 1)[1] for x in buck_output.strip().split('\n')]
return [os.path.dirname(x)
@ -240,6 +242,9 @@ class BuckAnalyzer:
if not ret == os.EX_OK and not self.keep_going:
return ret
result_paths = self._get_analysis_result_paths()
if result_paths is None:
# huho, the Buck command to extract results paths failed
return os.EX_SOFTWARE
merged_reports_path = os.path.join(
self.args.infer_out, config.JSON_REPORT_FILENAME)
merged_deps_path = os.path.join(

@ -83,6 +83,9 @@ class GradleCapture:
def capture(self):
print('Running and capturing gradle compilation...')
cmds = self.get_infer_commands(util.get_build_output(self.build_cmd))
(code, verbose_out) = util.get_build_output(self.build_cmd)
if code != os.EX_OK:
return code
cmds = self.get_infer_commands(verbose_out)
clean_cmd = '%s clean' % self.build_cmd[0]
return util.run_compilation_commands(cmds, clean_cmd)

@ -25,7 +25,12 @@ def get_build_output(build_cmd):
# TODO make it return generator to be able to handle large builds
proc = subprocess.Popen(build_cmd, stdout=subprocess.PIPE)
(verbose_out_chars, _) = proc.communicate()
return utils.decode(verbose_out_chars).split('\n')
if proc.returncode != 0:
utils.stderr(
'ERROR: couldn\'t run compilation command `{}`'.format(build_cmd))
return (proc.returncode, None)
out = utils.decode(verbose_out_chars).split('\n')
return (os.EX_OK, out)
def run_compilation_commands(cmds, clean_cmd):
@ -33,7 +38,7 @@ def run_compilation_commands(cmds, clean_cmd):
in case there is nothing to compile.
"""
# TODO call it in parallel
if len(cmds) == 0:
if cmds is None or len(cmds) == 0:
utils.stderr('Nothing to compile. Try running `{}` first.'
.format(clean_cmd))
return os.EX_NOINPUT

Loading…
Cancel
Save