spec.py: make parser select from environment (#30276)

The parser is already committing a crime of querying the database for
specs when it encounters a `/hash`. It's helpful, but unfortunately not
helpful when trying to install a specific spec in an environment by
hash. Therefore, consider the environment first, then the database.

This allows the following:

```console
$ spack -e . concretize
==> Starting concretization
==> Environment concretized in 0.27 seconds.
==> Concretized diffutils
 -   7vangk4  diffutils@3.8%gcc@10.3.0 arch=linux-ubuntu20.04-zen2
 -   hyb7ehx      ^libiconv@1.16%gcc@10.3.0 libs=shared,static arch=linux-ubuntu20.04-zen2

$ spack -e . install /hyb7ehx
==> Installing libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
...
==> libiconv: Successfully installed libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
  Fetch: 0.01s.  Build: 17.54s.  Total: 17.55s.
[+] /tmp/tmp.VpvYApofVm/store/linux-ubuntu20.04-zen2/gcc-10.3.0/libiconv-1.16-hyb7ehxxyqqp2hiw56bzm5ampkw6cxws
```
This commit is contained in:
Harmen Stoppels 2022-04-25 17:41:48 +02:00 committed by GitHub
parent c1ed51e767
commit 3dd4999fd7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 2 deletions

View file

@ -1659,6 +1659,15 @@ def concretized_specs(self):
for s, h in zip(self.concretized_user_specs, self.concretized_order):
yield (s, self.specs_by_hash[h])
def get_by_hash(self, dag_hash):
matches = {}
for _, root in self.concretized_specs():
for spec in root.traverse(root=True):
dep_hash = spec.dag_hash()
if dep_hash.startswith(dag_hash):
matches[dep_hash] = spec
return list(matches.values())
def matching_spec(self, spec):
"""
Given a spec (likely not concretized), find a matching concretized

View file

@ -5167,10 +5167,15 @@ def parse_compiler(self, text):
return self.compiler()
def spec_by_hash(self):
# TODO: Remove parser dependency on active environment and database.
import spack.environment
self.expect(ID)
dag_hash = self.token.value
matches = spack.store.db.get_by_hash(dag_hash)
matches = []
if spack.environment.active_environment():
matches = spack.environment.active_environment().get_by_hash(dag_hash)
if not matches:
matches = spack.store.db.get_by_hash(dag_hash)
if not matches:
raise NoSuchHashError(dag_hash)

View file

@ -2843,3 +2843,16 @@ def test_environment_view_target_already_exists(
# Make sure the dir was left untouched.
assert not os.path.lexists(view)
assert os.listdir(real_view) == ['file']
def test_environment_query_spec_by_hash(mock_stage, mock_fetch, install_mockery):
env('create', 'test')
with ev.read('test'):
add('libdwarf')
concretize()
with ev.read('test') as e:
spec = e.matching_spec('libelf')
install('/{0}'.format(spec.dag_hash()))
with ev.read('test') as e:
assert not e.matching_spec('libdwarf').installed
assert e.matching_spec('libelf').installed