From edfcac32c35ca9642bc5e9df765c8323cf2501fb Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sat, 20 Jun 2015 21:46:52 -0700 Subject: [PATCH] Fix bug in uninstall (regression in 0fc3b58) --- lib/spack/spack/cmd/uninstall.py | 30 ++++++++++++++++++++++-------- lib/spack/spack/package.py | 20 +++++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py index 6ded455390..aa62510fed 100644 --- a/lib/spack/spack/cmd/uninstall.py +++ b/lib/spack/spack/cmd/uninstall.py @@ -22,13 +22,17 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## +import sys from external import argparse import llnl.util.tty as tty +from llnl.util.tty.colify import colify import spack import spack.cmd import spack.packages +from spack.cmd.find import display_specs +from spack.package import PackageStillNeededError description="Remove an installed package" @@ -57,13 +61,14 @@ def uninstall(parser, args): for spec in specs: matching_specs = spack.db.get_installed(spec) if not args.all and len(matching_specs) > 1: - args = ["%s matches multiple packages." % spec, - "Matching packages:"] - args += [" " + str(s) for s in matching_specs] - args += ["You can either:", - " a) Use spack uninstall -a to uninstall ALL matching specs, or", - " b) use a more specific spec."] - tty.die(*args) + tty.error("%s matches multiple packages:" % spec) + print + display_specs(matching_specs, long=True) + print + print "You can either:" + print " a) Use a more specific spec, or" + print " b) use spack uninstall -a to uninstall ALL matching specs." + sys.exit(1) if len(matching_specs) == 0: if args.force: continue @@ -86,4 +91,13 @@ def num_installed_deps(pkg): # Uninstall packages in order now. for pkg in pkgs: - pkg.do_uninstall(force=args.force) + try: + pkg.do_uninstall(force=args.force) + except PackageStillNeededError, e: + tty.error("Will not uninstall %s" % e.spec.format("$_$@$%@$#", color=True)) + print + print "The following packages depend on it:" + display_specs(e.dependents, long=True) + print + print "You can use spack uninstall -f to force this action." + sys.exit(1) diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 5abf2a6bb3..5c81d3128e 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -569,7 +569,7 @@ def installed_dependents(self): if self.name == spec.name: continue for dep in spec.traverse(): - if spec == dep: + if self.spec == dep: dependents.append(spec) return dependents @@ -897,12 +897,9 @@ def do_uninstall(self, force=False): raise InstallError(str(self.spec) + " is not installed.") if not force: - deps = self.installed_dependents - formatted_deps = [s.format('$_$@$%@$+$=$#') for s in deps] - if deps: raise InstallError( - "Cannot uninstall %s." % self.spec, - "The following installed packages depend on it: %s" % - ' '.join(formatted_deps)) + dependents = self.installed_dependents + if dependents: + raise PackageStillNeededError(self.spec, dependents) # Pre-uninstall hook runs first. spack.hooks.pre_uninstall(self) @@ -1182,6 +1179,15 @@ def __init__(self, message, long_msg=None): super(InstallError, self).__init__(message, long_msg) +class PackageStillNeededError(InstallError): + """Raised when package is still needed by another on uninstall.""" + def __init__(self, spec, dependents): + super(PackageStillNeededError, self).__init__( + "Cannot uninstall %s" % spec) + self.spec = spec + self.dependents = dependents + + class PackageError(spack.error.SpackError): """Raised when something is wrong with a package definition.""" def __init__(self, message, long_msg=None):