From f1c5e64c23037a3dd7fa65794a1f917f9d5f812c Mon Sep 17 00:00:00 2001
From: Todd Gamblin <tgamblin@llnl.gov>
Date: Mon, 15 Dec 2014 14:46:34 -0800
Subject: [PATCH] Partial fix for SPACK-48.

- Try to accommodate packages that have grown dependencies better.
- This will only get fully fixed when optional dependencies are supported
  and some extra functionality is added to the spec syntax.
---
 lib/spack/spack/cmd/uninstall.py    |  3 +--
 lib/spack/spack/directory_layout.py | 31 +++++++++++++++++------------
 lib/spack/spack/packages.py         |  3 ++-
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py
index 84eb4703a6..e787c460ad 100644
--- a/lib/spack/spack/cmd/uninstall.py
+++ b/lib/spack/spack/cmd/uninstall.py
@@ -72,13 +72,12 @@ def uninstall(parser, args):
         for s in matching_specs:
             try:
                 # should work if package is known to spack
-                pkgs.append(spack.db.get(s))
+                pkgs.append(s.package)
 
             except spack.packages.UnknownPackageError, e:
                 # The package.py file has gone away -- but still want to uninstall.
                 spack.Package(s).do_uninstall(force=True)
 
-
     # Sort packages to be uninstalled by the number of installed dependents
     # This ensures we do things in the right order
     def num_installed_deps(pkg):
diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py
index 9b31aad5fe..42cac0c9d2 100644
--- a/lib/spack/spack/directory_layout.py
+++ b/lib/spack/spack/directory_layout.py
@@ -157,19 +157,24 @@ def read_spec(self, path):
             # Specs from files are assumed normal and concrete
             spec = Spec(spec_file.read().replace('\n', ''))
 
-        # If we do not have a package on hand for this spec, we know
-        # it is concrete, and we *assume* that it is normal. This
-        # prevents us from trying to fetch a non-existing package, and
-        # allows best effort for commands like spack find.
-        if not spack.db.exists(spec.name):
-            spec._normal = True
-            spec._concrete = True
-        else:
-            spec.normalize()
-            if not spec.concrete:
-                tty.warn("Spec read from installed package is not concrete:",
-                         path, spec)
-
+        if all(spack.db.exists(s.name) for s in spec.traverse()):
+            copy = spec.copy()
+            copy.normalize()
+            if copy.concrete:
+                return copy   # These are specs spack still understands.
+
+        # If we get here, either the spec is no longer in spack, or
+        # something about its dependencies has changed. So we need to
+        # just assume the read spec is correct.  We'll lose graph
+        # information if we do this, but this is just for best effort
+        # for commands like uninstall and find.  Currently Spack
+        # doesn't do anything that needs the graph info after install.
+
+        # TODO: store specs with full connectivity information, so
+        # that we don't have to normalize or reconstruct based on
+        # changing dependencies in the Spack tree.
+        spec._normal = True
+        spec._concrete = True
         return spec
 
 
diff --git a/lib/spack/spack/packages.py b/lib/spack/spack/packages.py
index 047d82a93a..25d01fe7eb 100644
--- a/lib/spack/spack/packages.py
+++ b/lib/spack/spack/packages.py
@@ -74,7 +74,8 @@ def get(self, spec, **kwargs):
         if not spec in self.instances:
             package_class = self.get_class_for_package_name(spec.name)
             try:
-                self.instances[spec.copy()] = package_class(spec)
+                copy = spec.copy()
+                self.instances[copy] = package_class(copy)
             except Exception, e:
                 raise FailedConstructorError(spec.name, e)
 
-- 
GitLab