find and uninstall work when installed package is no longer in spack.
- Make switching between git branches easier. - Make future removal of packages easier.
This commit is contained in:
parent
2f21ca64e0
commit
d0b179962b
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
import spack
|
import spack
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
|
import spack.packages
|
||||||
|
|
||||||
description="Remove an installed package"
|
description="Remove an installed package"
|
||||||
|
|
||||||
@ -68,7 +69,15 @@ def uninstall(parser, args):
|
|||||||
if len(matching_specs) == 0:
|
if len(matching_specs) == 0:
|
||||||
tty.die("%s does not match any installed packages." % spec)
|
tty.die("%s does not match any installed packages." % spec)
|
||||||
|
|
||||||
pkgs.extend(spack.db.get(s) for s in matching_specs)
|
for s in matching_specs:
|
||||||
|
try:
|
||||||
|
# should work if package is known to spack
|
||||||
|
pkgs.append(spack.db.get(s))
|
||||||
|
|
||||||
|
except spack.packages.UnknownPackageError, e:
|
||||||
|
# The package.py file has gone away -- but still want to uninstall.
|
||||||
|
spack.Package(s).do_uninstall(force=True)
|
||||||
|
|
||||||
|
|
||||||
# Sort packages to be uninstalled by the number of installed dependents
|
# Sort packages to be uninstalled by the number of installed dependents
|
||||||
# This ensures we do things in the right order
|
# This ensures we do things in the right order
|
||||||
|
@ -155,7 +155,8 @@ def read_spec(self, path):
|
|||||||
"""Read the contents of a file and parse them as a spec"""
|
"""Read the contents of a file and parse them as a spec"""
|
||||||
with closing(open(path)) as spec_file:
|
with closing(open(path)) as spec_file:
|
||||||
string = spec_file.read().replace('\n', '')
|
string = spec_file.read().replace('\n', '')
|
||||||
return Spec(string)
|
# Specs from files are assumed normal and concrete
|
||||||
|
return Spec(string, concrete=True)
|
||||||
|
|
||||||
|
|
||||||
def make_path_for_spec(self, spec):
|
def make_path_for_spec(self, spec):
|
||||||
|
@ -322,9 +322,6 @@ class SomePackage(Package):
|
|||||||
|
|
||||||
|
|
||||||
def __init__(self, spec):
|
def __init__(self, spec):
|
||||||
# These attributes are required for all packages.
|
|
||||||
attr_required(self.__class__, 'homepage')
|
|
||||||
|
|
||||||
# this determines how the package should be built.
|
# this determines how the package should be built.
|
||||||
self.spec = spec
|
self.spec = spec
|
||||||
|
|
||||||
@ -396,9 +393,13 @@ def stage(self):
|
|||||||
raise ValueError("Can only get a stage for a concrete package.")
|
raise ValueError("Can only get a stage for a concrete package.")
|
||||||
|
|
||||||
if self._stage is None:
|
if self._stage is None:
|
||||||
|
if not self.url:
|
||||||
|
raise PackageVersionError(self.version)
|
||||||
|
|
||||||
# TODO: move this logic into a mirror module.
|
# TODO: move this logic into a mirror module.
|
||||||
mirror_path = "%s/%s" % (self.name, "%s-%s.%s" % (
|
mirror_path = "%s/%s" % (self.name, "%s-%s.%s" % (
|
||||||
self.name, self.version, extension(self.url)))
|
self.name, self.version, extension(self.url)))
|
||||||
|
|
||||||
self._stage = Stage(
|
self._stage = Stage(
|
||||||
self.url, mirror_path=mirror_path, name=self.spec.short_spec)
|
self.url, mirror_path=mirror_path, name=self.spec.short_spec)
|
||||||
return self._stage
|
return self._stage
|
||||||
@ -531,8 +532,6 @@ def nearest_url(version):
|
|||||||
break
|
break
|
||||||
if self.versions[v].url:
|
if self.versions[v].url:
|
||||||
url = self.versions[v].url
|
url = self.versions[v].url
|
||||||
if not url:
|
|
||||||
raise PackageVersionError(v)
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
if version in self.versions:
|
if version in self.versions:
|
||||||
|
@ -345,6 +345,17 @@ def __init__(self, spec_like, *dep_like, **kwargs):
|
|||||||
self.compiler = other.compiler
|
self.compiler = other.compiler
|
||||||
self.dependencies = other.dependencies
|
self.dependencies = other.dependencies
|
||||||
|
|
||||||
|
# Specs are by default not assumed to be normal, but in some
|
||||||
|
# cases we've read them from a file want to assume normal.
|
||||||
|
# This allows us to manipulate specs that Spack doesn't have
|
||||||
|
# package.py files for.
|
||||||
|
self._normal = kwargs.get('normal', False)
|
||||||
|
self._concrete = kwargs.get('concrete', False)
|
||||||
|
|
||||||
|
# Specs cannot be concrete and non-normal.
|
||||||
|
if self._concrete:
|
||||||
|
self._normal = True
|
||||||
|
|
||||||
# This allows users to construct a spec DAG with literals.
|
# This allows users to construct a spec DAG with literals.
|
||||||
# Note that given two specs a and b, Spec(a) copies a, but
|
# Note that given two specs a and b, Spec(a) copies a, but
|
||||||
# Spec(a, b) will copy a but just add b as a dep.
|
# Spec(a, b) will copy a but just add b as a dep.
|
||||||
@ -432,11 +443,15 @@ def concrete(self):
|
|||||||
If any of the name, version, architecture, compiler, or depdenencies
|
If any of the name, version, architecture, compiler, or depdenencies
|
||||||
are ambiguous,then it is not concrete.
|
are ambiguous,then it is not concrete.
|
||||||
"""
|
"""
|
||||||
return bool(not self.virtual
|
if self._concrete:
|
||||||
and self.versions.concrete
|
return True
|
||||||
and self.architecture
|
|
||||||
and self.compiler and self.compiler.concrete
|
self._concrete = bool(not self.virtual
|
||||||
and self.dependencies.concrete)
|
and self.versions.concrete
|
||||||
|
and self.architecture
|
||||||
|
and self.compiler and self.compiler.concrete
|
||||||
|
and self.dependencies.concrete)
|
||||||
|
return self._concrete
|
||||||
|
|
||||||
|
|
||||||
def preorder_traversal(self, visited=None, d=0, **kwargs):
|
def preorder_traversal(self, visited=None, d=0, **kwargs):
|
||||||
@ -606,7 +621,7 @@ def _expand_virtual_packages(self):
|
|||||||
|
|
||||||
# If there are duplicate providers or duplicate provider deps, this
|
# If there are duplicate providers or duplicate provider deps, this
|
||||||
# consolidates them and merges constraints.
|
# consolidates them and merges constraints.
|
||||||
self.normalize()
|
self.normalize(force=True)
|
||||||
|
|
||||||
|
|
||||||
def concretize(self):
|
def concretize(self):
|
||||||
@ -621,9 +636,13 @@ def concretize(self):
|
|||||||
with requirements of its pacakges. See flatten() and normalize() for
|
with requirements of its pacakges. See flatten() and normalize() for
|
||||||
more details on this.
|
more details on this.
|
||||||
"""
|
"""
|
||||||
|
if self._concrete:
|
||||||
|
return
|
||||||
|
|
||||||
self.normalize()
|
self.normalize()
|
||||||
self._expand_virtual_packages()
|
self._expand_virtual_packages()
|
||||||
self._concretize_helper()
|
self._concretize_helper()
|
||||||
|
self._concrete = True
|
||||||
|
|
||||||
|
|
||||||
def concretized(self):
|
def concretized(self):
|
||||||
@ -754,7 +773,7 @@ def _normalize_helper(self, visited, spec_deps, provider_index):
|
|||||||
dependency._normalize_helper(visited, spec_deps, provider_index)
|
dependency._normalize_helper(visited, spec_deps, provider_index)
|
||||||
|
|
||||||
|
|
||||||
def normalize(self):
|
def normalize(self, **kwargs):
|
||||||
"""When specs are parsed, any dependencies specified are hanging off
|
"""When specs are parsed, any dependencies specified are hanging off
|
||||||
the root, and ONLY the ones that were explicitly provided are there.
|
the root, and ONLY the ones that were explicitly provided are there.
|
||||||
Normalization turns a partial flat spec into a DAG, where:
|
Normalization turns a partial flat spec into a DAG, where:
|
||||||
@ -772,6 +791,9 @@ def normalize(self):
|
|||||||
TODO: normalize should probably implement some form of cycle detection,
|
TODO: normalize should probably implement some form of cycle detection,
|
||||||
to ensure that the spec is actually a DAG.
|
to ensure that the spec is actually a DAG.
|
||||||
"""
|
"""
|
||||||
|
if self._normal and not kwargs.get('force', False):
|
||||||
|
return
|
||||||
|
|
||||||
# Ensure first that all packages & compilers in the DAG exist.
|
# Ensure first that all packages & compilers in the DAG exist.
|
||||||
self.validate_names()
|
self.validate_names()
|
||||||
|
|
||||||
@ -805,6 +827,9 @@ def normalize(self):
|
|||||||
raise InvalidDependencyException(
|
raise InvalidDependencyException(
|
||||||
self.name + " does not depend on " + comma_or(extra))
|
self.name + " does not depend on " + comma_or(extra))
|
||||||
|
|
||||||
|
# Mark the spec as normal once done.
|
||||||
|
self._normal = True
|
||||||
|
|
||||||
|
|
||||||
def normalized(self):
|
def normalized(self):
|
||||||
"""Return a normalized copy of this spec without modifying this spec."""
|
"""Return a normalized copy of this spec without modifying this spec."""
|
||||||
@ -1009,6 +1034,9 @@ def _dup(self, other, **kwargs):
|
|||||||
else:
|
else:
|
||||||
self.dependencies = DependencyMap()
|
self.dependencies = DependencyMap()
|
||||||
|
|
||||||
|
self._normal = other._normal
|
||||||
|
self._concrete = other._concrete
|
||||||
|
|
||||||
|
|
||||||
def copy(self, **kwargs):
|
def copy(self, **kwargs):
|
||||||
"""Return a copy of this spec.
|
"""Return a copy of this spec.
|
||||||
@ -1261,6 +1289,9 @@ def spec(self):
|
|||||||
spec.dependents = DependencyMap()
|
spec.dependents = DependencyMap()
|
||||||
spec.dependencies = DependencyMap()
|
spec.dependencies = DependencyMap()
|
||||||
|
|
||||||
|
spec._normal = False
|
||||||
|
spec._concrete = False
|
||||||
|
|
||||||
# record this so that we know whether version is
|
# record this so that we know whether version is
|
||||||
# unspecified or not.
|
# unspecified or not.
|
||||||
added_version = False
|
added_version = False
|
||||||
|
Loading…
Reference in New Issue
Block a user