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:
		@@ -1659,6 +1659,15 @@ def concretized_specs(self):
 | 
				
			|||||||
        for s, h in zip(self.concretized_user_specs, self.concretized_order):
 | 
					        for s, h in zip(self.concretized_user_specs, self.concretized_order):
 | 
				
			||||||
            yield (s, self.specs_by_hash[h])
 | 
					            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):
 | 
					    def matching_spec(self, spec):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Given a spec (likely not concretized), find a matching concretized
 | 
					        Given a spec (likely not concretized), find a matching concretized
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5167,10 +5167,15 @@ def parse_compiler(self, text):
 | 
				
			|||||||
        return self.compiler()
 | 
					        return self.compiler()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def spec_by_hash(self):
 | 
					    def spec_by_hash(self):
 | 
				
			||||||
 | 
					        # TODO: Remove parser dependency on active environment and database.
 | 
				
			||||||
 | 
					        import spack.environment
 | 
				
			||||||
        self.expect(ID)
 | 
					        self.expect(ID)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        dag_hash = self.token.value
 | 
					        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:
 | 
					        if not matches:
 | 
				
			||||||
            raise NoSuchHashError(dag_hash)
 | 
					            raise NoSuchHashError(dag_hash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2843,3 +2843,16 @@ def test_environment_view_target_already_exists(
 | 
				
			|||||||
    # Make sure the dir was left untouched.
 | 
					    # Make sure the dir was left untouched.
 | 
				
			||||||
    assert not os.path.lexists(view)
 | 
					    assert not os.path.lexists(view)
 | 
				
			||||||
    assert os.listdir(real_view) == ['file']
 | 
					    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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user