summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/create.py54
-rw-r--r--lib/spack/spack/cmd/uninstall.py30
-rw-r--r--lib/spack/spack/package.py20
-rw-r--r--lib/spack/spack/test/__init__.py3
-rw-r--r--lib/spack/spack/test/configure_guess.py90
5 files changed, 163 insertions, 34 deletions
diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py
index c734f58b99..46e6bcec14 100644
--- a/lib/spack/spack/cmd/create.py
+++ b/lib/spack/spack/cmd/create.py
@@ -103,21 +103,35 @@ class ConfigureGuesser(object):
"""Try to guess the type of build system used by the project, and return
an appropriate configure line.
"""
+ autotools = "configure('--prefix=%s' % prefix)"
+ cmake = "cmake('.', *std_cmake_args)"
+ python = "python('setup.py', 'install', '--prefix=%s' % prefix)"
+
+ config_lines = ((r'/configure$', 'autotools', autotools),
+ (r'/CMakeLists.txt$', 'cmake', cmake),
+ (r'/setup.py$', 'python', python))
+
+ # Peek inside the tarball.
tar = which('tar')
output = tar(
"--exclude=*/*/*", "-tf", stage.archive_file, return_output=True)
-
- autotools = 'configure("--prefix=%s" % prefix)'
- cmake = 'cmake(".", *std_cmake_args)'
- lines = output.split('\n')
-
- if any(re.search(r'/configure$', l) for l in lines):
- self.configure = autotools
- elif any(re.search(r'/CMakeLists.txt$', l) for l in lines):
- self.configure = cmake
+ lines = output.split("\n")
+
+ # Set the configure line to the one that matched.
+ for pattern, bs, cl in config_lines:
+ if any(re.search(pattern, l) for l in lines):
+ config_line = cl
+ build_system = bs
+ break
else:
- # Both, with cmake commented out
- self.configure = '%s\n # %s' % (autotools, cmake)
+ # None matched -- just put both, with cmake commented out
+ config_line = "# FIXME: Spack couldn't guess one, so here are some options:\n"
+ config_line += " # " + autotools + "\n"
+ config_line += " # " + cmake
+ build_system = 'unknown'
+
+ self.configure = config_line
+ self.build_system = build_system
def make_version_calls(ver_hash_tuples):
@@ -152,13 +166,6 @@ def create(parser, args):
tty.msg("This looks like a URL for %s version %s." % (name, version))
tty.msg("Creating template for package %s" % name)
- # Create a directory for the new package.
- pkg_path = spack.db.filename_for_package_name(name)
- if os.path.exists(pkg_path) and not args.force:
- tty.die("%s already exists." % pkg_path)
- else:
- mkdirp(os.path.dirname(pkg_path))
-
versions = spack.package.find_versions_of_archive(url)
rkeys = sorted(versions.keys(), reverse=True)
versions = OrderedDict(zip(rkeys, (versions[v] for v in rkeys)))
@@ -190,6 +197,17 @@ def create(parser, args):
if not ver_hash_tuples:
tty.die("Could not fetch any tarballs for %s." % name)
+ # Prepend 'py-' to python package names, by convention.
+ if guesser.build_system == 'python':
+ name = 'py-%s' % name
+
+ # Create a directory for the new package.
+ pkg_path = spack.db.filename_for_package_name(name)
+ if os.path.exists(pkg_path) and not args.force:
+ tty.die("%s already exists." % pkg_path)
+ else:
+ mkdirp(os.path.dirname(pkg_path))
+
# Write out a template for the file
with open(pkg_path, "w") as pkg_file:
pkg_file.write(
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 uninstall(parser, args):
# 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 @@ class Package(object):
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 @@ class Package(object):
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 @@ class InstallError(spack.error.SpackError):
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):
diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py
index 8d4b0c6cde..6b3715be6f 100644
--- a/lib/spack/spack/test/__init__.py
+++ b/lib/spack/spack/test/__init__.py
@@ -55,7 +55,8 @@ test_names = ['versions',
'link_tree',
'spec_yaml',
'optional_deps',
- 'make_executable']
+ 'make_executable',
+ 'configure_guess']
def list_tests():
diff --git a/lib/spack/spack/test/configure_guess.py b/lib/spack/spack/test/configure_guess.py
new file mode 100644
index 0000000000..766dd51d52
--- /dev/null
+++ b/lib/spack/spack/test/configure_guess.py
@@ -0,0 +1,90 @@
+##############################################################################
+# Copyright (c) 2013-2015, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://scalability-llnl.github.io/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License (as published by
+# the Free Software Foundation) version 2.1 dated February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+import os
+import unittest
+import shutil
+import tempfile
+
+from llnl.util.filesystem import *
+
+from spack.cmd.create import ConfigureGuesser
+from spack.stage import Stage
+
+from spack.fetch_strategy import URLFetchStrategy
+from spack.directory_layout import YamlDirectoryLayout
+from spack.util.executable import which
+from spack.test.mock_packages_test import *
+from spack.test.mock_repo import MockArchive
+
+
+class InstallTest(unittest.TestCase):
+ """Tests the configure guesser in spack create"""
+
+ def setUp(self):
+ self.tar = which('tar')
+ self.tmpdir = tempfile.mkdtemp()
+ self.orig_dir = os.getcwd()
+ os.chdir(self.tmpdir)
+ self.stage = None
+
+
+ def tearDown(self):
+ shutil.rmtree(self.tmpdir, ignore_errors=True)
+ if self.stage:
+ self.stage.destroy()
+ os.chdir(self.orig_dir)
+
+
+ def check_archive(self, filename, system):
+ mkdirp('archive')
+ touch(join_path('archive', filename))
+ self.tar('czf', 'archive.tar.gz', 'archive')
+
+ url = 'file://' + join_path(os.getcwd(), 'archive.tar.gz')
+ print url
+ self.stage = Stage(url)
+ self.stage.fetch()
+
+ guesser = ConfigureGuesser()
+ guesser(self.stage)
+ self.assertEqual(system, guesser.build_system)
+
+
+ def test_python(self):
+ self.check_archive('setup.py', 'python')
+
+
+ def test_autotools(self):
+ self.check_archive('configure', 'autotools')
+
+
+ def test_cmake(self):
+ self.check_archive('CMakeLists.txt', 'cmake')
+
+
+ def test_unknown(self):
+ self.check_archive('foobar', 'unknown')
+
+