diff --git a/bin/spack b/bin/spack index b922fc5479..fb9f045f35 100755 --- a/bin/spack +++ b/bin/spack @@ -96,8 +96,10 @@ except SpackError, e: if spack.debug: # In debug mode, raise with a full stack trace. raise + elif e.long_message: + tty.die(e.message, e.long_message) else: - # Otherwise print a nice simple message. tty.die(e.message) + except KeyboardInterrupt: tty.die("Got a keyboard interrupt from the user.") diff --git a/lib/spack/llnl/util/tty/__init__.py b/lib/spack/llnl/util/tty/__init__.py index afc4b59a63..0e5ddab5fe 100644 --- a/lib/spack/llnl/util/tty/__init__.py +++ b/lib/spack/llnl/util/tty/__init__.py @@ -23,6 +23,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import sys +import textwrap from llnl.util.tty.color import * debug = False @@ -39,7 +40,10 @@ def info(message, *args, **kwargs): format = kwargs.get('format', '*b') cprint("@%s{==>} %s" % (format, cescape(str(message)))) for arg in args: - print indent + str(arg) + lines = textwrap.wrap( + str(arg), initial_indent=indent, subsequent_indent=indent) + for line in lines: + print line def verbose(message, *args): diff --git a/lib/spack/spack/error.py b/lib/spack/spack/error.py index b593ff9fc3..47fb858f3f 100644 --- a/lib/spack/spack/error.py +++ b/lib/spack/spack/error.py @@ -27,8 +27,9 @@ class SpackError(Exception): """This is the superclass for all Spack errors. Subclasses can be found in the modules they have to do with. """ - def __init__(self, message): + def __init__(self, message, long_message=None): super(SpackError, self).__init__(message) + self.long_message = long_message class UnsupportedPlatformError(SpackError): diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py index fe99c0ad8a..df2fe83dac 100644 --- a/lib/spack/spack/stage.py +++ b/lib/spack/spack/stage.py @@ -215,17 +215,27 @@ def chdir(self): def fetch_from_url(self, url): - try: - # Run curl but grab the mime type from the http headers - headers = spack.curl('-#', # status bar - '-O', # save file to disk - '-D', '-', # print out HTML headers - '-L', url, return_output=True) - except: + # Run curl but grab the mime type from the http headers + headers = spack.curl('-#', # status bar + '-O', # save file to disk + '-D', '-', # print out HTML headers + '-L', url, + return_output=True, fail_on_error=False) + + if spack.curl.returncode != 0: # clean up archive on failure. if self.archive_file: os.remove(self.archive_file) - raise + + if spack.curl.returncode == 60: + # This is a certificate error. Suggest spack -k + raise FailedDownloadError( + url, + "Curl was unable to fetch due to invalid certificate. " + "This is either an attack, or your cluster's SSL configuration " + "is bad. If you believe your SSL configuration is bad, you " + "can try running spack -k, which will not check SSL certificates." + "Use this at your own risk.") # Check if we somehow got an HTML file rather than the archive we # asked for. We only look at the last content type, to handle @@ -358,7 +368,7 @@ def find_tmp_root(): class FailedDownloadError(serr.SpackError): """Raised wen a download fails.""" - def __init__(self, url): + def __init__(self, url, msg=""): super(FailedDownloadError, self).__init__( - "Failed to fetch file from URL: " + url) + "Failed to fetch file from URL: %s" % url, msg) self.url = url diff --git a/lib/spack/spack/util/executable.py b/lib/spack/spack/util/executable.py index ac329445f7..845d1470e7 100644 --- a/lib/spack/spack/util/executable.py +++ b/lib/spack/spack/util/executable.py @@ -35,7 +35,7 @@ class Executable(object): """Class representing a program that can be run on the command line.""" def __init__(self, name): self.exe = name.split(' ') - + self.returncode = None def add_default_arg(self, arg): self.exe.append(arg) @@ -68,6 +68,8 @@ def __call__(self, *args, **kwargs): stderr=sys.stderr, stdout=subprocess.PIPE if return_output else sys.stdout) out, err = proc.communicate() + self.returncode = proc.returncode + if fail_on_error and proc.returncode != 0: raise SpackError("command '%s' returned error code %d" % (" ".join(cmd), proc.returncode))