stacks: update environment add/remove algorithms
This commit is contained in:
		
				
					committed by
					
						
						Todd Gamblin
					
				
			
			
				
	
			
			
			
						parent
						
							6cfbfcc967
						
					
				
				
					commit
					533a8d7c82
				
			@@ -674,73 +674,61 @@ def add(self, user_spec, list_name='specs'):
 | 
				
			|||||||
            elif not spack.repo.path.exists(spec.name):
 | 
					            elif not spack.repo.path.exists(spec.name):
 | 
				
			||||||
                raise SpackEnvironmentError('no such package: %s' % spec.name)
 | 
					                raise SpackEnvironmentError('no such package: %s' % spec.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        added = False
 | 
					        list_to_change = self.read_specs[list_name]
 | 
				
			||||||
        existing = False
 | 
					        existing = str(spec) in list_to_change.yaml_list
 | 
				
			||||||
        for i, (name, speclist) in enumerate(self.read_specs.items()):
 | 
					        if not existing:
 | 
				
			||||||
            # Iterate over all named lists from an OrderedDict()
 | 
					            list_to_change.add(str(spec))
 | 
				
			||||||
            if name == list_name:
 | 
					            index = list(self.read_specs.keys()).index(list_name)
 | 
				
			||||||
                # We need to modify this list
 | 
					
 | 
				
			||||||
                # TODO: Add conditional which reimplements name-level checking
 | 
					            for i, (name, speclist) in enumerate(
 | 
				
			||||||
                existing = str(spec) in speclist.yaml_list
 | 
					                    list(self.read_specs.items())[index + 1:], index + 1):
 | 
				
			||||||
                if not existing:
 | 
					 | 
				
			||||||
                    speclist.add(str(spec))
 | 
					 | 
				
			||||||
                    added = True
 | 
					 | 
				
			||||||
            elif added:
 | 
					 | 
				
			||||||
                # We've already modified a list, so all later lists need to
 | 
					 | 
				
			||||||
                # have their references updated.
 | 
					 | 
				
			||||||
                new_reference = dict((n, self.read_specs[n])
 | 
					                new_reference = dict((n, self.read_specs[n])
 | 
				
			||||||
                                     for n in list(self.read_specs.keys())[:i])
 | 
					                                     for n in list(self.read_specs.keys())[:i])
 | 
				
			||||||
                speclist.update_reference(new_reference)
 | 
					                speclist.update_reference(new_reference)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return bool(not existing)
 | 
					        return bool(not existing)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def remove(self, query_spec, list_name='specs', force=False):
 | 
					    def remove(self, query_spec, list_name='specs', force=False):
 | 
				
			||||||
        """Remove specs from an environment that match a query_spec"""
 | 
					        """Remove specs from an environment that match a query_spec"""
 | 
				
			||||||
        query_spec = Spec(query_spec)
 | 
					        query_spec = Spec(query_spec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        removed = False
 | 
					        list_to_change = self.read_specs[list_name]
 | 
				
			||||||
        for i, (name, speclist) in enumerate(self.read_specs.items()):
 | 
					        matches = []
 | 
				
			||||||
            # Iterate over all named lists from an OrderedDict()
 | 
					 | 
				
			||||||
            if name == list_name:
 | 
					 | 
				
			||||||
                # We need to modify this list
 | 
					 | 
				
			||||||
                # try abstract specs first
 | 
					 | 
				
			||||||
                matches = []
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if not query_spec.concrete:
 | 
					        if not query_spec.concrete:
 | 
				
			||||||
                    matches = [s for s in speclist if s.satisfies(query_spec)]
 | 
					            matches = [s for s in list_to_change if s.satisfies(query_spec)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if not matches:
 | 
					        if not matches:
 | 
				
			||||||
                    # concrete specs match against concrete specs in the env
 | 
					            # concrete specs match against concrete specs in the env
 | 
				
			||||||
                    specs_hashes = zip(
 | 
					            specs_hashes = zip(
 | 
				
			||||||
                        self.concretized_user_specs, self.concretized_order)
 | 
					                self.concretized_user_specs, self.concretized_order)
 | 
				
			||||||
                    matches = [
 | 
					            matches = [
 | 
				
			||||||
                        s for s, h in specs_hashes
 | 
					                s for s, h in specs_hashes
 | 
				
			||||||
                        if query_spec.dag_hash() == h
 | 
					                if query_spec.dag_hash() == h
 | 
				
			||||||
                    ]
 | 
					            ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if not matches:
 | 
					        if not matches:
 | 
				
			||||||
                    raise SpackEnvironmentError(
 | 
					            raise SpackEnvironmentError(
 | 
				
			||||||
                        "Not found: {0}".format(query_spec))
 | 
					                "Not found: {0}".format(query_spec))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for spec in matches:
 | 
					        for spec in matches:
 | 
				
			||||||
                    if spec in speclist:
 | 
					            if spec in list_to_change:
 | 
				
			||||||
                        speclist.remove(spec)
 | 
					                list_to_change.remove(spec)
 | 
				
			||||||
                        removed = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if force and spec in self.concretized_user_specs:
 | 
					            if force and spec in self.concretized_user_specs:
 | 
				
			||||||
                        i = self.concretized_user_specs.index(spec)
 | 
					                i = self.concretized_user_specs.index(spec)
 | 
				
			||||||
                        del self.concretized_user_specs[i]
 | 
					                del self.concretized_user_specs[i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        dag_hash = self.concretized_order[i]
 | 
					                dag_hash = self.concretized_order[i]
 | 
				
			||||||
                        del self.concretized_order[i]
 | 
					                del self.concretized_order[i]
 | 
				
			||||||
                        del self.specs_by_hash[dag_hash]
 | 
					                del self.specs_by_hash[dag_hash]
 | 
				
			||||||
                        removed = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elif removed:
 | 
					        index = list(self.read_specs.keys()).index(list_name)
 | 
				
			||||||
                # We've already modified one list, so all later lists need
 | 
					        for i, (name, speclist) in enumerate(
 | 
				
			||||||
                # their references updated.
 | 
					                list(self.read_specs.items())[index + 1:], index + 1):
 | 
				
			||||||
                new_reference = dict((n, self.read_specs[n])
 | 
					            new_reference = dict((n, self.read_specs[n])
 | 
				
			||||||
                                     for n in list(self.read_specs.keys())[:i])
 | 
					                                 for n in list(self.read_specs.keys())[:i])
 | 
				
			||||||
                speclist.update_reference(new_reference)
 | 
					            speclist.update_reference(new_reference)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def concretize(self, force=False):
 | 
					    def concretize(self, force=False):
 | 
				
			||||||
        """Concretize user_specs in this environment.
 | 
					        """Concretize user_specs in this environment.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,7 +136,7 @@ def _expand_references(self, yaml):
 | 
				
			|||||||
                        return ret
 | 
					                        return ret
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        msg = 'SpecList %s refers to ' % self.name
 | 
					                        msg = 'SpecList %s refers to ' % self.name
 | 
				
			||||||
                        msg = 'named list %s ' % name
 | 
					                        msg += 'named list %s ' % name
 | 
				
			||||||
                        msg += 'which does not appear in its reference dict'
 | 
					                        msg += 'which does not appear in its reference dict'
 | 
				
			||||||
                        raise UndefinedReferenceError(msg)
 | 
					                        raise UndefinedReferenceError(msg)
 | 
				
			||||||
            # No references in this
 | 
					            # No references in this
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -827,6 +827,33 @@ def test_stack_yaml_remove_from_list(tmpdir):
 | 
				
			|||||||
        assert Spec('callpath') in test.user_specs
 | 
					        assert Spec('callpath') in test.user_specs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_stack_yaml_remove_from_list_force(tmpdir):
 | 
				
			||||||
 | 
					    filename = str(tmpdir.join('spack.yaml'))
 | 
				
			||||||
 | 
					    with open(filename, 'w') as f:
 | 
				
			||||||
 | 
					        f.write("""\
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  definitions:
 | 
				
			||||||
 | 
					    - packages: [mpileaks, callpath]
 | 
				
			||||||
 | 
					  specs:
 | 
				
			||||||
 | 
					    - matrix:
 | 
				
			||||||
 | 
					        - [$packages]
 | 
				
			||||||
 | 
					        - [^mpich, ^zmpi]
 | 
				
			||||||
 | 
					""")
 | 
				
			||||||
 | 
					    with tmpdir.as_cwd():
 | 
				
			||||||
 | 
					        env('create', 'test', './spack.yaml')
 | 
				
			||||||
 | 
					        with ev.read('test'):
 | 
				
			||||||
 | 
					            concretize()
 | 
				
			||||||
 | 
					            remove('-f', '-l', 'packages', 'mpileaks')
 | 
				
			||||||
 | 
					            find_output = find('-c')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print find_output
 | 
				
			||||||
 | 
					        assert False
 | 
				
			||||||
 | 
					        test = ev.read('test')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert Spec('mpileaks') not in test.user_specs
 | 
				
			||||||
 | 
					        assert Spec('callpath') in test.user_specs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_stack_yaml_attempt_remove_from_matrix(tmpdir):
 | 
					def test_stack_yaml_attempt_remove_from_matrix(tmpdir):
 | 
				
			||||||
    filename = str(tmpdir.join('spack.yaml'))
 | 
					    filename = str(tmpdir.join('spack.yaml'))
 | 
				
			||||||
    with open(filename, 'w') as f:
 | 
					    with open(filename, 'w') as f:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user