summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/basic_usage.rst2
-rw-r--r--lib/spack/docs/getting_started.rst2
-rwxr-xr-xlib/spack/env/cc8
l---------lib/spack/env/pgi/case-insensitive/pgCC1
l---------lib/spack/env/pgi/pgc++ (renamed from lib/spack/env/pgi/pgf77)0
l---------lib/spack/env/pgi/pgfortran (renamed from lib/spack/env/pgi/pgf90)0
-rw-r--r--lib/spack/llnl/util/filesystem.py11
-rw-r--r--lib/spack/spack/cmd/checksum.py19
-rw-r--r--lib/spack/spack/cmd/compiler.py6
-rw-r--r--lib/spack/spack/cmd/create.py10
-rw-r--r--lib/spack/spack/cmd/mirror.py4
-rw-r--r--lib/spack/spack/cmd/module.py6
-rw-r--r--lib/spack/spack/cmd/repo.py60
-rw-r--r--lib/spack/spack/compiler.py4
-rw-r--r--lib/spack/spack/compilers/pgi.py18
-rw-r--r--lib/spack/spack/config.py6
-rw-r--r--lib/spack/spack/database.py2
-rw-r--r--lib/spack/spack/directives.py10
-rw-r--r--lib/spack/spack/directory_layout.py18
-rw-r--r--lib/spack/spack/fetch_strategy.py16
-rw-r--r--lib/spack/spack/mirror.py4
-rw-r--r--lib/spack/spack/modules.py2
-rw-r--r--lib/spack/spack/multimethod.py9
-rw-r--r--lib/spack/spack/package.py84
-rw-r--r--lib/spack/spack/repository.py105
-rw-r--r--lib/spack/spack/resource.py2
-rw-r--r--lib/spack/spack/stage.py4
-rw-r--r--lib/spack/spack/test/namespace_trie.py2
-rw-r--r--lib/spack/spack/test/tally_plugin.py8
-rw-r--r--lib/spack/spack/util/environment.py7
-rw-r--r--lib/spack/spack/util/web.py6
31 files changed, 291 insertions, 145 deletions
diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst
index 0578f0c8db..f94ac3d2ba 100644
--- a/lib/spack/docs/basic_usage.rst
+++ b/lib/spack/docs/basic_usage.rst
@@ -896,7 +896,7 @@ Or, similarly with modules, you could type:
$ spack load mpich %gcc@4.4.7
These commands will add appropriate directories to your ``PATH``,
-``MANPATH``, and ``LD_LIBRARY_PATH``. When you no longer want to use
+``MANPATH``, ``CPATH``, and ``LD_LIBRARY_PATH``. When you no longer want to use
a package, you can type unload or unuse similarly:
.. code-block:: sh
diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst
index 67ca18e71a..2c5b68ea65 100644
--- a/lib/spack/docs/getting_started.rst
+++ b/lib/spack/docs/getting_started.rst
@@ -22,7 +22,7 @@ go:
$ spack install libelf
For a richer experience, use Spack's `shell support
-<http://llnl.github.io/spack/basic_usage.html#environment-modules>`_:
+<http://software.llnl.gov/spack/basic_usage.html#environment-modules>`_:
.. code-block:: sh
diff --git a/lib/spack/env/cc b/lib/spack/env/cc
index aacba996b3..b8b6c86e01 100755
--- a/lib/spack/env/cc
+++ b/lib/spack/env/cc
@@ -90,15 +90,15 @@ case "$command" in
command="$SPACK_CC"
language="C"
;;
- c++|CC|g++|clang++|icpc|pgCC|xlc++)
+ c++|CC|g++|clang++|icpc|pgc++|xlc++)
command="$SPACK_CXX"
language="C++"
;;
- f90|fc|f95|gfortran|ifort|pgf90|xlf90|nagfor)
+ f90|fc|f95|gfortran|ifort|pgfortran|xlf90|nagfor)
command="$SPACK_FC"
language="Fortran 90"
;;
- f77|gfortran|ifort|pgf77|xlf|nagfor)
+ f77|gfortran|ifort|pgfortran|xlf|nagfor)
command="$SPACK_F77"
language="Fortran 77"
;;
@@ -130,7 +130,7 @@ if [ -z "$mode" ]; then
done
fi
-# Dump the version and exist if we're in testing mode.
+# Dump the version and exit if we're in testing mode.
if [ "$SPACK_TEST_COMMAND" = "dump-mode" ]; then
echo "$mode"
exit
diff --git a/lib/spack/env/pgi/case-insensitive/pgCC b/lib/spack/env/pgi/case-insensitive/pgCC
deleted file mode 120000
index e2deb67f3b..0000000000
--- a/lib/spack/env/pgi/case-insensitive/pgCC
+++ /dev/null
@@ -1 +0,0 @@
-../../cc \ No newline at end of file
diff --git a/lib/spack/env/pgi/pgf77 b/lib/spack/env/pgi/pgc++
index 82c2b8e90a..82c2b8e90a 120000
--- a/lib/spack/env/pgi/pgf77
+++ b/lib/spack/env/pgi/pgc++
diff --git a/lib/spack/env/pgi/pgf90 b/lib/spack/env/pgi/pgfortran
index 82c2b8e90a..82c2b8e90a 120000
--- a/lib/spack/env/pgi/pgf90
+++ b/lib/spack/env/pgi/pgfortran
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
index 24cfbfde71..da3cf96050 100644
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -152,15 +152,20 @@ def set_install_permissions(path):
def copy_mode(src, dest):
src_mode = os.stat(src).st_mode
dest_mode = os.stat(dest).st_mode
- if src_mode | stat.S_IXUSR: dest_mode |= stat.S_IXUSR
- if src_mode | stat.S_IXGRP: dest_mode |= stat.S_IXGRP
- if src_mode | stat.S_IXOTH: dest_mode |= stat.S_IXOTH
+ if src_mode & stat.S_IXUSR: dest_mode |= stat.S_IXUSR
+ if src_mode & stat.S_IXGRP: dest_mode |= stat.S_IXGRP
+ if src_mode & stat.S_IXOTH: dest_mode |= stat.S_IXOTH
os.chmod(dest, dest_mode)
def install(src, dest):
"""Manually install a file to a particular location."""
tty.debug("Installing %s to %s" % (src, dest))
+
+ # Expand dsst to its eventual full path if it is a directory.
+ if os.path.isdir(dest):
+ dest = join_path(dest, os.path.basename(src))
+
shutil.copy(src, dest)
set_install_permissions(dest)
copy_mode(src, dest)
diff --git a/lib/spack/spack/cmd/checksum.py b/lib/spack/spack/cmd/checksum.py
index b1ad89dbb8..966ff9a5e9 100644
--- a/lib/spack/spack/cmd/checksum.py
+++ b/lib/spack/spack/cmd/checksum.py
@@ -58,24 +58,29 @@ def get_checksums(versions, urls, **kwargs):
tty.msg("Downloading...")
hashes = []
- for i, (url, version) in enumerate(zip(urls, versions)):
+ i = 0
+ for url, version in zip(urls, versions):
stage = Stage(url)
try:
stage.fetch()
if i == 0 and first_stage_function:
first_stage_function(stage)
- hashes.append(
- spack.util.crypto.checksum(hashlib.md5, stage.archive_file))
+ hashes.append((version,
+ spack.util.crypto.checksum(hashlib.md5, stage.archive_file)))
except FailedDownloadError, e:
tty.msg("Failed to fetch %s" % url)
continue
+ except Exception, e:
+ tty.msg('Something failed on %s, skipping.\n (%s)' % (url, e))
+ continue
finally:
if not keep_stage:
stage.destroy()
+ i += 1
- return zip(versions, hashes)
+ return hashes
@@ -95,11 +100,11 @@ def checksum(parser, args):
else:
versions = pkg.fetch_remote_versions()
if not versions:
- tty.die("Could not fetch any versions for %s." % pkg.name)
+ tty.die("Could not fetch any versions for %s" % pkg.name)
sorted_versions = sorted(versions, reverse=True)
- tty.msg("Found %s versions of %s." % (len(versions), pkg.name),
+ tty.msg("Found %s versions of %s" % (len(versions), pkg.name),
*spack.cmd.elide_list(
["%-10s%s" % (v, versions[v]) for v in sorted_versions]))
print
@@ -116,7 +121,7 @@ def checksum(parser, args):
keep_stage=args.keep_stage)
if not version_hashes:
- tty.die("Could not fetch any versions for %s." % pkg.name)
+ tty.die("Could not fetch any versions for %s" % pkg.name)
version_lines = [" version('%s', '%s')" % (v, h) for v, h in version_hashes]
tty.msg("Checksummed new versions of %s:" % pkg.name, *version_lines)
diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py
index 75b51f6b49..3e58e82184 100644
--- a/lib/spack/spack/cmd/compiler.py
+++ b/lib/spack/spack/cmd/compiler.py
@@ -96,7 +96,7 @@ def compiler_remove(args):
compilers = spack.compilers.compilers_for_spec(cspec, scope=args.scope)
if not compilers:
- tty.die("No compilers match spec %s." % cspec)
+ tty.die("No compilers match spec %s" % cspec)
elif not args.all and len(compilers) > 1:
tty.error("Multiple compilers match spec %s. Choose one:" % cspec)
colify(reversed(sorted([c.spec for c in compilers])), indent=4)
@@ -105,7 +105,7 @@ def compiler_remove(args):
for compiler in compilers:
spack.compilers.remove_compiler_from_config(compiler.spec, scope=args.scope)
- tty.msg("Removed compiler %s." % compiler.spec)
+ tty.msg("Removed compiler %s" % compiler.spec)
def compiler_info(args):
@@ -114,7 +114,7 @@ def compiler_info(args):
compilers = spack.compilers.compilers_for_spec(cspec, scope=args.scope)
if not compilers:
- tty.error("No compilers match spec %s." % cspec)
+ tty.error("No compilers match spec %s" % cspec)
else:
for c in compilers:
print str(c.spec) + ":"
diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py
index 6809209046..4564143f83 100644
--- a/lib/spack/spack/cmd/create.py
+++ b/lib/spack/spack/cmd/create.py
@@ -156,7 +156,7 @@ def guess_name_and_version(url, args):
# Try to deduce name and version of the new package from the URL
version = spack.url.parse_version(url)
if not version:
- tty.die("Couldn't guess a version string from %s." % url)
+ tty.die("Couldn't guess a version string from %s" % url)
# Try to guess a name. If it doesn't work, allow the user to override.
if args.alternate_name:
@@ -189,7 +189,7 @@ def find_repository(spec, args):
try:
repo = Repo(repo_path)
if spec.namespace and spec.namespace != repo.namespace:
- tty.die("Can't create package with namespace %s in repo with namespace %s."
+ tty.die("Can't create package with namespace %s in repo with namespace %s"
% (spec.namespace, repo.namespace))
except RepoError as e:
tty.die(str(e))
@@ -252,7 +252,7 @@ def create(parser, args):
name = spec.name # factors out namespace, if any
repo = find_repository(spec, args)
- tty.msg("This looks like a URL for %s version %s." % (name, version))
+ tty.msg("This looks like a URL for %s version %s" % (name, version))
tty.msg("Creating template for package %s" % name)
# Fetch tarballs (prompting user if necessary)
@@ -266,7 +266,7 @@ def create(parser, args):
keep_stage=args.keep_stage)
if not ver_hash_tuples:
- tty.die("Could not fetch any tarballs for %s." % name)
+ tty.die("Could not fetch any tarballs for %s" % name)
# Prepend 'py-' to python package names, by convention.
if guesser.build_system == 'python':
@@ -291,4 +291,4 @@ def create(parser, args):
# If everything checks out, go ahead and edit.
spack.editor(pkg_path)
- tty.msg("Created package %s." % pkg_path)
+ tty.msg("Created package %s" % pkg_path)
diff --git a/lib/spack/spack/cmd/mirror.py b/lib/spack/spack/cmd/mirror.py
index 8e9438c1a3..fcd15a6a90 100644
--- a/lib/spack/spack/cmd/mirror.py
+++ b/lib/spack/spack/cmd/mirror.py
@@ -126,7 +126,7 @@ def mirror_remove(args):
old_value = mirrors.pop(name)
spack.config.update_config('mirrors', mirrors, scope=args.scope)
- tty.msg("Removed mirror %s with url %s." % (name, old_value))
+ tty.msg("Removed mirror %s with url %s" % (name, old_value))
def mirror_list(args):
@@ -203,7 +203,7 @@ def mirror_create(args):
verb = "updated" if existed else "created"
tty.msg(
- "Successfully %s mirror in %s." % (verb, directory),
+ "Successfully %s mirror in %s" % (verb, directory),
"Archive stats:",
" %-4d already present" % p,
" %-4d added" % m,
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index a5a9570eb5..1d6867c1d9 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -58,7 +58,7 @@ def module_find(mtype, spec_array):
should type to use that package's module.
"""
if mtype not in module_types:
- tty.die("Invalid module type: '%s'. Options are %s." % (mtype, comma_or(module_types)))
+ tty.die("Invalid module type: '%s'. Options are %s" % (mtype, comma_or(module_types)))
specs = spack.cmd.parse_specs(spec_array)
if len(specs) > 1:
@@ -78,7 +78,7 @@ def module_find(mtype, spec_array):
mt = module_types[mtype]
mod = mt(specs[0])
if not os.path.isfile(mod.file_name):
- tty.die("No %s module is installed for %s." % (mtype, spec))
+ tty.die("No %s module is installed for %s" % (mtype, spec))
print mod.use_name
@@ -94,7 +94,7 @@ def module_refresh():
shutil.rmtree(cls.path, ignore_errors=False)
mkdirp(cls.path)
for spec in specs:
- tty.debug(" Writing file for %s." % spec)
+ tty.debug(" Writing file for %s" % spec)
cls(spec).write()
diff --git a/lib/spack/spack/cmd/repo.py b/lib/spack/spack/cmd/repo.py
index 34c755fb67..87c782000f 100644
--- a/lib/spack/spack/cmd/repo.py
+++ b/lib/spack/spack/cmd/repo.py
@@ -6,7 +6,7 @@
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
-# For details, see https://llnl.github.io/spack
+# For details, see https://software.llnl.gov/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
@@ -74,51 +74,7 @@ def setup_parser(subparser):
def repo_create(args):
"""Create a new package repository."""
- root = canonicalize_path(args.directory)
- namespace = args.namespace
-
- if not args.namespace:
- namespace = os.path.basename(root)
-
- if not re.match(r'\w[\.\w-]*', namespace):
- tty.die("'%s' is not a valid namespace." % namespace)
-
- existed = False
- if os.path.exists(root):
- if os.path.isfile(root):
- tty.die('File %s already exists and is not a directory' % root)
- elif os.path.isdir(root):
- if not os.access(root, os.R_OK | os.W_OK):
- tty.die('Cannot create new repo in %s: cannot access directory.' % root)
- if os.listdir(root):
- tty.die('Cannot create new repo in %s: directory is not empty.' % root)
- existed = True
-
- full_path = os.path.realpath(root)
- parent = os.path.dirname(full_path)
- if not os.access(parent, os.R_OK | os.W_OK):
- tty.die("Cannot create repository in %s: can't access parent!" % root)
-
- try:
- config_path = os.path.join(root, repo_config_name)
- packages_path = os.path.join(root, packages_dir_name)
-
- mkdirp(packages_path)
- with open(config_path, 'w') as config:
- config.write("repo:\n")
- config.write(" namespace: '%s'\n" % namespace)
-
- except (IOError, OSError) as e:
- tty.die('Failed to create new repository in %s.' % root,
- "Caused by %s: %s" % (type(e), e))
-
- # try to clean up.
- if existed:
- shutil.rmtree(config_path, ignore_errors=True)
- shutil.rmtree(packages_path, ignore_errors=True)
- else:
- shutil.rmtree(root, ignore_errors=True)
-
+ full_path, namespace = create_repo(args.directory, args.namespace)
tty.msg("Created repo with namespace '%s'." % namespace)
tty.msg("To register it with spack, run this command:",
'spack repo add %s' % full_path)
@@ -133,11 +89,11 @@ def repo_add(args):
# check if the path exists
if not os.path.exists(canon_path):
- tty.die("No such file or directory: '%s'." % path)
+ tty.die("No such file or directory: %s" % path)
# Make sure the path is a directory.
if not os.path.isdir(canon_path):
- tty.die("Not a Spack repository: '%s'." % path)
+ tty.die("Not a Spack repository: %s" % path)
# Make sure it's actually a spack repository by constructing it.
repo = Repo(canon_path)
@@ -147,7 +103,7 @@ def repo_add(args):
if not repos: repos = []
if repo.root in repos or path in repos:
- tty.die("Repository is already registered with Spack: '%s'" % path)
+ tty.die("Repository is already registered with Spack: %s" % path)
repos.insert(0, canon_path)
spack.config.update_config('repos', repos, args.scope)
@@ -166,7 +122,7 @@ def repo_remove(args):
if canon_path == repo_canon_path:
repos.remove(repo_path)
spack.config.update_config('repos', repos, args.scope)
- tty.msg("Removed repository '%s'." % repo_path)
+ tty.msg("Removed repository %s" % repo_path)
return
# If it is a namespace, remove corresponding repo
@@ -176,13 +132,13 @@ def repo_remove(args):
if repo.namespace == path_or_namespace:
repos.remove(path)
spack.config.update_config('repos', repos, args.scope)
- tty.msg("Removed repository '%s' with namespace %s."
+ tty.msg("Removed repository %s with namespace '%s'."
% (repo.root, repo.namespace))
return
except RepoError as e:
continue
- tty.die("No repository with path or namespace: '%s'"
+ tty.die("No repository with path or namespace: %s"
% path_or_namespace)
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
index 12c02e0ea2..d38c0b00b1 100644
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -256,12 +256,12 @@ class Compiler(object):
def __repr__(self):
- """Return a string represntation of the compiler toolchain."""
+ """Return a string representation of the compiler toolchain."""
return self.__str__()
def __str__(self):
- """Return a string represntation of the compiler toolchain."""
+ """Return a string representation of the compiler toolchain."""
return "%s(%s)" % (
self.name, '\n '.join((str(s) for s in (self.cc, self.cxx, self.f77, self.fc))))
diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py
index 9ac74cfbdb..c6a1078bd9 100644
--- a/lib/spack/spack/compilers/pgi.py
+++ b/lib/spack/spack/compilers/pgi.py
@@ -29,28 +29,28 @@ class Pgi(Compiler):
cc_names = ['pgcc']
# Subclasses use possible names of C++ compiler
- cxx_names = ['pgCC']
+ cxx_names = ['pgc++', 'pgCC']
# Subclasses use possible names of Fortran 77 compiler
- f77_names = ['pgf77']
+ f77_names = ['pgfortran', 'pgf77']
# Subclasses use possible names of Fortran 90 compiler
- fc_names = ['pgf95', 'pgf90']
+ fc_names = ['pgfortran', 'pgf95', 'pgf90']
# Named wrapper links within spack.build_env_path
link_paths = { 'cc' : 'pgi/pgcc',
- 'cxx' : 'pgi/case-insensitive/pgCC',
- 'f77' : 'pgi/pgf77',
- 'fc' : 'pgi/pgf90' }
+ 'cxx' : 'pgi/pgc++',
+ 'f77' : 'pgi/pgfortran',
+ 'fc' : 'pgi/pgfortran' }
@classmethod
def default_version(cls, comp):
"""The '-V' option works for all the PGI compilers.
Output looks like this::
- pgf95 10.2-0 64-bit target on x86-64 Linux -tp nehalem-64
- Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
- Copyright 2000-2010, STMicroelectronics, Inc. All Rights Reserved.
+ pgcc 15.10-0 64-bit target on x86-64 Linux -tp sandybridge
+ The Portland Group - PGI Compilers and Tools
+ Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
"""
return get_compiler_version(
comp, '-V', r'pg[^ ]* ([^ ]+) \d\d\d?-bit target')
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py
index 6fecde9980..576a5afa2e 100644
--- a/lib/spack/spack/config.py
+++ b/lib/spack/spack/config.py
@@ -205,7 +205,7 @@ config_scopes = OrderedDict()
def validate_section_name(section):
"""Raise a ValueError if the section is not a valid section."""
if section not in section_schemas:
- raise ValueError("Invalid config section: '%s'. Options are %s."
+ raise ValueError("Invalid config section: '%s'. Options are %s"
% (section, section_schemas))
@@ -335,7 +335,7 @@ def validate_scope(scope):
return config_scopes[scope]
else:
- raise ValueError("Invalid config scope: '%s'. Must be one of %s."
+ raise ValueError("Invalid config scope: '%s'. Must be one of %s"
% (scope, config_scopes.keys()))
@@ -350,7 +350,7 @@ def _read_config_file(filename, schema):
"Invlaid configuration. %s exists but is not a file." % filename)
elif not os.access(filename, os.R_OK):
- raise ConfigFileError("Config file is not readable: %s." % filename)
+ raise ConfigFileError("Config file is not readable: %s" % filename)
try:
tty.debug("Reading config file %s" % filename)
diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py
index 9cbe7de44a..089d29325e 100644
--- a/lib/spack/spack/database.py
+++ b/lib/spack/spack/database.py
@@ -330,7 +330,7 @@ class Database(object):
found = rec.ref_count
if not expected == found:
raise AssertionError(
- "Invalid ref_count: %s: %d (expected %d), in DB %s."
+ "Invalid ref_count: %s: %d (expected %d), in DB %s"
% (key, found, expected, self._index_path))
diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py
index 5745adce63..61cd303012 100644
--- a/lib/spack/spack/directives.py
+++ b/lib/spack/spack/directives.py
@@ -125,7 +125,7 @@ class directive(object):
dicts = (dicts,)
elif type(dicts) not in (list, tuple):
raise TypeError(
- "dicts arg must be list, tuple, or string. Found %s."
+ "dicts arg must be list, tuple, or string. Found %s"
% type(dicts))
self.dicts = dicts
@@ -174,7 +174,11 @@ def version(pkg, ver, checksum=None, **kwargs):
def _depends_on(pkg, spec, when=None):
- if when is None:
+ # If when is False do nothing
+ if when is False:
+ return
+ # If when is None or True make sure the condition is always satisfied
+ if when is None or when is True:
when = pkg.name
when_spec = parse_anonymous_spec(when, pkg.name)
@@ -313,5 +317,5 @@ class CircularReferenceError(DirectiveError):
def __init__(self, directive, package):
super(CircularReferenceError, self).__init__(
directive,
- "Package '%s' cannot pass itself to %s." % (package, directive))
+ "Package '%s' cannot pass itself to %s" % (package, directive))
self.package = package
diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py
index 3e416a6a1f..08c23627f4 100644
--- a/lib/spack/spack/directory_layout.py
+++ b/lib/spack/spack/directory_layout.py
@@ -173,7 +173,9 @@ class YamlDirectoryLayout(DirectoryLayout):
self.spec_file_name = 'spec.yaml'
self.extension_file_name = 'extensions.yaml'
- self.build_log_name = 'build.out' # TODO: use config file.
+ self.build_log_name = 'build.out' # build log.
+ self.build_env_name = 'build.env' # build environment
+ self.packages_dir = 'repos' # archive of package.py files
# Cache of already written/read extension maps.
self._extension_maps = {}
@@ -231,6 +233,16 @@ class YamlDirectoryLayout(DirectoryLayout):
self.build_log_name)
+ def build_env_path(self, spec):
+ return join_path(self.path_for_spec(spec), self.metadata_dir,
+ self.build_env_name)
+
+
+ def build_packages_path(self, spec):
+ return join_path(self.path_for_spec(spec), self.metadata_dir,
+ self.packages_dir)
+
+
def create_install_directory(self, spec):
_check_concrete(spec)
@@ -323,7 +335,7 @@ class YamlDirectoryLayout(DirectoryLayout):
if not dag_hash in by_hash:
raise InvalidExtensionSpecError(
- "Spec %s not found in %s." % (dag_hash, prefix))
+ "Spec %s not found in %s" % (dag_hash, prefix))
ext_spec = by_hash[dag_hash]
if not prefix == ext_spec.prefix:
@@ -438,7 +450,7 @@ class ExtensionConflictError(DirectoryLayoutError):
"""Raised when an extension is added to a package that already has it."""
def __init__(self, spec, ext_spec, conflict):
super(ExtensionConflictError, self).__init__(
- "%s cannot be installed in %s because it conflicts with %s."% (
+ "%s cannot be installed in %s because it conflicts with %s"% (
ext_spec.short_spec, spec.short_spec, conflict.short_spec))
diff --git a/lib/spack/spack/fetch_strategy.py b/lib/spack/spack/fetch_strategy.py
index 83a2dbb59c..ec17cb97f1 100644
--- a/lib/spack/spack/fetch_strategy.py
+++ b/lib/spack/spack/fetch_strategy.py
@@ -153,7 +153,7 @@ class URLFetchStrategy(FetchStrategy):
self.stage.chdir()
if self.archive_file:
- tty.msg("Already downloaded %s." % self.archive_file)
+ tty.msg("Already downloaded %s" % self.archive_file)
return
tty.msg("Trying to fetch from %s" % self.url)
@@ -275,8 +275,8 @@ class URLFetchStrategy(FetchStrategy):
checker = crypto.Checker(self.digest)
if not checker.check(self.archive_file):
raise ChecksumError(
- "%s checksum failed for %s." % (checker.hash_name, self.archive_file),
- "Expected %s but got %s." % (self.digest, checker.sum))
+ "%s checksum failed for %s" % (checker.hash_name, self.archive_file),
+ "Expected %s but got %s" % (self.digest, checker.sum))
@_needs_stage
def reset(self):
@@ -312,7 +312,7 @@ class VCSFetchStrategy(FetchStrategy):
# Ensure that there's only one of the rev_types
if sum(k in kwargs for k in rev_types) > 1:
raise FetchStrategyError(
- "Supply only one of %s to fetch with %s." % (
+ "Supply only one of %s to fetch with %s" % (
comma_or(rev_types), name))
# Set attributes for each rev type.
@@ -321,7 +321,7 @@ class VCSFetchStrategy(FetchStrategy):
@_needs_stage
def check(self):
- tty.msg("No checksum needed when fetching with %s." % self.name)
+ tty.msg("No checksum needed when fetching with %s" % self.name)
@_needs_stage
def expand(self):
@@ -395,7 +395,7 @@ class GitFetchStrategy(VCSFetchStrategy):
self.stage.chdir()
if self.stage.source_path:
- tty.msg("Already fetched %s." % self.stage.source_path)
+ tty.msg("Already fetched %s" % self.stage.source_path)
return
args = []
@@ -505,7 +505,7 @@ class SvnFetchStrategy(VCSFetchStrategy):
self.stage.chdir()
if self.stage.source_path:
- tty.msg("Already fetched %s." % self.stage.source_path)
+ tty.msg("Already fetched %s" % self.stage.source_path)
return
tty.msg("Trying to check out svn repository: %s" % self.url)
@@ -584,7 +584,7 @@ class HgFetchStrategy(VCSFetchStrategy):
self.stage.chdir()
if self.stage.source_path:
- tty.msg("Already fetched %s." % self.stage.source_path)
+ tty.msg("Already fetched %s" % self.stage.source_path)
return
args = []
diff --git a/lib/spack/spack/mirror.py b/lib/spack/spack/mirror.py
index fa29e20803..58e31c2c7b 100644
--- a/lib/spack/spack/mirror.py
+++ b/lib/spack/spack/mirror.py
@@ -73,7 +73,7 @@ def get_matching_versions(specs, **kwargs):
# Skip any package that has no known versions.
if not pkg.versions:
- tty.msg("No safe (checksummed) versions for package %s." % pkg.name)
+ tty.msg("No safe (checksummed) versions for package %s" % pkg.name)
continue
num_versions = kwargs.get('num_versions', 0)
@@ -203,7 +203,7 @@ def create(path, specs, **kwargs):
if spack.debug:
sys.excepthook(*sys.exc_info())
else:
- tty.warn("Error while fetching %s." % spec.format('$_$@'), e.message)
+ tty.warn("Error while fetching %s" % spec.format('$_$@'), e.message)
error.append(spec)
finally:
pkg.stage.destroy()
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index c834763564..c27043db8c 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -33,6 +33,7 @@ number of directories to be appended to paths in the user's environment:
* /bin directories to be appended to PATH
* /lib* directories for LD_LIBRARY_PATH
+ * /include directories for CPATH
* /man* and /share/man* directories for MANPATH
* the package prefix for CMAKE_PREFIX_PATH
@@ -121,6 +122,7 @@ class EnvModule(object):
('LIBRARY_PATH', self.spec.prefix.lib64),
('LD_LIBRARY_PATH', self.spec.prefix.lib),
('LD_LIBRARY_PATH', self.spec.prefix.lib64),
+ ('CPATH', self.spec.prefix.include),
('PKG_CONFIG_PATH', join_path(self.spec.prefix.lib, 'pkgconfig')),
('PKG_CONFIG_PATH', join_path(self.spec.prefix.lib64, 'pkgconfig'))]:
diff --git a/lib/spack/spack/multimethod.py b/lib/spack/spack/multimethod.py
index df9b9b2ab1..51c6a8e89d 100644
--- a/lib/spack/spack/multimethod.py
+++ b/lib/spack/spack/multimethod.py
@@ -193,10 +193,11 @@ class when(object):
platform-specific versions. There's not much we can do to get
around this because of the way decorators work.
"""
-class when(object):
def __init__(self, spec):
pkg = get_calling_module_name()
- self.spec = parse_anonymous_spec(spec, pkg)
+ if spec is True:
+ spec = pkg
+ self.spec = parse_anonymous_spec(spec, pkg) if spec is not False else None
def __call__(self, method):
# Get the first definition of the method in the calling scope
@@ -207,7 +208,9 @@ class when(object):
if not type(original_method) == SpecMultiMethod:
original_method = SpecMultiMethod(original_method)
- original_method.register(self.spec, method)
+ if self.spec is not None:
+ original_method.register(self.spec, method)
+
return original_method
diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py
index 8019b29cba..fb96f61de9 100644
--- a/lib/spack/spack/package.py
+++ b/lib/spack/spack/package.py
@@ -58,6 +58,7 @@ import spack.compilers
import spack.mirror
import spack.hooks
import spack.directives
+import spack.repository
import spack.build_environment
import spack.url
import spack.util.web
@@ -66,6 +67,7 @@ from spack.version import *
from spack.stage import Stage, ResourceStage, StageComposite
from spack.util.compression import allowed_archive, extension
from spack.util.executable import ProcessError
+from spack.util.environment import dump_environment
"""Allowed URL schemes for spack packages."""
_ALLOWED_URL_SCHEMES = ["http", "https", "ftp", "file", "git"]
@@ -501,6 +503,7 @@ class Package(object):
self._fetcher = self._make_fetcher()
return self._fetcher
+
@fetcher.setter
def fetcher(self, f):
self._fetcher = f
@@ -685,7 +688,7 @@ class Package(object):
if not ignore_checksum:
raise FetchError(
- "Will not fetch %s." % self.spec.format('$_$@'), checksum_msg)
+ "Will not fetch %s" % self.spec.format('$_$@'), checksum_msg)
self.stage.fetch(mirror_only)
@@ -719,7 +722,7 @@ class Package(object):
# If there are no patches, note it.
if not self.patches and not has_patch_fun:
- tty.msg("No patches needed for %s." % self.name)
+ tty.msg("No patches needed for %s" % self.name)
return
# Construct paths to special files in the archive dir used to
@@ -742,7 +745,7 @@ class Package(object):
tty.msg("Already patched %s" % self.name)
return
elif os.path.isfile(no_patches_file):
- tty.msg("No patches needed for %s." % self.name)
+ tty.msg("No patches needed for %s" % self.name)
return
# Apply all the patches for specs that match this one
@@ -763,10 +766,10 @@ class Package(object):
if has_patch_fun:
try:
self.patch()
- tty.msg("Ran patch() for %s." % self.name)
+ tty.msg("Ran patch() for %s" % self.name)
patched = True
except:
- tty.msg("patch() function failed for %s." % self.name)
+ tty.msg("patch() function failed for %s" % self.name)
touch(bad_file)
raise
@@ -835,7 +838,7 @@ class Package(object):
raise ValueError("Can only install concrete packages.")
if os.path.exists(self.prefix):
- tty.msg("%s is already installed in %s." % (self.name, self.prefix))
+ tty.msg("%s is already installed in %s" % (self.name, self.prefix))
return
tty.msg("Installing %s" % self.name)
@@ -871,7 +874,7 @@ class Package(object):
def real_work():
try:
- tty.msg("Building %s." % self.name)
+ tty.msg("Building %s" % self.name)
# Run the pre-install hook in the child process after
# the directory is created.
@@ -884,10 +887,14 @@ class Package(object):
# Do the real install in the source directory.
self.stage.chdir_to_source()
+ # Save the build environment in a file before building.
+ env_path = join_path(os.getcwd(), 'spack-build.env')
+
# This redirects I/O to a build log (and optionally to the terminal)
log_path = join_path(os.getcwd(), 'spack-build.out')
log_file = open(log_path, 'w')
with log_output(log_file, verbose, sys.stdout.isatty(), True):
+ dump_environment(env_path)
self.install(self.spec, self.prefix)
# Ensure that something was actually installed.
@@ -896,7 +903,12 @@ class Package(object):
# Move build log into install directory on success
if not fake:
log_install_path = spack.install_layout.build_log_path(self.spec)
+ env_install_path = spack.install_layout.build_env_path(self.spec)
install(log_path, log_install_path)
+ install(env_path, env_install_path)
+
+ packages_dir = spack.install_layout.build_packages_path(self.spec)
+ dump_packages(self.spec, packages_dir)
# On successful install, remove the stage.
if not keep_stage:
@@ -906,8 +918,8 @@ class Package(object):
self._total_time = time.time() - start_time
build_time = self._total_time - self._fetch_time
- tty.msg("Successfully installed %s." % self.name,
- "Fetch: %s. Build: %s. Total: %s."
+ tty.msg("Successfully installed %s" % self.name,
+ "Fetch: %s. Build: %s. Total: %s"
% (_hms(self._fetch_time), _hms(build_time), _hms(self._total_time)))
print_pkg(self.prefix)
@@ -1013,7 +1025,7 @@ class Package(object):
# Uninstalling in Spack only requires removing the prefix.
self.remove_prefix()
spack.installed_db.remove(self.spec)
- tty.msg("Successfully uninstalled %s." % self.spec.short_spec)
+ tty.msg("Successfully uninstalled %s" % self.spec.short_spec)
# Once everything else is done, run post install hooks
spack.hooks.post_uninstall(self)
@@ -1060,7 +1072,7 @@ class Package(object):
self.extendee_spec.package.activate(self, **self.extendee_args)
spack.install_layout.add_extension(self.extendee_spec, self.spec)
- tty.msg("Activated extension %s for %s."
+ tty.msg("Activated extension %s for %s"
% (self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@")))
@@ -1112,7 +1124,7 @@ class Package(object):
if self.activated:
spack.install_layout.remove_extension(self.extendee_spec, self.spec)
- tty.msg("Deactivated extension %s for %s."
+ tty.msg("Deactivated extension %s for %s"
% (self.spec.short_spec, self.extendee_spec.format("$_$@$+$%@")))
@@ -1212,6 +1224,52 @@ def validate_package_url(url_string):
tty.die("Invalid file type in URL: '%s'" % url_string)
+def dump_packages(spec, path):
+ """Dump all package information for a spec and its dependencies.
+
+ This creates a package repository within path for every
+ namespace in the spec DAG, and fills the repos wtih package
+ files and patch files for every node in the DAG.
+ """
+ mkdirp(path)
+
+ # Copy in package.py files from any dependencies.
+ # Note that we copy them in as they are in the *install* directory
+ # NOT as they are in the repository, because we want a snapshot of
+ # how *this* particular build was done.
+ for node in spec.traverse():
+ if node is not spec:
+ # Locate the dependency package in the install tree and find
+ # its provenance information.
+ source = spack.install_layout.build_packages_path(node)
+ source_repo_root = join_path(source, node.namespace)
+
+ # There's no provenance installed for the source package. Skip it.
+ # User can always get something current from the builtin repo.
+ if not os.path.isdir(source_repo_root):
+ continue
+
+ # Create a source repo and get the pkg directory out of it.
+ try:
+ source_repo = spack.repository.Repo(source_repo_root)
+ source_pkg_dir = source_repo.dirname_for_package_name(node.name)
+ except RepoError as e:
+ tty.warn("Warning: Couldn't copy in provenance for %s" % node.name)
+
+ # Create a destination repository
+ dest_repo_root = join_path(path, node.namespace)
+ if not os.path.exists(dest_repo_root):
+ spack.repository.create_repo(dest_repo_root)
+ repo = spack.repository.Repo(dest_repo_root)
+
+ # Get the location of the package in the dest repo.
+ dest_pkg_dir = repo.dirname_for_package_name(node.name)
+ if node is not spec:
+ install_tree(source_pkg_dir, dest_pkg_dir)
+ else:
+ spack.repo.dump_provenance(node, dest_pkg_dir)
+
+
def print_pkg(message):
"""Outputs a message with a package icon."""
from llnl.util.tty.color import cwrite
@@ -1262,7 +1320,7 @@ class PackageVersionError(PackageError):
"""Raised when a version URL cannot automatically be determined."""
def __init__(self, version):
super(PackageVersionError, self).__init__(
- "Cannot determine a URL automatically for version %s." % version,
+ "Cannot determine a URL automatically for version %s" % version,
"Please provide a url for this version in the package.py file.")
diff --git a/lib/spack/spack/repository.py b/lib/spack/spack/repository.py
index f58cd52125..3c3ba08bcc 100644
--- a/lib/spack/spack/repository.py
+++ b/lib/spack/spack/repository.py
@@ -6,7 +6,7 @@
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
-# For details, see https://llnl.github.io/spack
+# For details, see https://software.llnl.gov/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@ from bisect import bisect_left
from external import yaml
import llnl.util.tty as tty
-from llnl.util.filesystem import join_path
+from llnl.util.filesystem import *
import spack.error
import spack.config
@@ -156,7 +156,7 @@ class RepoPath(object):
if repo.namespace in self.by_namespace:
raise DuplicateRepoError(
- "Package repos '%s' and '%s' both provide namespace %s."
+ "Package repos '%s' and '%s' both provide namespace %s"
% (repo.root, self.by_namespace[repo.namespace].root, repo.namespace))
# Add repo to the pkg indexes
@@ -316,6 +316,16 @@ class RepoPath(object):
return self.repo_for_pkg(spec).get(spec)
+ @_autospec
+ def dump_provenance(self, spec, path):
+ """Dump provenance information for a spec to a particular path.
+
+ This dumps the package file and any associated patch files.
+ Raises UnknownPackageError if not found.
+ """
+ return self.repo_for_pkg(spec).dump_provenance(spec, path)
+
+
def dirname_for_package_name(self, pkg_name):
return self.repo_for_pkg(pkg_name).dirname_for_package_name(pkg_name)
@@ -535,7 +545,7 @@ class Repo(object):
raise UnknownPackageError(spec.name)
if spec.namespace and spec.namespace != self.namespace:
- raise UnknownPackageError("Repository %s does not contain package %s."
+ raise UnknownPackageError("Repository %s does not contain package %s"
% (self.namespace, spec.fullname))
key = hash(spec)
@@ -552,6 +562,35 @@ class Repo(object):
return self._instances[key]
+ @_autospec
+ def dump_provenance(self, spec, path):
+ """Dump provenance information for a spec to a particular path.
+
+ This dumps the package file and any associated patch files.
+ Raises UnknownPackageError if not found.
+ """
+ # Some preliminary checks.
+ if spec.virtual:
+ raise UnknownPackageError(spec.name)
+
+ if spec.namespace and spec.namespace != self.namespace:
+ raise UnknownPackageError("Repository %s does not contain package %s."
+ % (self.namespace, spec.fullname))
+
+ # Install any patch files needed by packages.
+ mkdirp(path)
+ for spec, patches in spec.package.patches.items():
+ for patch in patches:
+ if patch.path:
+ if os.path.exists(patch.path):
+ install(patch.path, path)
+ else:
+ tty.warn("Patch file did not exist: %s" % patch.path)
+
+ # Install the package.py file itself.
+ install(self.filename_for_package_name(spec), path)
+
+
def purge(self):
"""Clear entire package instance cache."""
self._instances.clear()
@@ -705,6 +744,58 @@ class Repo(object):
return self.exists(pkg_name)
+def create_repo(root, namespace=None):
+ """Create a new repository in root with the specified namespace.
+
+ If the namespace is not provided, use basename of root.
+ Return the canonicalized path and the namespace of the created repository.
+ """
+ root = canonicalize_path(root)
+ if not namespace:
+ namespace = os.path.basename(root)
+
+ if not re.match(r'\w[\.\w-]*', namespace):
+ raise InvalidNamespaceError("'%s' is not a valid namespace." % namespace)
+
+ existed = False
+ if os.path.exists(root):
+ if os.path.isfile(root):
+ raise BadRepoError('File %s already exists and is not a directory' % root)
+ elif os.path.isdir(root):
+ if not os.access(root, os.R_OK | os.W_OK):
+ raise BadRepoError('Cannot create new repo in %s: cannot access directory.' % root)
+ if os.listdir(root):
+ raise BadRepoError('Cannot create new repo in %s: directory is not empty.' % root)
+ existed = True
+
+ full_path = os.path.realpath(root)
+ parent = os.path.dirname(full_path)
+ if not os.access(parent, os.R_OK | os.W_OK):
+ raise BadRepoError("Cannot create repository in %s: can't access parent!" % root)
+
+ try:
+ config_path = os.path.join(root, repo_config_name)
+ packages_path = os.path.join(root, packages_dir_name)
+
+ mkdirp(packages_path)
+ with open(config_path, 'w') as config:
+ config.write("repo:\n")
+ config.write(" namespace: '%s'\n" % namespace)
+
+ except (IOError, OSError) as e:
+ raise BadRepoError('Failed to create new repository in %s.' % root,
+ "Caused by %s: %s" % (type(e), e))
+
+ # try to clean up.
+ if existed:
+ shutil.rmtree(config_path, ignore_errors=True)
+ shutil.rmtree(packages_path, ignore_errors=True)
+ else:
+ shutil.rmtree(root, ignore_errors=True)
+
+ return full_path, namespace
+
+
class RepoError(spack.error.SpackError):
"""Superclass for repository-related errors."""
@@ -713,6 +804,10 @@ class NoRepoConfiguredError(RepoError):
"""Raised when there are no repositories configured."""
+class InvalidNamespaceError(RepoError):
+ """Raised when an invalid namespace is encountered."""
+
+
class BadRepoError(RepoError):
"""Raised when repo layout is invalid."""
@@ -730,7 +825,7 @@ class UnknownPackageError(PackageLoadError):
def __init__(self, name, repo=None):
msg = None
if repo:
- msg = "Package %s not found in repository %s." % (name, repo)
+ msg = "Package %s not found in repository %s" % (name, repo)
else:
msg = "Package %s not found." % name
super(UnknownPackageError, self).__init__(msg)
diff --git a/lib/spack/spack/resource.py b/lib/spack/spack/resource.py
index 2bf92947fd..ddfaaf4cb0 100644
--- a/lib/spack/spack/resource.py
+++ b/lib/spack/spack/resource.py
@@ -6,7 +6,7 @@
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
-# For details, see https://llnl.github.io/spack
+# For details, see https://software.llnl.gov/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py
index f217450d42..5591cb9ba5 100644
--- a/lib/spack/spack/stage.py
+++ b/lib/spack/spack/stage.py
@@ -306,9 +306,9 @@ class Stage(object):
archive_dir = self.source_path
if not archive_dir:
self.fetcher.expand()
- tty.msg("Created stage in %s." % self.path)
+ tty.msg("Created stage in %s" % self.path)
else:
- tty.msg("Already staged %s in %s." % (self.name, self.path))
+ tty.msg("Already staged %s in %s" % (self.name, self.path))
def chdir_to_source(self):
"""Changes directory to the expanded archive directory.
diff --git a/lib/spack/spack/test/namespace_trie.py b/lib/spack/spack/test/namespace_trie.py
index d0d809004d..647976df21 100644
--- a/lib/spack/spack/test/namespace_trie.py
+++ b/lib/spack/spack/test/namespace_trie.py
@@ -6,7 +6,7 @@
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
-# For details, see https://llnl.github.io/spack
+# For details, see https://software.llnl.gov/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
diff --git a/lib/spack/spack/test/tally_plugin.py b/lib/spack/spack/test/tally_plugin.py
index 9ca898c47c..e0b9618e0c 100644
--- a/lib/spack/spack/test/tally_plugin.py
+++ b/lib/spack/spack/test/tally_plugin.py
@@ -6,7 +6,7 @@
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
-# For details, see https://scalability-llnl.github.io/spack
+# For details, see https://scalability-software.llnl.gov/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@ class Tally(Plugin):
self.successCount = 0
self.failCount = 0
self.errorCount = 0
-
+
@property
def numberOfTestsRun(self):
"""Excludes skipped tests"""
@@ -48,10 +48,10 @@ class Tally(Plugin):
def addSuccess(self, test):
self.successCount += 1
-
+
def addError(self, test, err):
self.errorCount += 1
-
+
def addFailure(self, test, err):
self.failCount += 1
diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py
index cd413dcfbc..ae8e5708be 100644
--- a/lib/spack/spack/util/environment.py
+++ b/lib/spack/spack/util/environment.py
@@ -63,3 +63,10 @@ def pop_keys(dictionary, *keys):
for key in keys:
if key in dictionary:
dictionary.pop(key)
+
+
+def dump_environment(path):
+ """Dump the current environment out to a file."""
+ with open(path, 'w') as env_file:
+ for key,val in sorted(os.environ.items()):
+ env_file.write("%s=%s\n" % (key, val))
diff --git a/lib/spack/spack/util/web.py b/lib/spack/spack/util/web.py
index e26daef296..73f4858b02 100644
--- a/lib/spack/spack/util/web.py
+++ b/lib/spack/spack/util/web.py
@@ -86,12 +86,12 @@ def _spider(args):
if not "Content-type" in resp.headers:
tty.debug("ignoring page " + url)
- return pages
+ return pages, links
if not resp.headers["Content-type"].startswith('text/html'):
tty.debug("ignoring page " + url + " with content type " +
resp.headers["Content-type"])
- return pages
+ return pages, links
# Do the real GET request when we know it's just HTML.
req.get_method = lambda: "GET"
@@ -173,7 +173,7 @@ def spider(root_url, **kwargs):
performance over a sequential fetch.
"""
max_depth = kwargs.setdefault('depth', 1)
- pages, links = _spider((root_url, set(), root_url, None, 1, max_depth, False))
+ pages, links = _spider((root_url, set(), root_url, None, 1, max_depth, False))
return pages, links