Repository: spack/spack

Issue:
spack does not handle multiple repos any more
I had recently updated develop. I was using an additional repo.
 Now this seem to prevent spack to work:

To reproduce:
cd /tmp
git clone https://github.com/LLNL/spack.git 
cd spack
source share/spack/setup-env.sh 
spack spec zlib
---------- WORK as expected ----------
spack repo create /tmp/goofy
spack repo add /tmp/goofy
spack spec zlib
==> Error: Invalid namespace for goofy repo: builtin




Discussion:
I' ve used git bisect to find the problem ( beware I' m a newbie on bisect.... first time ) and seems the problem shows up after commit 
65b38764aedf56192568f5d49eb9a9c87257761b
That is the concretizer speedup
Am I doing something wrong?
@tgamblin Sorry, It seems to me the problem persist: Am I alone in using multiple repos or am I doing something basically wrong? Thanks in advance
By trying and testing I found that this problem goes away by changing fullname to name in line 1198 of spec.py
https://github.com/RemoteConnectionManager/spack/commit/adaa4781d2924eb64919bea247ce606883c83b39

As I' ve not the slightest idea of what I' m doing, hope that someone shade some light on this.
For now, continue testing as I need the repo functionality

In case still work, will submit a PR
I was just about to report the same problem.
I get the same 'Invalid namespace' error.

Reverting to commit db149876 seems to solve the problem,
at least for the few examples I've tried so far.
I think I see the issue here, although I'm not sure how it was triggered only recently. I'll open a PR in the next hour or so.

Resolving patch:
diff --git a/lib/spack/spack/repository.py b/lib/spack/spack/repository.py
--- a/lib/spack/spack/repository.py
+++ b/lib/spack/spack/repository.py
@@ -541,19 +541,21 @@ def repo_for_pkg(self, spec):
         """Given a spec, get the repository for its package."""
         # We don't @_autospec this function b/c it's called very frequently
         # and we want to avoid parsing str's into Specs unnecessarily.
+        namespace = None
         if isinstance(spec, spack.spec.Spec):
-            # If the spec already has a namespace, then return the
-            # corresponding repo if we know about it.
-            if spec.namespace:
-                fullspace = '%s.%s' % (self.super_namespace, spec.namespace)
-                if fullspace not in self.by_namespace:
-                    raise UnknownNamespaceError(spec.namespace)
-                return self.by_namespace[fullspace]
+            namespace = spec.namespace
             name = spec.name
-
         else:
             # handle strings directly for speed instead of @_autospec'ing
-            name = spec
+            namespace, _, name = spec.rpartition('.')
+
+        # If the spec already has a namespace, then return the
+        # corresponding repo if we know about it.
+        if namespace:
+            fullspace = '%s.%s' % (self.super_namespace, namespace)
+            if fullspace not in self.by_namespace:
+                raise UnknownNamespaceError(spec.namespace)
+            return self.by_namespace[fullspace]
 
         # If there's no namespace, search in the RepoPath.
         for repo in self.repos:
@@ -817,7 +819,7 @@ def _read_config(self):
 
     @_autospec
     def get(self, spec, new=False):
-        if spec.virtual:
+        if not self.exists(spec.name):
             raise UnknownPackageError(spec.name)
 
         if spec.namespace and spec.namespace != self.namespace:


Test patch:
diff --git a/lib/spack/spack/test/repo.py b/lib/spack/spack/test/repo.py
new file mode 100644
--- /dev/null
+++ b/lib/spack/spack/test/repo.py
@@ -0,0 +1,76 @@
+##############################################################################
+# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the NOTICE and LICENSE files 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 Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, 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 Lesser 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 spack
+
+import pytest
+
+
+# Unlike the repo_path fixture defined in conftest, this has a test-level
+# scope rather than a session level scope, since we want to edit the
+# given RepoPath
+@pytest.fixture()
+def repo_for_test():
+    return spack.repository.RepoPath(spack.mock_packages_path)
+
+
+@pytest.fixture()
+def extra_repo(tmpdir_factory):
+    repo_namespace = 'extra_test_repo'
+    repo_dir = tmpdir_factory.mktemp(repo_namespace)
+    repo_dir.ensure('packages', dir=True)
+
+    with open(str(repo_dir.join('repo.yaml')), 'w') as F:
+        F.write("""
+repo:
+  namespace: extra_test_repo
+""")
+    return spack.repository.Repo(str(repo_dir))
+
+
+def test_repo_getpkg(repo_for_test):
+    repo_for_test.get('a')
+    repo_for_test.get('builtin.mock.a')
+
+
+def test_repo_multi_getpkg(repo_for_test, extra_repo):
+    repo_for_test.put_first(extra_repo)
+    repo_for_test.get('a')
+    repo_for_test.get('builtin.mock.a')
+
+
+def test_repo_multi_getpkgclass(repo_for_test, extra_repo):
+    repo_for_test.put_first(extra_repo)
+    repo_for_test.get_pkg_class('a')
+    repo_for_test.get_pkg_class('builtin.mock.a')
+
+
+def test_repo_pkg_with_unknown_namespace(repo_for_test):
+    with pytest.raises(spack.repository.UnknownNamespaceError):
+        repo_for_test.get('unknown.a')
+
+
+def test_repo_unknown_pkg(repo_for_test):
+    with pytest.raises(spack.repository.UnknownPackageError):
+        repo_for_test.get('builtin.mock.nonexistentpackage')