From 7ea328659f6bbaff33319427ba7c6321cc33a637 Mon Sep 17 00:00:00 2001 From: Matthew LeGendre Date: Mon, 20 Apr 2015 13:27:03 -0700 Subject: Record package repo origins in .spec files --- lib/spack/spack/packages.py | 35 ++++++++++++++++++++--------------- lib/spack/spack/repo_loader.py | 2 +- lib/spack/spack/spec.py | 29 +++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/packages.py b/lib/spack/spack/packages.py index 79dbd60703..48705948b7 100644 --- a/lib/spack/spack/packages.py +++ b/lib/spack/spack/packages.py @@ -73,12 +73,12 @@ class PackageDB(object): dir1 = list(dups)[0][1] dir2 = dict(s)[reponame] tty.die("Package repo %s in directory %s has the same name as the " - "repo in directory %s" % + "repo in directory %s" % (reponame, dir1, dir2)) # For each repo, create a RepoLoader self.repo_loaders = dict([(r[0], RepoLoader(r[0], r[1])) for r in self.repos]) - + self.instances = {} self.provider_index = None @@ -87,13 +87,13 @@ class PackageDB(object): """For a packagerepo directory, read the repo name from the dir/reponame file""" path = os.path.join(dir, 'reponame') - try: + try: with closing(open(path, 'r')) as reponame_file: - name = reponame_file.read().lstrip().rstrip() + name = reponame_file.read().lstrip().rstrip() if not re.match(r'[a-zA-Z][a-zA-Z0-9]+', name): tty.die("Package repo name '%s', read from %s, is an invalid name. " "Repo names must began with a letter and only contain letters " - "and numbers." % (name, path)) + "and numbers." % (name, path)) return name except exceptions.IOError, e: tty.die("Could not read from package repo name file %s" % path) @@ -107,7 +107,7 @@ class PackageDB(object): dir_string = config.get('packagerepo', 'directories') return dir_string.split(':') - + @_autospec def get(self, spec, **kwargs): if spec.virtual: @@ -118,7 +118,7 @@ class PackageDB(object): del self.instances[spec] if not spec in self.instances: - package_class = self.get_class_for_package_name(spec.name) + package_class = self.get_class_for_package_name(spec.name, spec.repo) try: copy = spec.copy() self.instances[copy] = package_class(copy) @@ -191,7 +191,7 @@ class PackageDB(object): path = join_path(pkgrepo[1], pkg_name) if os.path.exists(path): return (pkgrepo[0], path) - + repo_to_add_to = roots[-1] return (repo_to_add_to[0], join_path(repo_to_add_to[1], pkg_name)) @@ -259,7 +259,7 @@ class PackageDB(object): if os.path.isfile(pkg_file): all_packages.add(pkg_name) all_package_names = list(all_packages) - all_package_names.sort() + all_package_names.sort() return all_package_names @@ -275,12 +275,12 @@ class PackageDB(object): @memoized - def get_class_for_package_name(self, pkg_name): + def get_class_for_package_name(self, pkg_name, reponame = None): """Get an instance of the class for a particular package.""" - repo = self.repo_for_package_name(pkg_name) - module_name = imported_packages_module + '.' + repo[0] + '.' + pkg_name + (reponame, repodir) = self.repo_for_package_name(pkg_name, reponame) + module_name = imported_packages_module + '.' + reponame + '.' + pkg_name - module = self.repo_loaders[repo[0]].get_module(pkg_name) + module = self.repo_loaders[reponame].get_module(pkg_name) class_name = mod_to_class(pkg_name) cls = getattr(module, class_name) @@ -292,8 +292,13 @@ class PackageDB(object): class UnknownPackageError(spack.error.SpackError): """Raised when we encounter a package spack doesn't have.""" - def __init__(self, name): - super(UnknownPackageError, self).__init__("Package '%s' not found." % name) + def __init__(self, name, repo=None): + msg = None + if repo: + msg = "Package %s not found in packagerepo %s." % (name, repo) + else: + msg = "Package %s not found." % name + super(UnknownPackageError, self).__init__(msg) self.name = name diff --git a/lib/spack/spack/repo_loader.py b/lib/spack/spack/repo_loader.py index 57c19a6c28..6eaa1eead2 100644 --- a/lib/spack/spack/repo_loader.py +++ b/lib/spack/spack/repo_loader.py @@ -100,7 +100,7 @@ class RepoLoader(types.ModuleType): if not os.access(file_path, os.R_OK): tty.die("Cannot read '%s'!" % file_path) else: - raise spack.packages.UnknownPackageError(pkg_name) + raise spack.packages.UnknownPackageError(pkg_name, self.reponame if self.reponame != 'original' else None) try: module_name = imported_packages_module + '.' + self.reponame + '.' + pkg_name diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index e1fbb84423..972ba9ccbb 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -112,6 +112,7 @@ from spack.version import * from spack.util.string import * from spack.util.prefix import Prefix from spack.virtual import ProviderIndex +from spack.repo_loader import imported_packages_module # Valid pattern for an identifier in Spack identifier_re = r'\w[\w-]*' @@ -412,6 +413,7 @@ class Spec(object): self.dependencies = other.dependencies self.variants = other.variants self.variants.spec = self + self.repo = other.repo # Specs are by default not assumed to be normal, but in some # cases we've read them from a file want to assume normal. @@ -1355,6 +1357,7 @@ class Spec(object): self.dependencies = DependencyMap() self.variants = other.variants.copy() self.variants.spec = self + self.repo = other.repo # If we copy dependencies, preserve DAG structure in the new spec if kwargs.get('deps', True): @@ -1503,6 +1506,7 @@ class Spec(object): in the format string. The format strings you can provide are:: $_ Package name + $. Long package name $@ Version $% Compiler $%@ Compiler & compiler version @@ -1550,6 +1554,9 @@ class Spec(object): if c == '_': out.write(fmt % self.name) + elif c == '.': + longname = '%s.%s.%s' % (imported_packages_module, self.repo, self.name) if self.repo else self.name + out.write(fmt % longname) elif c == '@': if self.versions and self.versions != _any_version: write(fmt % (c + str(self.versions)), c) @@ -1698,17 +1705,29 @@ class SpecParser(spack.parse.Parser): def spec(self): """Parse a spec out of the input. If a spec is supplied, then initialize and return it instead of creating a new one.""" - self.check_identifier() + + spec_name = None + spec_repo = None + if self.token.value.startswith(imported_packages_module): + lst = self.token.value.split('.') + spec_name = lst[-1] + spec_repo = lst[-2] + else: + spec_name = self.token.value + (spec_repo, repodir) = spack.db.repo_for_package_name(spec_name) + + self.check_identifier(spec_name) # This will init the spec without calling __init__. spec = Spec.__new__(Spec) - spec.name = self.token.value + spec.name = spec_name spec.versions = VersionList() spec.variants = VariantMap(spec) spec.architecture = None spec.compiler = None spec.dependents = DependencyMap() spec.dependencies = DependencyMap() + spec.repo = spec_repo spec._normal = False spec._concrete = False @@ -1802,12 +1821,14 @@ class SpecParser(spack.parse.Parser): return compiler - def check_identifier(self): + def check_identifier(self, id=None): """The only identifiers that can contain '.' are versions, but version ids are context-sensitive so we have to check on a case-by-case basis. Call this if we detect a version id where it shouldn't be. """ - if '.' in self.token.value: + if not id: + id = self.token.value + if '.' in id: self.last_token_error("Identifier cannot contain '.'") -- cgit v1.2.3-70-g09d2