def installed_relatives(self, spec, direction='children', transitive=True): """Return installed specs related to this one.""" if direction not in ('parents', 'children'): raise ValueError("Invalid direction: %s" % direction) relatives = set() for spec in self.query(spec): if transitive: to_add = spec.traverse(direction=direction, root=False) elif direction == 'parents': to_add = spec.dependents() else: # direction == 'children' to_add = spec.dependencies() for relative in to_add: hash_key = relative.dag_hash() if hash_key not in self._data: reltype = ('Dependent' if direction == 'parents' else 'Dependency') tty.warn("Inconsistent state! %s %s of %s not in DB" % (reltype, hash_key, spec.dag_hash())) continue if not self._data[hash_key].installed: continue relatives.add(relative) return relatives
def installed_relatives(self, spec, direction='children', transitive=True, deptype='all'): """Return installed specs related to this one.""" if direction not in ('parents', 'children'): raise ValueError("Invalid direction: %s" % direction) relatives = set() for spec in self.query(spec): if transitive: to_add = spec.traverse( direction=direction, root=False, deptype=deptype) elif direction == 'parents': to_add = spec.dependents(deptype=deptype) else: # direction == 'children' to_add = spec.dependencies(deptype=deptype) for relative in to_add: hash_key = relative.dag_hash() upstream, record = self.query_by_spec_hash(hash_key) if not record: reltype = ('Dependent' if direction == 'parents' else 'Dependency') msg = ("Inconsistent state! %s %s of %s not in DB" % (reltype, hash_key, spec.dag_hash())) if self._fail_when_missing_deps: raise MissingDependenciesError(msg) tty.warn(msg) continue if not record.installed: continue relatives.add(relative) return relatives
def get_deps(spec): for dep in spec.dependencies(deptype=('link', 'run')): get_deps(dep) if dep not in dependencies and dep not in matches: tty.msg("Installing buildcache for dependency spec %s" % dep) dependencies.append(dep)
def _add(self, spec, directory_layout=None, explicit=False): """Add an install record for this spec to the database. Assumes spec is installed in ``layout.path_for_spec(spec)``. Also ensures dependencies are present and updated in the DB as either intsalled or missing. """ if not spec.concrete: raise NonConcreteSpecAddError( "Specs added to DB must be concrete.") for dep in spec.dependencies(_tracked_deps): dkey = dep.dag_hash() if dkey not in self._data: self._add(dep, directory_layout, explicit=False) key = spec.dag_hash() if key not in self._data: installed = False path = None if not spec.external and directory_layout: path = directory_layout.path_for_spec(spec) try: directory_layout.check_installed(spec) installed = True except DirectoryLayoutError as e: tty.warn( 'Dependency missing due to corrupt install directory:', path, str(e)) # Create a new install record with no deps initially. new_spec = spec.copy(deps=False) self._data[key] = InstallRecord(new_spec, path, installed, ref_count=0, explicit=explicit) # Connect dependencies from the DB to the new copy. for name, dep in spec.dependencies_dict(_tracked_deps).iteritems(): dkey = dep.spec.dag_hash() new_spec._add_dependency(self._data[dkey].spec, dep.deptypes) self._data[dkey].ref_count += 1 # Mark concrete once everything is built, and preserve # the original hash of concrete specs. new_spec._mark_concrete() new_spec._hash = key else: # If it is already there, mark it as installed. self._data[key].installed = True self._data[key].explicit = explicit
def _check_merkleiness(): """Ensure the spack database is a valid merkle graph.""" all_specs = spack.store.db.query(installed=any) seen = {} for spec in all_specs: for dep in spec.dependencies(): hash_key = dep.dag_hash() if hash_key not in seen: seen[hash_key] = id(dep) else: assert seen[hash_key] == id(dep)
def _add(self, spec, directory_layout=None, explicit=False): """Add an install record for this spec to the database. Assumes spec is installed in ``layout.path_for_spec(spec)``. Also ensures dependencies are present and updated in the DB as either intsalled or missing. """ if not spec.concrete: raise NonConcreteSpecAddError( "Specs added to DB must be concrete.") for dep in spec.dependencies(_tracked_deps): dkey = dep.dag_hash() if dkey not in self._data: self._add(dep, directory_layout, explicit=False) key = spec.dag_hash() if key not in self._data: installed = bool(spec.external) path = None if not spec.external and directory_layout: path = directory_layout.path_for_spec(spec) try: directory_layout.check_installed(spec) installed = True except DirectoryLayoutError as e: tty.warn( 'Dependency missing due to corrupt install directory:', path, str(e)) # Create a new install record with no deps initially. new_spec = spec.copy(deps=False) self._data[key] = InstallRecord( new_spec, path, installed, ref_count=0, explicit=explicit) # Connect dependencies from the DB to the new copy. for name, dep in iteritems(spec.dependencies_dict(_tracked_deps)): dkey = dep.spec.dag_hash() new_spec._add_dependency(self._data[dkey].spec, dep.deptypes) self._data[dkey].ref_count += 1 # Mark concrete once everything is built, and preserve # the original hash of concrete specs. new_spec._mark_concrete() new_spec._hash = key else: # If it is already there, mark it as installed. self._data[key].installed = True self._data[key].explicit = explicit
def test_get_dependent_ids(install_mockery, mock_packages): # Concretize the parent package, which handle dependency too spec = spack.spec.Spec('a') spec.concretize() assert spec.concrete pkg_id = inst.package_id(spec.package) # Grab the sole dependency of 'a', which is 'b' dep = spec.dependencies()[0] # Ensure the parent package is a dependent of the dependency package assert pkg_id in inst.get_dependent_ids(dep)
def _decrement_ref_count(self, spec): key = spec.dag_hash() if key not in self._data: # TODO: print something here? DB is corrupt, but # not much we can do. return rec = self._data[key] rec.ref_count -= 1 if rec.ref_count == 0 and not rec.installed: del self._data[key] for dep in spec.dependencies(_tracked_deps): self._decrement_ref_count(dep)
def _add( self, spec, directory_layout=None, explicit=False, installation_time=None ): """Add an install record for this spec to the database. Assumes spec is installed in ``layout.path_for_spec(spec)``. Also ensures dependencies are present and updated in the DB as either installed or missing. Args: spec: spec to be added directory_layout: layout of the spec installation **kwargs: explicit Possible values: True, False, any A spec that was installed following a specific user request is marked as explicit. If instead it was pulled-in as a dependency of a user requested spec it's considered implicit. installation_time Date and time of installation """ if not spec.concrete: raise NonConcreteSpecAddError( "Specs added to DB must be concrete.") # Retrieve optional arguments installation_time = installation_time or _now() for dep in spec.dependencies(_tracked_deps): dkey = dep.dag_hash() if dkey not in self._data: extra_args = { 'explicit': False, 'installation_time': installation_time } self._add(dep, directory_layout, **extra_args) key = spec.dag_hash() if key not in self._data: installed = bool(spec.external) path = None if not spec.external and directory_layout: path = directory_layout.path_for_spec(spec) try: directory_layout.check_installed(spec) installed = True except DirectoryLayoutError as e: tty.warn( 'Dependency missing due to corrupt install directory:', path, str(e)) # Create a new install record with no deps initially. new_spec = spec.copy(deps=False) extra_args = { 'explicit': explicit, 'installation_time': installation_time } self._data[key] = InstallRecord( new_spec, path, installed, ref_count=0, **extra_args ) # Connect dependencies from the DB to the new copy. for name, dep in iteritems(spec.dependencies_dict(_tracked_deps)): dkey = dep.spec.dag_hash() new_spec._add_dependency(self._data[dkey].spec, dep.deptypes) self._data[dkey].ref_count += 1 # Mark concrete once everything is built, and preserve # the original hash of concrete specs. new_spec._mark_concrete() new_spec._hash = key else: # If it is already there, mark it as installed. self._data[key].installed = True self._data[key].explicit = explicit