Dependencies now work. Added libelf, libdwarf.
This commit is contained in:
		| @@ -19,7 +19,7 @@ import spack | |||||||
| # Command parsing | # Command parsing | ||||||
| parser = argparse.ArgumentParser( | parser = argparse.ArgumentParser( | ||||||
|     description='Spack: the Supercomputing PACKage Manager.') |     description='Spack: the Supercomputing PACKage Manager.') | ||||||
| parser.add_argument('-V', '--version', action='version', version="%s" % spack.version) | parser.add_argument('-V', '--version', action='version', version="%s" % spack.spack_version) | ||||||
| parser.add_argument('-v', '--verbose', action='store_true', dest='verbose') | parser.add_argument('-v', '--verbose', action='store_true', dest='verbose') | ||||||
|  |  | ||||||
| # each command module implements a parser() function, to which we pass its | # each command module implements a parser() function, to which we pass its | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								lib/spack/env/c++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/c++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/c89
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/c89
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/c99
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/c99
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/case-insensitive/CC
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/case-insensitive/CC
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | ../cc | ||||||
							
								
								
									
										69
									
								
								lib/spack/env/cc
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								lib/spack/env/cc
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | #!/usr/bin/env python | ||||||
|  | import sys | ||||||
|  | import os | ||||||
|  | import subprocess | ||||||
|  | import argparse | ||||||
|  |  | ||||||
|  | def get_path(name): | ||||||
|  |     path = os.environ.get(name, "") | ||||||
|  |     return path.split(":") | ||||||
|  |  | ||||||
|  | # Import spack parameters through the build environment. | ||||||
|  | spack_lib      = os.environ.get("SPACK_LIB") | ||||||
|  | spack_deps     = get_path("SPACK_DEPENDENCIES") | ||||||
|  | spack_env_path = get_path("SPACK_ENV_PATH") | ||||||
|  | if not spack_lib or spack_deps == None: | ||||||
|  |     print "%s must be run from spack." % os.path.abspath(sys.argv[0]) | ||||||
|  |     sys.exit(1) | ||||||
|  |  | ||||||
|  | # Figure out what type of operation we're doing | ||||||
|  | command = os.path.basename(sys.argv[0]) | ||||||
|  |  | ||||||
|  | # Grab a minimal set of spack packages | ||||||
|  | sys.path.append(spack_lib) | ||||||
|  | from spack.utils import * | ||||||
|  | from spack.compilation import parse_rpaths | ||||||
|  | import spack.tty as tty | ||||||
|  |  | ||||||
|  | parser = argparse.ArgumentParser(add_help=False) | ||||||
|  | parser.add_argument("-I", action='append', default=[], dest='include_path') | ||||||
|  | parser.add_argument("-L", action='append', default=[], dest='lib_path') | ||||||
|  | parser.add_argument("-l", action='append', default=[], dest='libs') | ||||||
|  |  | ||||||
|  | options, other_args = parser.parse_known_args() | ||||||
|  | rpaths, other_args = parse_rpaths(other_args) | ||||||
|  |  | ||||||
|  | if rpaths: | ||||||
|  |     tty.warn("Spack stripping non-spack rpaths: ", *rpaths) | ||||||
|  |  | ||||||
|  | # Find the actual command the build is trying to run by removing | ||||||
|  | # Spack's env paths from the path.  We use this later for which() | ||||||
|  | script_dir = os.path.dirname(os.path.expanduser(__file__)) | ||||||
|  | clean_path = get_path("PATH") | ||||||
|  | remove_items(clean_path, '.') | ||||||
|  | for path in spack_env_path: | ||||||
|  |     remove_items(clean_path, path) | ||||||
|  |  | ||||||
|  | # Add dependence's paths to our compiler flags. | ||||||
|  | def append_if_dir(path_list, prefix, *dirs): | ||||||
|  |     full_path = os.path.join(prefix, *dirs) | ||||||
|  |     if os.path.isdir(full_path): | ||||||
|  |         path_list.append(full_path) | ||||||
|  |  | ||||||
|  | for prefix in spack_deps: | ||||||
|  |     append_if_dir(options.include_path, prefix, "include") | ||||||
|  |     append_if_dir(options.lib_path, prefix, "lib") | ||||||
|  |     append_if_dir(options.lib_path, prefix, "lib64") | ||||||
|  |  | ||||||
|  | # Add our modified arguments to it. | ||||||
|  | cmd = which(command, path=clean_path) | ||||||
|  | arguments  = ['-I%s' % path for path in options.include_path] | ||||||
|  | arguments += other_args | ||||||
|  | arguments += ['-L%s' % path for path in options.lib_path] | ||||||
|  | arguments += ['-l%s' % path for path in options.libs] | ||||||
|  |  | ||||||
|  | # Unset some pesky environment variables | ||||||
|  | pop_keys(os.environ, "LD_LIBRARY_PATH", "LD_RUN_PATH", "DYLD_LIBRARY_PATH") | ||||||
|  |  | ||||||
|  | rcode = cmd(*arguments, fail_on_error=False) | ||||||
|  | sys.exit(rcode) | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/clang
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/clang
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/clang++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/clang++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/cpp
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/cpp
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/g++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/g++
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/gcc
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/gcc
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
							
								
								
									
										1
									
								
								lib/spack/env/ld
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								lib/spack/env/ld
									
									
									
									
										vendored
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | cc | ||||||
| @@ -2,16 +2,39 @@ | |||||||
| import os | import os | ||||||
| import re | import re | ||||||
| import subprocess | import subprocess | ||||||
|  | import platform | ||||||
|  | import shutil | ||||||
|  |  | ||||||
| from spack import * | from spack import * | ||||||
|  | import packages | ||||||
| import tty | import tty | ||||||
| import attr | import attr | ||||||
| import validate | import validate | ||||||
| import version | import version | ||||||
| import shutil | import arch | ||||||
| import platform |  | ||||||
| from stage import Stage | from stage import Stage | ||||||
|  |  | ||||||
|  |  | ||||||
|  | DEPENDS_ON = "depends_on" | ||||||
|  |  | ||||||
|  | class Dependency(object): | ||||||
|  |     """Represents a dependency from one package to another.""" | ||||||
|  |     def __init__(self, name, **kwargs): | ||||||
|  |         self.name = name | ||||||
|  |         for key in kwargs: | ||||||
|  |             setattr(self, key, kwargs[key]) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def package(self): | ||||||
|  |         return packages.get(self.name) | ||||||
|  |  | ||||||
|  |     def __repr__(self): | ||||||
|  |         return "<dep: %s>" % self.name | ||||||
|  |  | ||||||
|  |     def __str__(self): | ||||||
|  |         return self.__repr__() | ||||||
|  |  | ||||||
|  |  | ||||||
| def depends_on(*args, **kwargs): | def depends_on(*args, **kwargs): | ||||||
|     """Adds a depends_on local variable in the locals of |     """Adds a depends_on local variable in the locals of | ||||||
|        the calling class, based on args. |        the calling class, based on args. | ||||||
| @@ -21,40 +44,170 @@ def depends_on(*args, **kwargs): | |||||||
|         locals = stack[1][0].f_locals |         locals = stack[1][0].f_locals | ||||||
|     finally: |     finally: | ||||||
|         del stack |         del stack | ||||||
|     print locals |  | ||||||
|  |  | ||||||
|     locals["depends_on"] = kwargs |         dependencies = locals.setdefault("dependencies", []) | ||||||
|  |     for name in args: | ||||||
|  |         dependencies.append(Dependency(name)) | ||||||
|  |  | ||||||
|  |  | ||||||
| class Package(object): | class Package(object): | ||||||
|     def __init__(self): |     def __init__(self, arch=arch.sys_type()): | ||||||
|         attr.required(self, 'homepage') |         attr.required(self, 'homepage') | ||||||
|         attr.required(self, 'url') |         attr.required(self, 'url') | ||||||
|         attr.required(self, 'md5') |         attr.required(self, 'md5') | ||||||
|  |         attr.setdefault(self, "dependencies", []) | ||||||
|  |  | ||||||
|         # Name of package is just the classname lowercased |         # Architecture for this package. | ||||||
|         self.name = self.__class__.__name__.lower() |         self.arch = arch | ||||||
|  |  | ||||||
|  |         # Name of package is the name of its module (the file that contains it) | ||||||
|  |         self.name = inspect.getmodulename(self.module.__file__) | ||||||
|  |  | ||||||
|         # Make sure URL is an allowed type |         # Make sure URL is an allowed type | ||||||
|         validate.url(self.url) |         validate.url(self.url) | ||||||
|  |  | ||||||
|         v = version.parse(self.url) |         # Set up version | ||||||
|         if not v: |         attr.setdefault(self, 'version', version.parse_version(self.url)) | ||||||
|  |         if not self.version: | ||||||
|             tty.die("Couldn't extract version from '%s'. " + |             tty.die("Couldn't extract version from '%s'. " + | ||||||
|                     "You must specify it explicitly for this URL." % self.url) |                     "You must specify it explicitly for this URL." % self.url) | ||||||
|         self.version = v |  | ||||||
|  |         # This adds a bunch of convenient commands to the package's module scope. | ||||||
|  |         self.add_commands_to_module() | ||||||
|  |  | ||||||
|  |         # Controls whether install and uninstall check deps before acting. | ||||||
|  |         self.ignore_dependencies = False | ||||||
|  |  | ||||||
|  |         # Empty at first; only compute dependents if necessary | ||||||
|  |         self._dependents = None | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def add_commands_to_module(self): | ||||||
|  |         """Populate the module scope of install() with some useful functions. | ||||||
|  |            This makes things easier for package writers. | ||||||
|  |         """ | ||||||
|  |         self.module.make  = make_make() | ||||||
|  |  | ||||||
|  |         # Find the configure script in the archive path | ||||||
|  |         # Don't use which for this; we want to find it in the current dir. | ||||||
|  |         self.module.configure = Executable('./configure') | ||||||
|  |         self.module.cmake = which("cmake") | ||||||
|  |  | ||||||
|  |         # standard CMake arguments | ||||||
|  |         self.module.std_cmake_args = [ | ||||||
|  |             '-DCMAKE_INSTALL_PREFIX=%s' % self.prefix, | ||||||
|  |             '-DCMAKE_BUILD_TYPE=None'] | ||||||
|  |         if platform.mac_ver()[0]: | ||||||
|  |             self.module.std_cmake_args.append('-DCMAKE_FIND_FRAMEWORK=LAST') | ||||||
|  |  | ||||||
|  |         # Emulate some shell commands for convenience | ||||||
|  |         self.module.cd         = os.chdir | ||||||
|  |         self.module.mkdir      = os.mkdir | ||||||
|  |         self.module.makedirs   = os.makedirs | ||||||
|  |         self.module.removedirs = os.removedirs | ||||||
|  |  | ||||||
|  |         self.module.mkdirp     = mkdirp | ||||||
|  |         self.module.install    = install | ||||||
|  |         self.module.rmtree     = shutil.rmtree | ||||||
|  |         self.module.move       = shutil.move | ||||||
|  |  | ||||||
|  |         # Useful directories within the prefix | ||||||
|  |         self.module.prefix  = self.prefix | ||||||
|  |         self.module.bin     = new_path(self.prefix, 'bin') | ||||||
|  |         self.module.sbin    = new_path(self.prefix, 'sbin') | ||||||
|  |         self.module.etc     = new_path(self.prefix, 'etc') | ||||||
|  |         self.module.include = new_path(self.prefix, 'include') | ||||||
|  |         self.module.lib     = new_path(self.prefix, 'lib') | ||||||
|  |         self.module.libexec = new_path(self.prefix, 'libexec') | ||||||
|  |         self.module.share   = new_path(self.prefix, 'share') | ||||||
|  |         self.module.doc     = new_path(self.module.share, 'doc') | ||||||
|  |         self.module.info    = new_path(self.module.share, 'info') | ||||||
|  |         self.module.man     = new_path(self.module.share, 'man') | ||||||
|  |         self.module.man1    = new_path(self.module.man, 'man1') | ||||||
|  |         self.module.man2    = new_path(self.module.man, 'man2') | ||||||
|  |         self.module.man3    = new_path(self.module.man, 'man3') | ||||||
|  |         self.module.man4    = new_path(self.module.man, 'man4') | ||||||
|  |         self.module.man5    = new_path(self.module.man, 'man5') | ||||||
|  |         self.module.man6    = new_path(self.module.man, 'man6') | ||||||
|  |         self.module.man7    = new_path(self.module.man, 'man7') | ||||||
|  |         self.module.man8    = new_path(self.module.man, 'man8') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def dependents(self): | ||||||
|  |         """List of names of packages that depend on this one.""" | ||||||
|  |         if self._dependents is None: | ||||||
|  |             packages.compute_dependents() | ||||||
|  |         return tuple(self._dependents) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def installed(self): | ||||||
|  |         return os.path.exists(self.prefix) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def installed_dependents(self): | ||||||
|  |         installed = [d for d in self.dependents if packages.get(d).installed] | ||||||
|  |         all_deps = [] | ||||||
|  |         for d in installed: | ||||||
|  |             all_deps.append(d) | ||||||
|  |             all_deps.extend(packages.get(d).installed_dependents) | ||||||
|  |         return tuple(all_deps) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def all_dependents(self): | ||||||
|  |         all_deps = list(self.dependents) | ||||||
|  |         for pkg in self.dependents: | ||||||
|  |             all_deps.extend(packages.get(pkg).all_dependents) | ||||||
|  |         return tuple(all_deps) | ||||||
|  |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def stage(self): |     def stage(self): | ||||||
|         return Stage(self.stage_name) |         return Stage(self.stage_name, self.url) | ||||||
|  |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def stage_name(self): |     def stage_name(self): | ||||||
|         return "%s-%s" % (self.name, self.version) |         return "%s-%s" % (self.name, self.version) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def platform_path(self): | ||||||
|  |         """Directory for binaries for the current platform.""" | ||||||
|  |         return new_path(install_path, self.arch) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def package_path(self): | ||||||
|  |         """Directory for different versions of this package.  Lives just above prefix.""" | ||||||
|  |         return new_path(self.platform_path, self.name) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def installed_versions(self): | ||||||
|  |         return [ver for ver in os.listdir(self.package_path) | ||||||
|  |                 if os.path.isdir(new_path(self.package_path, ver))] | ||||||
|  |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def prefix(self): |     def prefix(self): | ||||||
|         return new_path(install_path, self.stage_name) |         """Packages are installed in $spack_prefix/opt/<sys_type>/<name>/<version>""" | ||||||
|  |         return new_path(self.package_path, self.version) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def remove_prefix(self): | ||||||
|  |         """Removes the prefix for a package along with any empty parent directories.""" | ||||||
|  |         shutil.rmtree(self.prefix, True) | ||||||
|  |         for dir in (self.package_path, self.platform_path): | ||||||
|  |             if not os.listdir(dir): | ||||||
|  |                 os.rmdir(dir) | ||||||
|  |             else: | ||||||
|  |                 break | ||||||
|  |  | ||||||
|  |  | ||||||
|     def do_fetch(self): |     def do_fetch(self): | ||||||
|         """Creates a stage directory and downloads the taball for this package. |         """Creates a stage directory and downloads the taball for this package. | ||||||
| @@ -62,49 +215,28 @@ def do_fetch(self): | |||||||
|         """ |         """ | ||||||
|         stage = self.stage |         stage = self.stage | ||||||
|         stage.setup() |         stage.setup() | ||||||
|         stage.chdir() |         stage.fetch() | ||||||
|  |  | ||||||
|         archive_file = os.path.basename(self.url) |         archive_md5 = md5(stage.archive_file) | ||||||
|         if not os.path.exists(archive_file): |  | ||||||
|             tty.msg("Fetching %s" % self.url) |  | ||||||
|  |  | ||||||
|             # Run curl but grab the mime type from the http headers |  | ||||||
|             headers = curl('-#', '-O', '-D', '-', self.url, return_output=True) |  | ||||||
|  |  | ||||||
|             # output this if we somehow got an HTML file rather than the archive we |  | ||||||
|             # asked for. |  | ||||||
|             if re.search(r'Content-Type: text/html', headers): |  | ||||||
|                 tty.warn("The contents of '%s' look like HTML.  The checksum will "+ |  | ||||||
|                          "likely fail.  Use 'spack clean %s' to delete this file. " |  | ||||||
|                          "The fix the gateway issue and install again." % (archive_file, self.name)) |  | ||||||
|  |  | ||||||
|             if not os.path.exists(archive_file): |  | ||||||
|                 tty.die("Failed to download '%s'!" % self.url) |  | ||||||
|         else: |  | ||||||
|             tty.msg("Already downloaded %s." % self.name) |  | ||||||
|  |  | ||||||
|         archive_md5 = md5(archive_file) |  | ||||||
|         if archive_md5 != self.md5: |         if archive_md5 != self.md5: | ||||||
|             tty.die("MD5 Checksum failed for %s.  Expected %s but got %s." |             tty.die("MD5 Checksum failed for %s.  Expected %s but got %s." | ||||||
|                     % (self.name, self.md5, archive_md5)) |                     % (self.name, self.md5, archive_md5)) | ||||||
|  |  | ||||||
|         return archive_file |  | ||||||
|  |  | ||||||
|     def do_stage(self): |     def do_stage(self): | ||||||
|         """Unpacks the fetched tarball, then changes into the expanded tarball directory.""" |         """Unpacks the fetched tarball, then changes into the expanded tarball directory.""" | ||||||
|         archive_file = self.do_fetch() |         self.do_fetch() | ||||||
|         stage = self.stage |         stage = self.stage | ||||||
|  |  | ||||||
|         archive_dir = stage.archive_path |         archive_dir = stage.expanded_archive_path | ||||||
|         if not archive_dir: |         if not archive_dir: | ||||||
|             tty.msg("Staging archive: '%s'" % archive_file) |             tty.msg("Staging archive: '%s'" % stage.archive_file) | ||||||
|             decompress = decompressor_for(archive_file) |             stage.expand_archive() | ||||||
|             decompress(archive_file) |  | ||||||
|         else: |         else: | ||||||
|             tty.msg("Alredy staged %s" % self.name) |             tty.msg("Already staged %s" % self.name) | ||||||
|  |  | ||||||
|         stage.chdir_to_archive() |         stage.chdir_to_archive() | ||||||
|  |  | ||||||
|  |  | ||||||
|     def do_install(self): |     def do_install(self): | ||||||
|         """This class should call this version of the install method. |         """This class should call this version of the install method. | ||||||
|            Package implementations should override install(). |            Package implementations should override install(). | ||||||
| @@ -114,17 +246,55 @@ def do_install(self): | |||||||
|             tty.pkg(self.prefix) |             tty.pkg(self.prefix) | ||||||
|             return |             return | ||||||
|  |  | ||||||
|  |         if not self.ignore_dependencies: | ||||||
|  |             self.do_install_dependencies() | ||||||
|  |  | ||||||
|         self.do_stage() |         self.do_stage() | ||||||
|  |         self.setup_install_environment() | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             self.install(self.prefix) | ||||||
|  |             if not os.path.isdir(self.prefix): | ||||||
|  |                 tty.die("Install failed for %s.  No install dir created." % self.name) | ||||||
|  |         except Exception, e: | ||||||
|  |             # Blow away the install tree if anything goes wrong. | ||||||
|  |             self.remove_prefix() | ||||||
|  |             tty.die("Install failed for %s" % self.name, e.message) | ||||||
|  |  | ||||||
|         # Populate the module scope of install() with some useful functions. |  | ||||||
|         # This makes things easier for package writers. |  | ||||||
|         self.module.configure = which("configure", [self.stage.archive_path]) |  | ||||||
|         self.module.cmake = which("cmake") |  | ||||||
|  |  | ||||||
|         self.install(self.prefix) |  | ||||||
|         tty.msg("Successfully installed %s" % self.name) |         tty.msg("Successfully installed %s" % self.name) | ||||||
|         tty.pkg(self.prefix) |         tty.pkg(self.prefix) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def setup_install_environment(self): | ||||||
|  |         """This ensures a clean install environment when we build packages.""" | ||||||
|  |         pop_keys(os.environ, "LD_LIBRARY_PATH", "LD_RUN_PATH", "DYLD_LIBRARY_PATH") | ||||||
|  |  | ||||||
|  |         # Add spack environment at front of path and pass the | ||||||
|  |         # lib location along so the compiler script can find spack | ||||||
|  |         os.environ["SPACK_LIB"] = lib_path | ||||||
|  |  | ||||||
|  |         # Fix for case-insensitive file systems.  Conflicting links are | ||||||
|  |         # in directories called "case*" within the env directory. | ||||||
|  |         env_paths = [env_path] | ||||||
|  |         for file in os.listdir(env_path): | ||||||
|  |             path = new_path(env_path, file) | ||||||
|  |             if file.startswith("case") and os.path.isdir(path): | ||||||
|  |                 env_paths.append(path) | ||||||
|  |         path_prepend("PATH", *env_paths) | ||||||
|  |         path_prepend("SPACK_ENV_PATH", *env_paths) | ||||||
|  |  | ||||||
|  |         # Pass along paths of dependencies here | ||||||
|  |         for dep in self.dependencies: | ||||||
|  |             path_prepend("SPACK_DEPENDENCIES", dep.package.prefix) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def do_install_dependencies(self): | ||||||
|  |         # Pass along paths of dependencies here | ||||||
|  |         for dep in self.dependencies: | ||||||
|  |             dep.package.do_install() | ||||||
|  |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def module(self): |     def module(self): | ||||||
|         """Use this to add variables to the class's module's scope. |         """Use this to add variables to the class's module's scope. | ||||||
| @@ -133,36 +303,49 @@ def module(self): | |||||||
|         return __import__(self.__class__.__module__, |         return __import__(self.__class__.__module__, | ||||||
|                           fromlist=[self.__class__.__name__]) |                           fromlist=[self.__class__.__name__]) | ||||||
|  |  | ||||||
|  |  | ||||||
|     def install(self, prefix): |     def install(self, prefix): | ||||||
|         """Package implementations override this with their own build configuration.""" |         """Package implementations override this with their own build configuration.""" | ||||||
|         tty.die("Packages must provide an install method!") |         tty.die("Packages must provide an install method!") | ||||||
|  |  | ||||||
|  |  | ||||||
|     def do_uninstall(self): |     def do_uninstall(self): | ||||||
|         self.uninstall(self.prefix) |         if not os.path.exists(self.prefix): | ||||||
|  |             tty.die(self.name + " is not installed.") | ||||||
|  |  | ||||||
|  |         if not self.ignore_dependencies: | ||||||
|  |             deps = self.installed_dependents | ||||||
|  |             if deps: tty.die( | ||||||
|  |                 "Cannot uninstall %s. The following installed packages depend on it:" | ||||||
|  |                 % self.name, " ".join(deps)) | ||||||
|  |  | ||||||
|  |         self.remove_prefix() | ||||||
|         tty.msg("Successfully uninstalled %s." % self.name) |         tty.msg("Successfully uninstalled %s." % self.name) | ||||||
|  |  | ||||||
|     def uninstall(self, prefix): |  | ||||||
|         """By default just blows the install dir away.""" |  | ||||||
|         shutil.rmtree(self.prefix, True) |  | ||||||
|  |  | ||||||
|     def do_clean(self): |     def do_clean(self): | ||||||
|         self.clean() |         if self.stage.expanded_archive_path: | ||||||
|  |             self.stage.chdir_to_archive() | ||||||
|  |             self.clean() | ||||||
|  |  | ||||||
|  |  | ||||||
|     def clean(self): |     def clean(self): | ||||||
|         """By default just runs make clean.  Override if this isn't good.""" |         """By default just runs make clean.  Override if this isn't good.""" | ||||||
|         stage = self.stage |         try: | ||||||
|         if stage.archive_path: |             make = make_make() | ||||||
|             stage.chdir_to_archive() |             make('clean') | ||||||
|             try: |             tty.msg("Successfully cleaned %s" % self.name) | ||||||
|                 make("clean") |         except subprocess.CalledProcessError, e: | ||||||
|                 tty.msg("Successfully cleaned %s" % self.name) |             tty.warn("Warning: 'make clean' didn't work.  Consider 'spack clean --work'.") | ||||||
|             except subprocess.CalledProcessError: |  | ||||||
|                 # Might not be configured.  Ignore. |  | ||||||
|                 pass |  | ||||||
|  |  | ||||||
|     def do_clean_all(self): |  | ||||||
|  |     def do_clean_work(self): | ||||||
|  |         """By default just blows away the stage directory and re-stages.""" | ||||||
|  |         self.stage.restage() | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def do_clean_dist(self): | ||||||
|  |         """Removes the stage directory where this package was built.""" | ||||||
|         if os.path.exists(self.stage.path): |         if os.path.exists(self.stage.path): | ||||||
|             self.stage.destroy() |             self.stage.destroy() | ||||||
|         tty.msg("Successfully cleaned %s" % self.name) |         tty.msg("Successfully cleaned %s" % self.name) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
|  |  | ||||||
| from globals import * | from globals import * | ||||||
| from fileutils import * | from utils import * | ||||||
|  | from exception import * | ||||||
|  |  | ||||||
| from Package import Package, depends_on | from Package import Package, depends_on | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								lib/spack/spack/arch.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/spack/spack/arch.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import os | ||||||
|  | import platform | ||||||
|  |  | ||||||
|  | from version import Version | ||||||
|  | from utils import memoized | ||||||
|  |  | ||||||
|  | instances = {} | ||||||
|  | macos_versions = [ | ||||||
|  |     ('10.8', 'mountain_lion'), | ||||||
|  |     ('10.7', 'lion'), | ||||||
|  |     ('10.6', 'snow_leopard'), | ||||||
|  |     ('10.5', 'leopard')] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SysType(object): | ||||||
|  |     def __init__(self, arch_string): | ||||||
|  |         self.arch_string = arch_string | ||||||
|  |  | ||||||
|  |     def __repr__(self): | ||||||
|  |         return self.arch_string | ||||||
|  |  | ||||||
|  |     def __str__(self): | ||||||
|  |         return self.__repr__() | ||||||
|  |  | ||||||
|  | @memoized | ||||||
|  | def sys_type(): | ||||||
|  |     stype = os.environ.get('SYS_TYPE') | ||||||
|  |     if stype: | ||||||
|  |         return SysType(stype) | ||||||
|  |     elif platform.mac_ver()[0]: | ||||||
|  |         version = Version(platform.mac_ver()[0]) | ||||||
|  |         for mac_ver, name in macos_versions: | ||||||
|  |             if version >= Version(mac_ver): | ||||||
|  |                 return SysType(name) | ||||||
| @@ -6,3 +6,9 @@ def required(obj, attr_name): | |||||||
|         tty.die("No required attribute '%s' in class '%s'" |         tty.die("No required attribute '%s' in class '%s'" | ||||||
|                 % (attr_name, obj.__class__.__name__)) |                 % (attr_name, obj.__class__.__name__)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def setdefault(obj, name, value): | ||||||
|  |     """Like dict.setdefault, but for objects.""" | ||||||
|  |     if not hasattr(obj, name): | ||||||
|  |         setattr(obj, name, value) | ||||||
|  |     return getattr(obj, name) | ||||||
|   | |||||||
| @@ -4,16 +4,20 @@ | |||||||
| import spack | import spack | ||||||
| import spack.tty as tty | import spack.tty as tty | ||||||
|  |  | ||||||
| SETUP_PARSER = "setup_parser" | # Patterns to ignore in the commands directory when looking for commands. | ||||||
|  | ignore_files = r'^\.|^__init__.py$|^#' | ||||||
|  |  | ||||||
|  | setup_parser = "setup_parser" | ||||||
| command_path = os.path.join(spack.lib_path, "spack", "cmd") | command_path = os.path.join(spack.lib_path, "spack", "cmd") | ||||||
|  |  | ||||||
| commands = [] | commands = [] | ||||||
| for file in os.listdir(command_path): | for file in os.listdir(command_path): | ||||||
|     if file.endswith(".py") and not file == "__init__.py": |     if file.endswith(".py") and not re.search(ignore_files, file): | ||||||
|         cmd = re.sub(r'.py$', '', file) |         cmd = re.sub(r'.py$', '', file) | ||||||
|         commands.append(cmd) |         commands.append(cmd) | ||||||
| commands.sort() | commands.sort() | ||||||
|  |  | ||||||
|  |  | ||||||
| def null_op(*args): | def null_op(*args): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
| @@ -21,8 +25,8 @@ def null_op(*args): | |||||||
| def get_module(name): | def get_module(name): | ||||||
|     """Imports the module for a particular command name and returns it.""" |     """Imports the module for a particular command name and returns it.""" | ||||||
|     module_name = "%s.%s" % (__name__, name) |     module_name = "%s.%s" % (__name__, name) | ||||||
|     module = __import__(module_name, fromlist=[name, SETUP_PARSER], level=0) |     module = __import__(module_name, fromlist=[name, setup_parser], level=0) | ||||||
|     module.setup_parser = getattr(module, SETUP_PARSER, null_op) |     module.setup_parser = getattr(module, setup_parser, null_op) | ||||||
|  |  | ||||||
|     if not hasattr(module, name): |     if not hasattr(module, name): | ||||||
|         tty.die("Command module %s (%s) must define function '%s'." |         tty.die("Command module %s (%s) must define function '%s'." | ||||||
|   | |||||||
| @@ -1,12 +0,0 @@ | |||||||
| from spack import * |  | ||||||
| import spack.version as version |  | ||||||
|  |  | ||||||
| import multiprocessing |  | ||||||
| import platform |  | ||||||
|  |  | ||||||
| def arch(args): |  | ||||||
|     print multiprocessing.cpu_count() |  | ||||||
|     print platform.mac_ver() |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     print version.canonical(platform.mac_ver()[0]) |  | ||||||
| @@ -1,16 +1,21 @@ | |||||||
| import spack.packages as packages | import spack.packages as packages | ||||||
|  |  | ||||||
| def setup_parser(subparser): | def setup_parser(subparser): | ||||||
|     subparser.add_argument('name', help="name of package to clean") |     subparser.add_argument('names', nargs='+', help="name(s) of package(s) to clean") | ||||||
|     subparser.add_argument('-a', "--all", action="store_true", dest="all", |     subparser.add_mutually_exclusive_group() | ||||||
|                            help="delete the entire stage directory") |     subparser.add_argument('-c', "--clean", action="store_true", dest='clean', | ||||||
|  |                            help="run make clean in the stage directory (default)") | ||||||
|  |     subparser.add_argument('-w', "--work", action="store_true", dest='work', | ||||||
|  |                            help="delete and re-expand the entire stage directory") | ||||||
|  |     subparser.add_argument('-d', "--dist", action="store_true", dest='dist', | ||||||
|  |                            help="delete the downloaded archive.") | ||||||
|  |  | ||||||
| def clean(args): | def clean(args): | ||||||
|     package_class = packages.get(args.name) |     for name in args.names: | ||||||
|     package = package_class() |         package = packages.get(name) | ||||||
|     if args.all: |         if args.dist: | ||||||
|         package.do_clean_all() |             package.do_clean_dist() | ||||||
|     else: |         elif args.work: | ||||||
|         package.do_clean() |             package.do_clean_work() | ||||||
|  |         else: | ||||||
|  |             package.do_clean() | ||||||
|   | |||||||
| @@ -1,27 +1,30 @@ | |||||||
| import string | import string | ||||||
|  | import os | ||||||
|  |  | ||||||
| import spack | import spack | ||||||
| import spack.packages as packages | import spack.packages as packages | ||||||
| import spack.tty as tty | import spack.tty as tty | ||||||
| import spack.version | import spack.version | ||||||
|  |  | ||||||
| pacakge_tempate = string.Template("""\ | from spack.stage import Stage | ||||||
|  | from contextlib import closing | ||||||
|  |  | ||||||
|  | package_template = string.Template("""\ | ||||||
| from spack import * | from spack import * | ||||||
|  |  | ||||||
| class $name(Package): | class ${class_name}(Package): | ||||||
|     homepage = "${homepage}" |     homepage = "http://www.example.com" | ||||||
|     url      = "${url}" |     url      = "${url}" | ||||||
|     md5      = "${md5}" |     md5      = "${md5}" | ||||||
|  |  | ||||||
|     def install(self): |     def install(self, prefix): | ||||||
|         # Insert your installation code here. |         # Insert the configure line for your build system here. | ||||||
|         pass |         configure("--prefix=%s" % prefix) | ||||||
|  |         # cmake(".", *std_cmake_args) | ||||||
|  |         make() | ||||||
|  |         make("install") | ||||||
| """) | """) | ||||||
|  |  | ||||||
| def create_template(name): |  | ||||||
|     class_name = name.capitalize() |  | ||||||
|     return new_pacakge_tempate % class_name |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def setup_parser(subparser): | def setup_parser(subparser): | ||||||
|     subparser.add_argument('url', nargs='?', help="url of package archive") |     subparser.add_argument('url', nargs='?', help="url of package archive") | ||||||
| @@ -30,28 +33,42 @@ def setup_parser(subparser): | |||||||
| def create(args): | def create(args): | ||||||
|     url = args.url |     url = args.url | ||||||
|  |  | ||||||
|     version = spack.version.parse(url) |     # Try to deduce name and version of the new package from the URL | ||||||
|     if not version: |     name, version = spack.version.parse(url) | ||||||
|         tty.die("Couldn't figure out a version string from '%s'." % url) |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     # By default open the directory where packages live. |  | ||||||
|     if not name: |     if not name: | ||||||
|         path = spack.packages_path |         print "Couldn't guess a name for this package." | ||||||
|     else: |         while not name: | ||||||
|         path = packages.filename_for(name) |             new_name = raw_input("Name: ") | ||||||
|  |             if packages.valid_name(name): | ||||||
|  |                 name = new_name | ||||||
|  |             else: | ||||||
|  |                 print "Package names must contain letters, numbers, and '_' or '-'" | ||||||
|  |  | ||||||
|         if os.path.exists(path): |     if not version: | ||||||
|             if not os.path.isfile(path): |         tty.die("Couldn't guess a version string from %s." % url) | ||||||
|                 tty.die("Something's wrong.  '%s' is not a file!" % path) |  | ||||||
|             if not os.access(path, os.R_OK|os.W_OK): |     path = packages.filename_for(name) | ||||||
|                 tty.die("Insufficient permissions on '%s'!" % path) |     if os.path.exists(path): | ||||||
|         else: |         tty.die("%s already exists." % path) | ||||||
|             tty.msg("Editing new file: '%s'." % path) |  | ||||||
|             file = open(path, "w") |     # make a stage and fetch the archive. | ||||||
|             file.write(create_template(name)) |     try: | ||||||
|             file.close() |         stage = Stage(name, url) | ||||||
|  |         archive_file = stage.fetch() | ||||||
|  |     except spack.FailedDownloadException, e: | ||||||
|  |         tty.die(e.message) | ||||||
|  |  | ||||||
|  |     md5 = spack.md5(archive_file) | ||||||
|  |     class_name = packages.class_for(name) | ||||||
|  |  | ||||||
|  |     # Write outa template for the file | ||||||
|  |     tty.msg("Editing %s." % path) | ||||||
|  |     with closing(open(path, "w")) as pkg_file: | ||||||
|  |         pkg_file.write( | ||||||
|  |             package_template.substitute( | ||||||
|  |                 class_name=class_name, | ||||||
|  |                 url=url, | ||||||
|  |                 md5=md5)) | ||||||
|  |  | ||||||
|     # If everything checks out, go ahead and edit. |     # If everything checks out, go ahead and edit. | ||||||
|     spack.editor(path) |     spack.editor(path) | ||||||
|   | |||||||
| @@ -3,29 +3,12 @@ | |||||||
| import spack.packages as packages | import spack.packages as packages | ||||||
| import spack.tty as tty | import spack.tty as tty | ||||||
|  |  | ||||||
| new_pacakge_tempate = """\ |  | ||||||
| from spack import * |  | ||||||
|  |  | ||||||
| class %s(Package): |  | ||||||
|     homepage = "https://www.example.com" |  | ||||||
|     url      = "https://www.example.com/download/example-1.0.tar.gz" |  | ||||||
|     md5      = "nomd5" |  | ||||||
|  |  | ||||||
|     def install(self): |  | ||||||
|         # Insert your installation code here. |  | ||||||
|         pass |  | ||||||
|  |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| def create_template(name): |  | ||||||
|     class_name = name.capitalize() |  | ||||||
|     return new_pacakge_tempate % class_name |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def setup_parser(subparser): | def setup_parser(subparser): | ||||||
|     subparser.add_argument( |     subparser.add_argument( | ||||||
|         'name', nargs='?', default=None, help="name of package to edit") |         'name', nargs='?', default=None, help="name of package to edit") | ||||||
|  |  | ||||||
|  |  | ||||||
| def edit(args): | def edit(args): | ||||||
|     name = args.name |     name = args.name | ||||||
|  |  | ||||||
| @@ -41,10 +24,7 @@ def edit(args): | |||||||
|             if not os.access(path, os.R_OK|os.W_OK): |             if not os.access(path, os.R_OK|os.W_OK): | ||||||
|                 tty.die("Insufficient permissions on '%s'!" % path) |                 tty.die("Insufficient permissions on '%s'!" % path) | ||||||
|         else: |         else: | ||||||
|             tty.msg("Editing new file: '%s'." % path) |             tty.die("No package for %s.  Use spack create.") | ||||||
|             file = open(path, "w") |  | ||||||
|             file.write(create_template(name)) |  | ||||||
|             file.close() |  | ||||||
|  |  | ||||||
|     # If everything checks out, go ahead and edit. |     # If everything checks out, go ahead and edit. | ||||||
|     spack.editor(path) |     spack.editor(path) | ||||||
|   | |||||||
| @@ -4,6 +4,5 @@ def setup_parser(subparser): | |||||||
|     subparser.add_argument('name', help="name of package to fetch") |     subparser.add_argument('name', help="name of package to fetch") | ||||||
|  |  | ||||||
| def fetch(args): | def fetch(args): | ||||||
|     package_class = packages.get(args.name) |     package = packages.get(args.name) | ||||||
|     package = package_class() |  | ||||||
|     package.do_fetch() |     package.do_fetch() | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								lib/spack/spack/cmd/graph.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								lib/spack/spack/cmd/graph.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | import spack | ||||||
|  | import spack.packages as packages | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def graph(args): | ||||||
|  |     packages.graph_dependencies() | ||||||
| @@ -1,11 +1,14 @@ | |||||||
|  | import spack | ||||||
| import spack.packages as packages | import spack.packages as packages | ||||||
|  |  | ||||||
| def setup_parser(subparser): | def setup_parser(subparser): | ||||||
|     subparser.add_argument('name', help="name of package to install") |     subparser.add_argument('names', nargs='+', help="name(s) of package(s) to install") | ||||||
|  |     subparser.add_argument('-i', '--ignore-dependencies', | ||||||
|  |                            action='store_true', dest='ignore_dependencies', | ||||||
|  |                            help="Do not try to install dependencies of requested packages.") | ||||||
|  |  | ||||||
| def install(args): | def install(args): | ||||||
|     package_class = packages.get(args.name) |     spack.ignore_dependencies = args.ignore_dependencies | ||||||
|     package = package_class() |     for name in args.names: | ||||||
|     package.do_install() |         package = packages.get(name) | ||||||
|  |         package.do_install() | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								lib/spack/spack/cmd/list.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/spack/spack/cmd/list.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import spack | ||||||
|  | import spack.packages as packages | ||||||
|  | from spack.colify import colify | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def setup_parser(subparser): | ||||||
|  |     subparser.add_argument('-i', '--installed', action='store_true', dest='installed', | ||||||
|  |                            help='List installed packages for each platform along with versions.') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def list(args): | ||||||
|  |     if args.installed: | ||||||
|  |         pkgs = packages.installed_packages() | ||||||
|  |         for sys_type in pkgs: | ||||||
|  |             print "%s:" % sys_type | ||||||
|  |             package_vers = [] | ||||||
|  |             for pkg in pkgs[sys_type]: | ||||||
|  |                 pv = [pkg.name + "/" + v for v in pkg.installed_versions] | ||||||
|  |                 package_vers.extend(pv) | ||||||
|  |             colify(sorted(package_vers), indent=4) | ||||||
|  |     else: | ||||||
|  |         colify(packages.all_package_names()) | ||||||
| @@ -4,6 +4,5 @@ def setup_parser(subparser): | |||||||
|     subparser.add_argument('name', help="name of package to stage") |     subparser.add_argument('name', help="name of package to stage") | ||||||
|  |  | ||||||
| def stage(args): | def stage(args): | ||||||
|     package_class = packages.get(args.name) |     package = packages.get(args.name) | ||||||
|     package = package_class() |  | ||||||
|     package.do_stage() |     package.do_stage() | ||||||
|   | |||||||
| @@ -1,9 +1,20 @@ | |||||||
| import spack.packages as packages | import spack.packages as packages | ||||||
|  |  | ||||||
| def setup_parser(subparser): | def setup_parser(subparser): | ||||||
|     subparser.add_argument('name', help="name of package to uninstall") |     subparser.add_argument('names', nargs='+', help="name(s) of package(s) to uninstall") | ||||||
|  |     subparser.add_argument('-f', '--force', action='store_true', dest='force', | ||||||
|  |                            help="Ignore installed packages that depend on this one and remove it anyway.") | ||||||
|  |  | ||||||
| def uninstall(args): | def uninstall(args): | ||||||
|     package_class = packages.get(args.name) |     # get packages to uninstall as a list. | ||||||
|     package = package_class() |     pkgs = [packages.get(name) for name in args.names] | ||||||
|     package.do_uninstall() |  | ||||||
|  |     # Sort packages to be uninstalled by the number of installed dependents | ||||||
|  |     # This ensures we do things in the right order | ||||||
|  |     def num_installed_deps(pkg): | ||||||
|  |         return len(pkg.installed_dependents) | ||||||
|  |     pkgs.sort(key=num_installed_deps) | ||||||
|  |  | ||||||
|  |     # Uninstall packages in order now. | ||||||
|  |     for pkg in pkgs: | ||||||
|  |         pkg.do_uninstall() | ||||||
|   | |||||||
							
								
								
									
										159
									
								
								lib/spack/spack/colify.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								lib/spack/spack/colify.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | #!/usr/bin/env python | ||||||
|  | # | ||||||
|  | # colify | ||||||
|  | # By Todd Gamblin, tgamblin@llnl.gov | ||||||
|  | # | ||||||
|  | # Takes a list of items as input and finds a good columnization of them, | ||||||
|  | # similar to how gnu ls does.  You can pipe output to this script and | ||||||
|  | # get a tight display for it.  This supports both uniform-width and | ||||||
|  | # variable-width (tighter) columns. | ||||||
|  | # | ||||||
|  | # Run colify -h for more information. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | def get_terminal_size(): | ||||||
|  |     import os | ||||||
|  |  | ||||||
|  |     """Get the dimensions of the console.""" | ||||||
|  |     def ioctl_GWINSZ(fd): | ||||||
|  |         try: | ||||||
|  |             import fcntl, termios, struct | ||||||
|  |             cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) | ||||||
|  |         except: | ||||||
|  |             return | ||||||
|  |         return cr | ||||||
|  |     cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) | ||||||
|  |     if not cr: | ||||||
|  |         try: | ||||||
|  |             fd = os.open(os.ctermid(), os.O_RDONLY) | ||||||
|  |             cr = ioctl_GWINSZ(fd) | ||||||
|  |             os.close(fd) | ||||||
|  |         except: | ||||||
|  |             pass | ||||||
|  |     if not cr: | ||||||
|  |         cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) | ||||||
|  |  | ||||||
|  |     return int(cr[1]), int(cr[0]) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ColumnConfig: | ||||||
|  |     def __init__(self, cols): | ||||||
|  |         self.cols = cols | ||||||
|  |         self.line_length = 0 | ||||||
|  |         self.valid = True | ||||||
|  |         self.widths = [0] * cols | ||||||
|  |  | ||||||
|  |     def __repr__(self): | ||||||
|  |         attrs = [(a,getattr(self, a)) for a in dir(self) if not a.startswith("__")] | ||||||
|  |         return "<Config: %s>" % ", ".join("%s: %r" % a for a in attrs) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def config_variable_cols(elts, console_cols, padding): | ||||||
|  |     # Get a bound on the most columns we could possibly have. | ||||||
|  |     lengths = [len(elt) for elt in elts] | ||||||
|  |     max_cols = max(1, console_cols / (min(lengths) + padding)) | ||||||
|  |     max_cols = min(len(elts), max_cols) | ||||||
|  |  | ||||||
|  |     configs = [ColumnConfig(c) for c in xrange(1, max_cols+1)] | ||||||
|  |     for elt, length in enumerate(lengths): | ||||||
|  |         for i, conf in enumerate(configs): | ||||||
|  |             if conf.valid: | ||||||
|  |                 col = elt / ((len(elts) + i) / (i + 1)) | ||||||
|  |                 padded = length | ||||||
|  |                 if col < i: | ||||||
|  |                     padded += padding | ||||||
|  |  | ||||||
|  |                 if conf.widths[col] < padded: | ||||||
|  |                     conf.line_length += padded - conf.widths[col] | ||||||
|  |                     conf.widths[col] = padded | ||||||
|  |                     conf.valid = (conf.line_length < console_cols) | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         config = next(conf for conf in reversed(configs) if conf.valid) | ||||||
|  |     except StopIteration: | ||||||
|  |         # If nothing was valid the screen was too narrow -- just use 1 col. | ||||||
|  |         config = configs[0] | ||||||
|  |  | ||||||
|  |     config.widths = [w for w in config.widths if w != 0] | ||||||
|  |     config.cols = len(config.widths) | ||||||
|  |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def config_uniform_cols(elts, console_cols, padding): | ||||||
|  |     max_len = max(len(elt) for elt in elts) + padding | ||||||
|  |     cols = max(1, console_cols / max_len) | ||||||
|  |     cols = min(len(elts), cols) | ||||||
|  |     config = ColumnConfig(cols) | ||||||
|  |     config.widths = [max_len] * cols | ||||||
|  |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def colify(elts, **options): | ||||||
|  |     import sys | ||||||
|  |  | ||||||
|  |     # Get keyword arguments or set defaults | ||||||
|  |     output       = options.get("output", sys.stdout) | ||||||
|  |     indent       = options.get("indent", 0) | ||||||
|  |     padding      = options.get("padding", 2) | ||||||
|  |  | ||||||
|  |     # elts needs to be in an array so we can count the elements | ||||||
|  |     if not type(elts) == list: | ||||||
|  |         elts = list(elts) | ||||||
|  |  | ||||||
|  |     console_cols = options.get("cols", None) | ||||||
|  |     if not console_cols: | ||||||
|  |         console_cols, console_rows = get_terminal_size() | ||||||
|  |     elif type(console_cols) != int: | ||||||
|  |         raise ValueError("Number of columns must be an int") | ||||||
|  |     console_cols = max(1, console_cols - indent) | ||||||
|  |  | ||||||
|  |     method = options.get("method", "variable") | ||||||
|  |     if method == "variable": | ||||||
|  |         config = config_variable_cols(elts, console_cols, padding) | ||||||
|  |     elif method == "uniform": | ||||||
|  |         config = config_uniform_cols(elts, console_cols, padding) | ||||||
|  |     else: | ||||||
|  |         raise ValueError("method must be one of: " + allowed_methods) | ||||||
|  |  | ||||||
|  |     cols = config.cols | ||||||
|  |     formats = ["%%-%ds" % width for width in config.widths[:-1]] | ||||||
|  |     formats.append("%s")  # last column has no trailing space | ||||||
|  |  | ||||||
|  |     rows = (len(elts) + cols - 1) / cols | ||||||
|  |     rows_last_col = len(elts) % rows | ||||||
|  |  | ||||||
|  |     for row in xrange(rows): | ||||||
|  |         output.write(" " * indent) | ||||||
|  |         for col in xrange(cols): | ||||||
|  |             elt = col * rows + row | ||||||
|  |             output.write(formats[col] % elts[elt]) | ||||||
|  |  | ||||||
|  |         output.write("\n") | ||||||
|  |         row += 1 | ||||||
|  |         if row == rows_last_col: | ||||||
|  |             cols -= 1 | ||||||
|  |  | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     import optparse, sys | ||||||
|  |  | ||||||
|  |     cols, rows = get_terminal_size() | ||||||
|  |     parser = optparse.OptionParser() | ||||||
|  |     parser.add_option("-u", "--uniform", action="store_true", default=False, | ||||||
|  |                       help="Use uniformly sized columns instead of variable-size.") | ||||||
|  |     parser.add_option("-p", "--padding", metavar="PADDING", action="store", | ||||||
|  |                       type=int, default=2, help="Spaces to add between columns.  Default is 2.") | ||||||
|  |     parser.add_option("-i", "--indent", metavar="SPACES", action="store", | ||||||
|  |                       type=int, default=0, help="Indent the output by SPACES.  Default is 0.") | ||||||
|  |     parser.add_option("-w", "--width", metavar="COLS", action="store", | ||||||
|  |                       type=int, default=cols, help="Indent the output by SPACES.  Default is 0.") | ||||||
|  |     options, args = parser.parse_args() | ||||||
|  |  | ||||||
|  |     method = "variable" | ||||||
|  |     if options.uniform: | ||||||
|  |         method = "uniform" | ||||||
|  |  | ||||||
|  |     if sys.stdin.isatty(): | ||||||
|  |         parser.print_help() | ||||||
|  |         sys.exit(1) | ||||||
|  |     else: | ||||||
|  |         colify([line.strip() for line in sys.stdin], method=method, **options.__dict__) | ||||||
							
								
								
									
										52
									
								
								lib/spack/spack/compilation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lib/spack/spack/compilation.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | import os | ||||||
|  |  | ||||||
|  | def parse_rpaths(arguments): | ||||||
|  |     """argparse, for all its features, cannot understand most compilers' | ||||||
|  |        rpath arguments.  This handles '-Wl,', '-Xlinker', and '-R'""" | ||||||
|  |     linker_args = [] | ||||||
|  |     other_args = [] | ||||||
|  |  | ||||||
|  |     def get_next(arg, args): | ||||||
|  |         """Get an expected next value of an iterator, or die if it's not there""" | ||||||
|  |         try: | ||||||
|  |             return next(args) | ||||||
|  |         except StopIteration: | ||||||
|  |             # quietly ignore -rpath and -Xlinker without args. | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |     # Separate linker args from non-linker args | ||||||
|  |     args = iter(arguments) | ||||||
|  |     for arg in args: | ||||||
|  |         if arg.startswith('-Wl,'): | ||||||
|  |             sub_args = [sub for sub in arg.replace('-Wl,', '', 1).split(',')] | ||||||
|  |             linker_args.extend(sub_args) | ||||||
|  |         elif arg == '-Xlinker': | ||||||
|  |             target = get_next(arg, args) | ||||||
|  |             if target != None: | ||||||
|  |                 linker_args.append(target) | ||||||
|  |         else: | ||||||
|  |             other_args.append(arg) | ||||||
|  |  | ||||||
|  |     # Extract all the possible ways rpath can appear in linker args | ||||||
|  |     # and append non-rpaths to other_args | ||||||
|  |     rpaths = [] | ||||||
|  |     largs = iter(linker_args) | ||||||
|  |     for arg in largs: | ||||||
|  |         if arg == '-rpath': | ||||||
|  |             target = get_next(arg, largs) | ||||||
|  |             if target != None: | ||||||
|  |                 rpaths.append(target) | ||||||
|  |  | ||||||
|  |         elif arg.startswith('-R'): | ||||||
|  |             target = arg.replace('-R', '', 1) | ||||||
|  |             if not target: | ||||||
|  |                 target = get_next(arg, largs) | ||||||
|  |                 if target == None: break | ||||||
|  |  | ||||||
|  |             if os.path.isdir(target): | ||||||
|  |                 rpaths.append(target) | ||||||
|  |             else: | ||||||
|  |                 other_args.extend([arg, target]) | ||||||
|  |         else: | ||||||
|  |             other_args.append(arg) | ||||||
|  |     return rpaths, other_args | ||||||
							
								
								
									
										23
									
								
								lib/spack/spack/exception.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								lib/spack/spack/exception.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  | class SpackException(Exception): | ||||||
|  |     def __init__(self, message): | ||||||
|  |         self.message = message | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FailedDownloadException(SpackException): | ||||||
|  |     def __init__(self, url): | ||||||
|  |         super(FailedDownloadException, self).__init__("Failed to fetch file from URL: " + url) | ||||||
|  |         self.url = url | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class InvalidPackageNameException(SpackException): | ||||||
|  |     def __init__(self, name): | ||||||
|  |         super(InvalidPackageNameException, self).__init__("Invalid package name: " + name) | ||||||
|  |         self.name = name | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CommandFailedException(SpackException): | ||||||
|  |     def __init__(self, command): | ||||||
|  |         super(CommandFailedException, self).__init__("Failed to execute command: " + command) | ||||||
|  |         self.command = command | ||||||
| @@ -4,7 +4,8 @@ | |||||||
| from version import Version | from version import Version | ||||||
|  |  | ||||||
| import tty | import tty | ||||||
| from fileutils import * | from utils import * | ||||||
|  | from spack.exception import * | ||||||
|  |  | ||||||
| # This lives in $prefix/lib/spac/spack/__file__ | # This lives in $prefix/lib/spac/spack/__file__ | ||||||
| prefix = ancestor(__file__, 4) | prefix = ancestor(__file__, 4) | ||||||
| @@ -14,6 +15,7 @@ | |||||||
|  |  | ||||||
| # spack directory hierarchy | # spack directory hierarchy | ||||||
| lib_path      = new_path(prefix, "lib", "spack") | lib_path      = new_path(prefix, "lib", "spack") | ||||||
|  | env_path      = new_path(lib_path, "env") | ||||||
| module_path   = new_path(lib_path, "spack") | module_path   = new_path(lib_path, "spack") | ||||||
| packages_path = new_path(module_path, "packages") | packages_path = new_path(module_path, "packages") | ||||||
|  |  | ||||||
| @@ -23,20 +25,13 @@ | |||||||
| install_path  = new_path(prefix, "opt") | install_path  = new_path(prefix, "opt") | ||||||
|  |  | ||||||
| # Version information | # Version information | ||||||
| version = Version("0.1") | spack_version = Version("0.1") | ||||||
|  |  | ||||||
| # User's editor from the environment | # User's editor from the environment | ||||||
| editor = Executable(os.environ.get("EDITOR", "")) | editor = Executable(os.environ.get("EDITOR", "")) | ||||||
|  |  | ||||||
| # Curl tool for fetching files. | # Curl tool for fetching files. | ||||||
| curl = which("curl") | curl = which("curl", required=True) | ||||||
| if not curl: |  | ||||||
|     tty.die("spack requires curl.  Make sure it is in your path.") |  | ||||||
|  |  | ||||||
| make = which("make") |  | ||||||
| make.add_default_arg("-j%d" % multiprocessing.cpu_count()) |  | ||||||
| if not make: |  | ||||||
|     tty.die("spack requires make.  Make sure it is in your path.") |  | ||||||
|  |  | ||||||
| verbose = False | verbose = False | ||||||
| debug = False | debug = False | ||||||
|   | |||||||
| @@ -1,17 +1,86 @@ | |||||||
| import spack |  | ||||||
| from spack.fileutils import * |  | ||||||
|  |  | ||||||
| import re | import re | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | import string | ||||||
| import inspect | import inspect | ||||||
|  | import glob | ||||||
|  |  | ||||||
|  | import spack | ||||||
|  | from spack.utils import * | ||||||
|  | import spack.arch as arch | ||||||
|  | import spack.version as version | ||||||
|  | import spack.attr as attr | ||||||
|  |  | ||||||
|  | # Valid package names | ||||||
|  | valid_package = r'^[a-zA-Z0-9_-]*$' | ||||||
|  |  | ||||||
|  | # Don't allow consecutive [_-] in package names | ||||||
|  | invalid_package = r'[_-][_-]+' | ||||||
|  |  | ||||||
|  | instances = {} | ||||||
|  |  | ||||||
|  |  | ||||||
| def filename_for(package): | def valid_name(pkg): | ||||||
|  |     return re.match(valid_package, pkg) and not re.search(invalid_package, pkg) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_name(pkg): | ||||||
|  |     if not valid_name(pkg): | ||||||
|  |         raise spack.InvalidPackageNameException(pkg) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def filename_for(pkg): | ||||||
|     """Get the filename where a package name should be stored.""" |     """Get the filename where a package name should be stored.""" | ||||||
|     return new_path(spack.packages_path, "%s.py" % package.lower()) |     validate_name(pkg) | ||||||
|  |     return new_path(spack.packages_path, "%s.py" % pkg) | ||||||
|  |  | ||||||
|  |  | ||||||
| def get(name): | def installed_packages(**kwargs): | ||||||
|     file = filename_for(name) |     """Returns a dict from SysType to lists of Package objects.""" | ||||||
|  |     list_installed = kwargs.get('installed', False) | ||||||
|  |  | ||||||
|  |     pkgs = {} | ||||||
|  |     if not os.path.isdir(spack.install_path): | ||||||
|  |         return pkgs | ||||||
|  |  | ||||||
|  |     for sys_type in os.listdir(spack.install_path): | ||||||
|  |         sys_type = arch.SysType(sys_type) | ||||||
|  |         sys_path = new_path(spack.install_path, sys_type) | ||||||
|  |         pkgs[sys_type] = [get(pkg) for pkg in os.listdir(sys_path) | ||||||
|  |                           if os.path.isdir(new_path(sys_path, pkg))] | ||||||
|  |     return pkgs | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def all_package_names(): | ||||||
|  |     """Generator function for all packages.""" | ||||||
|  |     os.chdir(spack.packages_path) | ||||||
|  |     for name in glob.glob("*.py"): | ||||||
|  |         if name != '__init__.py': | ||||||
|  |             yield re.sub('.py$', '', name) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def all_packages(): | ||||||
|  |     for name in all_package_names(): | ||||||
|  |         yield get(name) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def class_for(pkg): | ||||||
|  |     """Get a name for the class the package file should contain.  Note that | ||||||
|  |        conflicts don't matter because the classes are in different modules. | ||||||
|  |     """ | ||||||
|  |     validate_name(pkg) | ||||||
|  |     class_name = string.capwords(pkg.replace('_', '-'), '-') | ||||||
|  |  | ||||||
|  |     # If a class starts with a number, prefix it with Number_ to make it a valid | ||||||
|  |     # Python class name. | ||||||
|  |     if re.match(r'^[0-9]', class_name): | ||||||
|  |         class_name = "Number_%s" % class_name | ||||||
|  |  | ||||||
|  |     return class_name | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_class(pkg): | ||||||
|  |     file = filename_for(pkg) | ||||||
|  |  | ||||||
|     if os.path.exists(file): |     if os.path.exists(file): | ||||||
|         if not os.path.isfile(file): |         if not os.path.isfile(file): | ||||||
| @@ -19,17 +88,63 @@ def get(name): | |||||||
|         if not os.access(file, os.R_OK): |         if not os.access(file, os.R_OK): | ||||||
|             tty.die("Cannot read '%s'!" % file) |             tty.die("Cannot read '%s'!" % file) | ||||||
|  |  | ||||||
|     class_name = name.capitalize() |     class_name = pkg.capitalize() | ||||||
|     try: |     try: | ||||||
|         module_name = "%s.%s" % (__name__, name) |         module_name = "%s.%s" % (__name__, pkg) | ||||||
|         module = __import__(module_name, fromlist=[class_name]) |         module = __import__(module_name, fromlist=[class_name]) | ||||||
|     except ImportError, e: |     except ImportError, e: | ||||||
|         tty.die("Error while importing %s.%s:\n%s" % (name, class_name, e.message)) |         tty.die("Error while importing %s.%s:\n%s" % (pkg, class_name, e.message)) | ||||||
|  |  | ||||||
|     klass = getattr(module, class_name) |     klass = getattr(module, class_name) | ||||||
|     if not inspect.isclass(klass): |     if not inspect.isclass(klass): | ||||||
|         tty.die("%s.%s is not a class" % (name, class_name)) |         tty.die("%s.%s is not a class" % (pkg, class_name)) | ||||||
|  |  | ||||||
|     return klass |     return klass | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get(pkg, arch=arch.sys_type()): | ||||||
|  |     key = (pkg, arch) | ||||||
|  |     if not key in instances: | ||||||
|  |         package_class = get_class(pkg) | ||||||
|  |         instances[key] = package_class(arch) | ||||||
|  |     return instances[key] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def compute_dependents(): | ||||||
|  |     """Reads in all package files and sets dependence information on | ||||||
|  |        Package objects in memory. | ||||||
|  |     """ | ||||||
|  |     for pkg in all_packages(): | ||||||
|  |         if pkg._dependents is None: | ||||||
|  |             pkg._dependents = [] | ||||||
|  |  | ||||||
|  |         for dep in pkg.dependencies: | ||||||
|  |             dpkg = get(dep.name) | ||||||
|  |             if dpkg._dependents is None: | ||||||
|  |                 dpkg._dependents = [] | ||||||
|  |             dpkg._dependents.append(pkg.name) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def graph_dependencies(out=sys.stdout): | ||||||
|  |     """Print out a graph of all the dependencies between package. | ||||||
|  |        Graph is in dot format.""" | ||||||
|  |     out.write('digraph G {\n') | ||||||
|  |     out.write('  label = "Spack Dependencies"\n') | ||||||
|  |     out.write('  labelloc = "b"\n') | ||||||
|  |     out.write('  rankdir = "LR"\n') | ||||||
|  |     out.write('  ranksep = "5"\n') | ||||||
|  |     out.write('\n') | ||||||
|  |  | ||||||
|  |     def quote(string): | ||||||
|  |         return '"%s"' % string | ||||||
|  |  | ||||||
|  |     deps = [] | ||||||
|  |     for pkg in all_packages(): | ||||||
|  |         out.write('  %-30s [label="%s"]\n' % (quote(pkg.name), pkg.name)) | ||||||
|  |         for dep in pkg.dependencies: | ||||||
|  |             deps.append((pkg.name, dep.name)) | ||||||
|  |     out.write('\n') | ||||||
|  |  | ||||||
|  |     for pair in deps: | ||||||
|  |         out.write('  "%s" -> "%s"\n' % pair) | ||||||
|  |     out.write('}\n') | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								lib/spack/spack/packages/libdwarf.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								lib/spack/spack/packages/libdwarf.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | from spack import * | ||||||
|  | import os | ||||||
|  |  | ||||||
|  | # Only build certain parts of dwarf because the other ones break. | ||||||
|  | dwarf_dirs = ['libdwarf', 'dwarfdump2'] | ||||||
|  |  | ||||||
|  | class Libdwarf(Package): | ||||||
|  |     homepage = "http://www.example.com" | ||||||
|  |     url      = "http://reality.sgiweb.org/davea/libdwarf-20130207.tar.gz" | ||||||
|  |     md5      = "64b42692e947d5180e162e46c689dfbf" | ||||||
|  |  | ||||||
|  |     depends_on("libelf") | ||||||
|  |  | ||||||
|  |     def clean(self): | ||||||
|  |         for dir in dwarf_dirs: | ||||||
|  |             with working_dir(dir): | ||||||
|  |                 if os.path.exists('Makefile'): | ||||||
|  |                     make('clean') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def install(self, prefix): | ||||||
|  |         make.add_default_arg('ARFLAGS=rcs') | ||||||
|  |  | ||||||
|  |         for dir in dwarf_dirs: | ||||||
|  |             with working_dir(dir): | ||||||
|  |                 #configure("--prefix=%s" % prefix, '--enable-shared') | ||||||
|  |                 configure("--prefix=%s" % prefix) | ||||||
|  |                 make() | ||||||
|  |  | ||||||
|  |         # Dwarf doesn't provide an install.  Annoying. | ||||||
|  |         mkdirp(bin, include, lib, man1) | ||||||
|  |         with working_dir('libdwarf'): | ||||||
|  |             install('libdwarf.a',  lib) | ||||||
|  |             #install('libdwarf.so', lib) | ||||||
|  |             install('libdwarf.h',  include) | ||||||
|  |             install('dwarf.h',     include) | ||||||
|  |  | ||||||
|  |         with working_dir('dwarfdump2'): | ||||||
|  |             install('dwarfdump',     bin) | ||||||
|  |             install('dwarfdump.conf', lib) | ||||||
|  |             install('dwarfdump.1',    man1) | ||||||
							
								
								
									
										13
									
								
								lib/spack/spack/packages/libelf.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/spack/spack/packages/libelf.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from spack import * | ||||||
|  |  | ||||||
|  | class Libelf(Package): | ||||||
|  |     homepage = "http://www.mr511.de/software/english.html" | ||||||
|  |     url      = "http://www.mr511.de/software/libelf-0.8.13.tar.gz" | ||||||
|  |     md5      = "4136d7b4c04df68b686570afa26988ac" | ||||||
|  |  | ||||||
|  |     def install(self, prefix): | ||||||
|  |         configure("--prefix=%s" % prefix, | ||||||
|  |                   "--disable-dependency-tracking", | ||||||
|  |                   "--disable-debug") | ||||||
|  |         make() | ||||||
|  |         make("install") | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| import os | import os | ||||||
|  | import re | ||||||
| import shutil | import shutil | ||||||
|  |  | ||||||
| import spack | import spack | ||||||
|  | import packages | ||||||
| import tty | import tty | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -11,8 +13,9 @@ def ensure_access(dir=spack.stage_path): | |||||||
|  |  | ||||||
|  |  | ||||||
| class Stage(object): | class Stage(object): | ||||||
|     def __init__(self, stage_name): |     def __init__(self, stage_name, url): | ||||||
|         self.stage_name = stage_name |         self.stage_name = stage_name | ||||||
|  |         self.url = url | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def path(self): |     def path(self): | ||||||
| @@ -30,7 +33,15 @@ def setup(self): | |||||||
|  |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def archive_path(self): |     def archive_file(self): | ||||||
|  |         path = os.path.join(self.path, os.path.basename(self.url)) | ||||||
|  |         if os.path.exists(path): | ||||||
|  |             return path | ||||||
|  |         return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def expanded_archive_path(self): | ||||||
|         """"Returns the path to the expanded archive directory if it's expanded; |         """"Returns the path to the expanded archive directory if it's expanded; | ||||||
|             None if the archive hasn't been expanded. |             None if the archive hasn't been expanded. | ||||||
|         """ |         """ | ||||||
| @@ -43,17 +54,54 @@ def archive_path(self): | |||||||
|  |  | ||||||
|     def chdir(self): |     def chdir(self): | ||||||
|         """Changes directory to the stage path.  Or dies if it is not set up.""" |         """Changes directory to the stage path.  Or dies if it is not set up.""" | ||||||
|  |         self.setup() | ||||||
|         if os.path.isdir(self.path): |         if os.path.isdir(self.path): | ||||||
|             os.chdir(self.path) |             os.chdir(self.path) | ||||||
|         else: |         else: | ||||||
|             tty.die("Attempt to chdir to stage before setup.") |             tty.die("Setup failed: no such directory: " + self.path) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def fetch(self): | ||||||
|  |         """Downloads the file at URL to the stage.  Returns true if it was downloaded, | ||||||
|  |            false if it already existed.""" | ||||||
|  |         self.chdir() | ||||||
|  |         if self.archive_file: | ||||||
|  |             tty.msg("Already downloaded %s." % self.archive_file) | ||||||
|  |  | ||||||
|  |         else: | ||||||
|  |             tty.msg("Fetching %s" % self.url) | ||||||
|  |  | ||||||
|  |             # Run curl but grab the mime type from the http headers | ||||||
|  |             headers = spack.curl('-#', '-O', '-D', '-', self.url, return_output=True) | ||||||
|  |  | ||||||
|  |             # output this if we somehow got an HTML file rather than the archive we | ||||||
|  |             # asked for. | ||||||
|  |             if re.search(r'Content-Type: text/html', headers): | ||||||
|  |                 tty.warn("The contents of '%s' look like HTML.  The checksum will "+ | ||||||
|  |                          "likely fail.  Use 'spack clean %s' to delete this file. " | ||||||
|  |                          "The fix the gateway issue and install again." % (self.archive_file, self.name)) | ||||||
|  |  | ||||||
|  |         if not self.archive_file: | ||||||
|  |             raise FailedDownloadException(url) | ||||||
|  |  | ||||||
|  |         return self.archive_file | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def expand_archive(self): | ||||||
|  |         self.chdir() | ||||||
|  |  | ||||||
|  |         if not self.archive_file: | ||||||
|  |             tty.die("Attempt to expand archive before fetching.") | ||||||
|  |  | ||||||
|  |         decompress = spack.decompressor_for(self.archive_file) | ||||||
|  |         decompress(self.archive_file) | ||||||
|  |  | ||||||
|  |  | ||||||
|     def chdir_to_archive(self): |     def chdir_to_archive(self): | ||||||
|         """Changes directory to the expanded archive directory if it exists. |         """Changes directory to the expanded archive directory if it exists. | ||||||
|            Dies with an error otherwise. |            Dies with an error otherwise. | ||||||
|         """ |         """ | ||||||
|         path = self.archive_path |         path = self.expanded_archive_path | ||||||
|         if not path: |         if not path: | ||||||
|             tty.die("Attempt to chdir before expanding archive.") |             tty.die("Attempt to chdir before expanding archive.") | ||||||
|         else: |         else: | ||||||
| @@ -62,6 +110,16 @@ def chdir_to_archive(self): | |||||||
|                 tty.die("Archive was empty for '%s'" % self.name) |                 tty.die("Archive was empty for '%s'" % self.name) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def restage(self): | ||||||
|  |         """Removes the expanded archive path if it exists, then re-expands the archive.""" | ||||||
|  |         if not self.archive_file: | ||||||
|  |             tty.die("Attempt to restage when not staged.") | ||||||
|  |  | ||||||
|  |         if self.expanded_archive_path: | ||||||
|  |             shutil.rmtree(self.expanded_archive_path, True) | ||||||
|  |         self.expand_archive() | ||||||
|  |  | ||||||
|  |  | ||||||
|     def destroy(self): |     def destroy(self): | ||||||
|         """Blows away the stage directory.  Can always call setup() again.""" |         """Blows away the stage directory.  Can always call setup() again.""" | ||||||
|         if os.path.exists(self.path): |         if os.path.exists(self.path): | ||||||
|   | |||||||
| @@ -10,20 +10,24 @@ | |||||||
| class VersionTest(unittest.TestCase): | class VersionTest(unittest.TestCase): | ||||||
|  |  | ||||||
|     def assert_not_detected(self, string): |     def assert_not_detected(self, string): | ||||||
|         self.assertIsNone(version.parse(string)) |         name, v = version.parse(string) | ||||||
|  |         self.assertIsNone(v) | ||||||
|  |  | ||||||
|  |     def assert_detected(self, name, v, string): | ||||||
|  |         parsed_name, parsed_v = version.parse(string) | ||||||
|  |         self.assertEqual(parsed_name, name) | ||||||
|  |         self.assertEqual(parsed_v, version.Version(v)) | ||||||
|  |  | ||||||
|     def assert_detected(self, v, string): |  | ||||||
|         self.assertEqual(v, version.parse(string)) |  | ||||||
|  |  | ||||||
|     def test_wwwoffle_version(self): |     def test_wwwoffle_version(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '2.9h', 'http://www.gedanken.demon.co.uk/download-wwwoffle/wwwoffle-2.9h.tgz') |             'wwwoffle', '2.9h', 'http://www.gedanken.demon.co.uk/download-wwwoffle/wwwoffle-2.9h.tgz') | ||||||
|  |  | ||||||
|     def test_version_sourceforge_download(self): |     def test_version_sourceforge_download(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.21', 'http://sourceforge.net/foo_bar-1.21.tar.gz/download') |             'foo_bar', '1.21', 'http://sourceforge.net/foo_bar-1.21.tar.gz/download') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.21', 'http://sf.net/foo_bar-1.21.tar.gz/download') |             'foo_bar', '1.21', 'http://sf.net/foo_bar-1.21.tar.gz/download') | ||||||
|  |  | ||||||
|     def test_no_version(self): |     def test_no_version(self): | ||||||
|         self.assert_not_detected('http://example.com/blah.tar') |         self.assert_not_detected('http://example.com/blah.tar') | ||||||
| @@ -31,159 +35,158 @@ def test_no_version(self): | |||||||
|  |  | ||||||
|     def test_version_all_dots(self): |     def test_version_all_dots(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.14','http://example.com/foo.bar.la.1.14.zip') |             'foo.bar.la', '1.14','http://example.com/foo.bar.la.1.14.zip') | ||||||
|  |  | ||||||
|     def test_version_underscore_separator(self): |     def test_version_underscore_separator(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.1', 'http://example.com/grc_1.1.tar.gz') |             'grc', '1.1', 'http://example.com/grc_1.1.tar.gz') | ||||||
|  |  | ||||||
|     def test_boost_version_style(self): |     def test_boost_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.39.0', 'http://example.com/boost_1_39_0.tar.bz2') |             'boost', '1.39.0', 'http://example.com/boost_1_39_0.tar.bz2') | ||||||
|  |  | ||||||
|     def test_erlang_version_style(self): |     def test_erlang_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             'R13B', 'http://erlang.org/download/otp_src_R13B.tar.gz') |             'otp', 'R13B', 'http://erlang.org/download/otp_src_R13B.tar.gz') | ||||||
|  |  | ||||||
|     def test_another_erlang_version_style(self): |     def test_another_erlang_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             'R15B01', 'https://github.com/erlang/otp/tarball/OTP_R15B01') |             'otp', 'R15B01', 'https://github.com/erlang/otp/tarball/OTP_R15B01') | ||||||
|  |  | ||||||
|     def test_yet_another_erlang_version_style(self): |     def test_yet_another_erlang_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             'R15B03-1', 'https://github.com/erlang/otp/tarball/OTP_R15B03-1') |             'otp', 'R15B03-1', 'https://github.com/erlang/otp/tarball/OTP_R15B03-1') | ||||||
|  |  | ||||||
|     def test_p7zip_version_style(self): |     def test_p7zip_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '9.04', |             'p7zip', '9.04', 'http://kent.dl.sourceforge.net/sourceforge/p7zip/p7zip_9.04_src_all.tar.bz2') | ||||||
|             'http://kent.dl.sourceforge.net/sourceforge/p7zip/p7zip_9.04_src_all.tar.bz2') |  | ||||||
|  |  | ||||||
|     def test_new_github_style(self): |     def test_new_github_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.1.4', 'https://github.com/sam-github/libnet/tarball/libnet-1.1.4') |             'libnet', '1.1.4', 'https://github.com/sam-github/libnet/tarball/libnet-1.1.4') | ||||||
|  |  | ||||||
|     def test_gloox_beta_style(self): |     def test_gloox_beta_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.0-beta7', 'http://camaya.net/download/gloox-1.0-beta7.tar.bz2') |             'gloox', '1.0-beta7', 'http://camaya.net/download/gloox-1.0-beta7.tar.bz2') | ||||||
|  |  | ||||||
|     def test_sphinx_beta_style(self): |     def test_sphinx_beta_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.10-beta', 'http://sphinxsearch.com/downloads/sphinx-1.10-beta.tar.gz') |             'sphinx', '1.10-beta', 'http://sphinxsearch.com/downloads/sphinx-1.10-beta.tar.gz') | ||||||
|  |  | ||||||
|     def test_astyle_verson_style(self): |     def test_astyle_verson_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.23', 'http://kent.dl.sourceforge.net/sourceforge/astyle/astyle_1.23_macosx.tar.gz') |             'astyle', '1.23', 'http://kent.dl.sourceforge.net/sourceforge/astyle/astyle_1.23_macosx.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_dos2unix(self): |     def test_version_dos2unix(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '3.1', 'http://www.sfr-fresh.com/linux/misc/dos2unix-3.1.tar.gz') |             'dos2unix', '3.1', 'http://www.sfr-fresh.com/linux/misc/dos2unix-3.1.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_internal_dash(self): |     def test_version_internal_dash(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.1-2', 'http://example.com/foo-arse-1.1-2.tar.gz') |             'foo-arse', '1.1-2', 'http://example.com/foo-arse-1.1-2.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_single_digit(self): |     def test_version_single_digit(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '45', 'http://example.com/foo_bar.45.tar.gz') |             'foo_bar', '45', 'http://example.com/foo_bar.45.tar.gz') | ||||||
|  |  | ||||||
|     def test_noseparator_single_digit(self): |     def test_noseparator_single_digit(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '45', 'http://example.com/foo_bar45.tar.gz') |             'foo_bar', '45', 'http://example.com/foo_bar45.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_developer_that_hates_us_format(self): |     def test_version_developer_that_hates_us_format(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.2.3', 'http://example.com/foo-bar-la.1.2.3.tar.gz') |             'foo-bar-la', '1.2.3', 'http://example.com/foo-bar-la.1.2.3.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_regular(self): |     def test_version_regular(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.21', 'http://example.com/foo_bar-1.21.tar.gz') |             'foo_bar', '1.21', 'http://example.com/foo_bar-1.21.tar.gz') | ||||||
|  |  | ||||||
|     def test_version_github(self): |     def test_version_github(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.0.5', 'http://github.com/lloyd/yajl/tarball/1.0.5') |             'yajl', '1.0.5', 'http://github.com/lloyd/yajl/tarball/1.0.5') | ||||||
|  |  | ||||||
|     def test_version_github_with_high_patch_number(self): |     def test_version_github_with_high_patch_number(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.2.34', 'http://github.com/lloyd/yajl/tarball/v1.2.34') |             'yajl', '1.2.34', 'http://github.com/lloyd/yajl/tarball/v1.2.34') | ||||||
|  |  | ||||||
|     def test_yet_another_version(self): |     def test_yet_another_version(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '0.15.1b', 'http://example.com/mad-0.15.1b.tar.gz') |             'mad', '0.15.1b', 'http://example.com/mad-0.15.1b.tar.gz') | ||||||
|  |  | ||||||
|     def test_lame_version_style(self): |     def test_lame_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '398-2', 'http://kent.dl.sourceforge.net/sourceforge/lame/lame-398-2.tar.gz') |             'lame', '398-2', 'http://kent.dl.sourceforge.net/sourceforge/lame/lame-398-2.tar.gz') | ||||||
|  |  | ||||||
|     def test_ruby_version_style(self): |     def test_ruby_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.9.1-p243', 'ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz') |             'ruby', '1.9.1-p243', 'ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz') | ||||||
|  |  | ||||||
|     def test_omega_version_style(self): |     def test_omega_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '0.80.2', 'http://www.alcyone.com/binaries/omega/omega-0.80.2-src.tar.gz') |             'omega', '0.80.2', 'http://www.alcyone.com/binaries/omega/omega-0.80.2-src.tar.gz') | ||||||
|  |  | ||||||
|     def test_rc_style(self): |     def test_rc_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.2.2rc1', 'http://downloads.xiph.org/releases/vorbis/libvorbis-1.2.2rc1.tar.bz2') |             'libvorbis', '1.2.2rc1', 'http://downloads.xiph.org/releases/vorbis/libvorbis-1.2.2rc1.tar.bz2') | ||||||
|  |  | ||||||
|     def test_dash_rc_style(self): |     def test_dash_rc_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.8.0-rc1', 'http://ftp.mozilla.org/pub/mozilla.org/js/js-1.8.0-rc1.tar.gz') |             'js', '1.8.0-rc1', 'http://ftp.mozilla.org/pub/mozilla.org/js/js-1.8.0-rc1.tar.gz') | ||||||
|  |  | ||||||
|     def test_angband_version_style(self): |     def test_angband_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '3.0.9b', 'http://rephial.org/downloads/3.0/angband-3.0.9b-src.tar.gz') |             'angband', '3.0.9b', 'http://rephial.org/downloads/3.0/angband-3.0.9b-src.tar.gz') | ||||||
|  |  | ||||||
|     def test_stable_suffix(self): |     def test_stable_suffix(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.4.14b', 'http://www.monkey.org/~provos/libevent-1.4.14b-stable.tar.gz') |             'libevent', '1.4.14b', 'http://www.monkey.org/~provos/libevent-1.4.14b-stable.tar.gz') | ||||||
|  |  | ||||||
|     def test_debian_style_1(self): |     def test_debian_style_1(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '3.03', 'http://ftp.de.debian.org/debian/pool/main/s/sl/sl_3.03.orig.tar.gz') |             'sl', '3.03', 'http://ftp.de.debian.org/debian/pool/main/s/sl/sl_3.03.orig.tar.gz') | ||||||
|  |  | ||||||
|     def test_debian_style_2(self): |     def test_debian_style_2(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.01b', 'http://ftp.de.debian.org/debian/pool/main/m/mmv/mmv_1.01b.orig.tar.gz') |             'mmv', '1.01b', 'http://ftp.de.debian.org/debian/pool/main/m/mmv/mmv_1.01b.orig.tar.gz') | ||||||
|  |  | ||||||
|     def test_imagemagick_style(self): |     def test_imagemagick_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '6.7.5-7', 'http://downloads.sf.net/project/machomebrew/mirror/ImageMagick-6.7.5-7.tar.bz2') |             'ImageMagick', '6.7.5-7', 'http://downloads.sf.net/project/machomebrew/mirror/ImageMagick-6.7.5-7.tar.bz2') | ||||||
|  |  | ||||||
|     def test_dash_version_dash_style(self): |     def test_dash_version_dash_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '3.4', 'http://www.antlr.org/download/antlr-3.4-complete.jar') |             'antlr', '3.4', 'http://www.antlr.org/download/antlr-3.4-complete.jar') | ||||||
|  |  | ||||||
|     def test_apache_version_style(self): |     def test_apache_version_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.2.0-rc2', 'http://www.apache.org/dyn/closer.cgi?path=/cassandra/1.2.0/apache-cassandra-1.2.0-rc2-bin.tar.gz') |             'apache-cassandra', '1.2.0-rc2', 'http://www.apache.org/dyn/closer.cgi?path=/cassandra/1.2.0/apache-cassandra-1.2.0-rc2-bin.tar.gz') | ||||||
|  |  | ||||||
|     def test_jpeg_style(self): |     def test_jpeg_style(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '8d', 'http://www.ijg.org/files/jpegsrc.v8d.tar.gz') |             'jpegsrc', '8d', 'http://www.ijg.org/files/jpegsrc.v8d.tar.gz') | ||||||
|  |  | ||||||
|     def test_more_versions(self): |     def test_more_versions(self): | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.4.1', 'http://pypy.org/download/pypy-1.4.1-osx.tar.bz2') |             'pypy', '1.4.1', 'http://pypy.org/download/pypy-1.4.1-osx.tar.bz2') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '0.9.8s', 'http://www.openssl.org/source/openssl-0.9.8s.tar.gz') |             'openssl', '0.9.8s', 'http://www.openssl.org/source/openssl-0.9.8s.tar.gz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.5E', 'ftp://ftp.visi.com/users/hawkeyd/X/Xaw3d-1.5E.tar.gz') |             'Xaw3d', '1.5E', 'ftp://ftp.visi.com/users/hawkeyd/X/Xaw3d-1.5E.tar.gz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '2.1.0beta', 'http://downloads.sourceforge.net/project/fann/fann/2.1.0beta/fann-2.1.0beta.zip') |             'fann', '2.1.0beta', 'http://downloads.sourceforge.net/project/fann/fann/2.1.0beta/fann-2.1.0beta.zip') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '2.0.1', 'ftp://iges.org/grads/2.0/grads-2.0.1-bin-darwin9.8-intel.tar.gz') |             'grads', '2.0.1', 'ftp://iges.org/grads/2.0/grads-2.0.1-bin-darwin9.8-intel.tar.gz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '2.08', 'http://haxe.org/file/haxe-2.08-osx.tar.gz') |             'haxe', '2.08', 'http://haxe.org/file/haxe-2.08-osx.tar.gz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '2007f', 'ftp://ftp.cac.washington.edu/imap/imap-2007f.tar.gz') |             'imap', '2007f', 'ftp://ftp.cac.washington.edu/imap/imap-2007f.tar.gz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '3.3.12ga7', 'http://sourceforge.net/projects/x3270/files/x3270/3.3.12ga7/suite3270-3.3.12ga7-src.tgz') |             'suite3270', '3.3.12ga7', 'http://sourceforge.net/projects/x3270/files/x3270/3.3.12ga7/suite3270-3.3.12ga7-src.tgz') | ||||||
|         self.assert_detected( |         self.assert_detected( | ||||||
|             '1.3.6p2', 'http://synergy.googlecode.com/files/synergy-1.3.6p2-MacOSX-Universal.zip') |             'synergy', '1.3.6p2', 'http://synergy.googlecode.com/files/synergy-1.3.6p2-MacOSX-Universal.zip') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     unittest.main() |     unittest.main(failfast=True) | ||||||
|   | |||||||
| @@ -32,6 +32,11 @@ def msg(msg, *args, **kwargs): | |||||||
|     print "{}==>{} {}{}".format(color, white, str(msg), reset) |     print "{}==>{} {}{}".format(color, white, str(msg), reset) | ||||||
|     for arg in args: print indent + str(arg) |     for arg in args: print indent + str(arg) | ||||||
|  |  | ||||||
|  | def info(msg, *args, **kwargs): | ||||||
|  |     color = kwargs.get("color", blue) | ||||||
|  |     print "{}==>{} {}".format(color, reset, str(msg)) | ||||||
|  |     for arg in args: print indent + str(arg) | ||||||
|  |  | ||||||
| def verbose(*args): | def verbose(*args): | ||||||
|     if spack.verbose: msg(*args, color=green) |     if spack.verbose: msg(*args, color=green) | ||||||
|  |  | ||||||
| @@ -46,8 +51,8 @@ def warn(msg, *args): | |||||||
|     print "{}Warning{}: {}".format(yellow, reset, str(msg)) |     print "{}Warning{}: {}".format(yellow, reset, str(msg)) | ||||||
|     for arg in args: print indent + str(arg) |     for arg in args: print indent + str(arg) | ||||||
|  |  | ||||||
| def die(msg): | def die(msg, *args): | ||||||
|     error(msg) |     error(msg, *args) | ||||||
|     sys.exit(1) |     sys.exit(1) | ||||||
|  |  | ||||||
| def pkg(msg): | def pkg(msg): | ||||||
|   | |||||||
| @@ -1,8 +1,12 @@ | |||||||
| import os | import os | ||||||
| import subprocess |  | ||||||
| import re | import re | ||||||
|  | import errno | ||||||
|  | import shutil | ||||||
|  | import subprocess | ||||||
|  | import multiprocessing | ||||||
| from itertools import product | from itertools import product | ||||||
| from contextlib import closing | import functools | ||||||
|  | from contextlib import closing, contextmanager | ||||||
| 
 | 
 | ||||||
| import tty | import tty | ||||||
| 
 | 
 | ||||||
| @@ -14,17 +18,85 @@ | |||||||
| ALLOWED_ARCHIVE_TYPES = [".".join(l) for l in product(PRE_EXTS, EXTS)] + EXTS | ALLOWED_ARCHIVE_TYPES = [".".join(l) for l in product(PRE_EXTS, EXTS)] + EXTS | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def memoized(obj): | ||||||
|  |     """Decorator that caches the results of a function, storing them | ||||||
|  |        in an attribute of that function.""" | ||||||
|  |     cache = obj.cache = {} | ||||||
|  |     @functools.wraps(obj) | ||||||
|  |     def memoizer(*args, **kwargs): | ||||||
|  |         if args not in cache: | ||||||
|  |             cache[args] = obj(*args, **kwargs) | ||||||
|  |             return cache[args] | ||||||
|  |     return memoizer | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def make_make(): | ||||||
|  |     """Gets a make set up with the proper default arguments.""" | ||||||
|  |     make = which('make', required=True) | ||||||
|  |     if not env_flag("SPACK_NO_PARALLEL_MAKE"): | ||||||
|  |         make.add_default_arg("-j%d" % multiprocessing.cpu_count()) | ||||||
|  |     return make | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def install(src, dest): | ||||||
|  |     tty.info("Installing %s to %s" % (src, dest)) | ||||||
|  |     shutil.copy(src, dest) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @contextmanager | ||||||
|  | def working_dir(dirname): | ||||||
|  |     orig_dir = os.getcwd() | ||||||
|  |     os.chdir(dirname) | ||||||
|  |     yield | ||||||
|  |     os.chdir(orig_dir) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def mkdirp(*paths): | ||||||
|  |     for path in paths: | ||||||
|  |         if not os.path.exists(path): | ||||||
|  |             os.makedirs(path) | ||||||
|  |         elif not os.path.isdir(path): | ||||||
|  |             raise OSError(errno.EEXIST, "File alredy exists", path) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def env_flag(name): | ||||||
|  |     if name in os.environ: | ||||||
|  |         return os.environ[name].lower() == "true" | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def path_prepend(var_name, *directories): | ||||||
|  |     path = os.environ.get(var_name, "") | ||||||
|  |     path_str = ":".join(str(dir) for dir in directories) | ||||||
|  |     if path == "": | ||||||
|  |         os.environ[var_name] = path_str | ||||||
|  |     else: | ||||||
|  |         os.environ[var_name] = "%s:%s" % (path_str, path) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def pop_keys(dictionary, *keys): | ||||||
|  |     for key in keys: | ||||||
|  |         if key in dictionary: | ||||||
|  |             dictionary.pop(key) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def remove_items(item_list, *items): | ||||||
|  |     for item in items: | ||||||
|  |         if item in item_list: | ||||||
|  |             item_list.remove(item) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def has_whitespace(string): | def has_whitespace(string): | ||||||
|     return re.search(r'\s', string) |     return re.search(r'\s', string) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def new_path(prefix, *args): | def new_path(prefix, *args): | ||||||
|     path=prefix |     path=str(prefix) | ||||||
|     for elt in args: |     for elt in args: | ||||||
|         path = os.path.join(path, elt) |         path = os.path.join(path, str(elt)) | ||||||
| 
 | 
 | ||||||
|     if has_whitespace(path): |     if has_whitespace(path): | ||||||
|         tty.die("Invalid path: '%s'.  Use a path without whitespace.") |         tty.die("Invalid path: '%s'.  Use a path without whitespace." % path) | ||||||
| 
 | 
 | ||||||
|     return path |     return path | ||||||
| 
 | 
 | ||||||
| @@ -48,6 +120,7 @@ def add_default_arg(self, arg): | |||||||
|     def __call__(self, *args, **kwargs): |     def __call__(self, *args, **kwargs): | ||||||
|         """Run the executable with subprocess.check_output, return output.""" |         """Run the executable with subprocess.check_output, return output.""" | ||||||
|         return_output = kwargs.get("return_output", False) |         return_output = kwargs.get("return_output", False) | ||||||
|  |         fail_on_error = kwargs.get("fail_on_error", True) | ||||||
| 
 | 
 | ||||||
|         quoted_args = [arg for arg in args if re.search(r'^"|^\'|"$|\'$', arg)] |         quoted_args = [arg for arg in args if re.search(r'^"|^\'|"$|\'$', arg)] | ||||||
|         if quoted_args: |         if quoted_args: | ||||||
| @@ -61,24 +134,30 @@ def __call__(self, *args, **kwargs): | |||||||
| 
 | 
 | ||||||
|         if return_output: |         if return_output: | ||||||
|             return subprocess.check_output(cmd) |             return subprocess.check_output(cmd) | ||||||
|         else: |         elif fail_on_error: | ||||||
|             return subprocess.check_call(cmd) |             return subprocess.check_call(cmd) | ||||||
|  |         else: | ||||||
|  |             return subprocess.call(cmd) | ||||||
| 
 | 
 | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return "<exe: %s>" % self.exe |         return "<exe: %s>" % self.exe | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def which(name, path=None): | def which(name, **kwargs): | ||||||
|     """Finds an executable in the path like command-line which.""" |     """Finds an executable in the path like command-line which.""" | ||||||
|  |     path     = kwargs.get('path', os.environ.get('PATH', '').split(os.pathsep)) | ||||||
|  |     required = kwargs.get('required', False) | ||||||
|  | 
 | ||||||
|     if not path: |     if not path: | ||||||
|         path = os.environ.get('PATH', '').split(os.pathsep) |         path = [] | ||||||
|     if not path: |  | ||||||
|         return None |  | ||||||
| 
 | 
 | ||||||
|     for dir in path: |     for dir in path: | ||||||
|         exe = os.path.join(dir, name) |         exe = os.path.join(dir, name) | ||||||
|         if os.access(exe, os.X_OK): |         if os.access(exe, os.X_OK): | ||||||
|             return Executable(exe) |             return Executable(exe) | ||||||
|  | 
 | ||||||
|  |     if required: | ||||||
|  |         tty.die("spack requires %s.  Make sure it is in your path." % name) | ||||||
|     return None |     return None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -94,10 +173,9 @@ def stem(path): | |||||||
| 
 | 
 | ||||||
| def decompressor_for(path): | def decompressor_for(path): | ||||||
|     """Get the appropriate decompressor for a path.""" |     """Get the appropriate decompressor for a path.""" | ||||||
|     if which("tar"): |     tar = which('tar', required=True) | ||||||
|         return Executable("tar -xf") |     tar.add_default_arg('-xf') | ||||||
|     else: |     return tar | ||||||
|         tty.die("spack requires tar.  Make sure it's on your path.") |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def md5(filename, block_size=2**20): | def md5(filename, block_size=2**20): | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| import tty | import tty | ||||||
| from fileutils import ALLOWED_ARCHIVE_TYPES | from utils import ALLOWED_ARCHIVE_TYPES | ||||||
| from urlparse import urlparse | from urlparse import urlparse | ||||||
|  |  | ||||||
| ALLOWED_SCHEMES    = ["http", "https", "ftp"] | ALLOWED_SCHEMES    = ["http", "https", "ftp"] | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import os | import os | ||||||
| import re | import re | ||||||
|  |  | ||||||
| import fileutils | import utils | ||||||
|  |  | ||||||
| class Version(object): | class Version(object): | ||||||
|     """Class to represent versions""" |     """Class to represent versions""" | ||||||
| @@ -48,16 +48,16 @@ def intify(part): | |||||||
|     return tuple(intify(v) for v in re.split(r'[_.-]+', v)) |     return tuple(intify(v) for v in re.split(r'[_.-]+', v)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def parse(spec): | def parse_version(spec): | ||||||
|     """Try to extract a version from a filename.  This is taken largely from |     """Try to extract a version from a filename or URL.  This is taken | ||||||
|     Homebrew's Version class.""" |     largely from Homebrew's Version class.""" | ||||||
|  |  | ||||||
|     if os.path.isdir(spec): |     if os.path.isdir(spec): | ||||||
|         stem = os.path.basename(spec) |         stem = os.path.basename(spec) | ||||||
|     elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', spec): |     elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', spec): | ||||||
|         stem = fileutils.stem(os.path.dirname(spec)) |         stem = utils.stem(os.path.dirname(spec)) | ||||||
|     else: |     else: | ||||||
|         stem = fileutils.stem(spec) |         stem = utils.stem(spec) | ||||||
|  |  | ||||||
|     version_types = [ |     version_types = [ | ||||||
|         # GitHub tarballs, e.g. v1.2.3 |         # GitHub tarballs, e.g. v1.2.3 | ||||||
| @@ -115,12 +115,36 @@ def parse(spec): | |||||||
|         # e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz |         # e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz | ||||||
|         (r'\.v(\d+[a-z]?)', stem)] |         (r'\.v(\d+[a-z]?)', stem)] | ||||||
|  |  | ||||||
|     for type in version_types: |     for vtype in version_types: | ||||||
|         regex, match_string = type[:2] |         regex, match_string = vtype[:2] | ||||||
|         match = re.search(regex, match_string) |         match = re.search(regex, match_string) | ||||||
|         if match and match.group(1) is not None: |         if match and match.group(1) is not None: | ||||||
|             if type[2:]: |             if vtype[2:]: | ||||||
|                 return Version(type[2](match.group(1))) |                 return Version(vtype[2](match.group(1))) | ||||||
|             else: |             else: | ||||||
|                 return Version(match.group(1)) |                 return Version(match.group(1)) | ||||||
|     return None |     return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def parse_name(spec, ver=None): | ||||||
|  |     if ver is None: | ||||||
|  |         ver = parse_version(spec) | ||||||
|  |  | ||||||
|  |     ntypes = (r'/sourceforge/([^/]+)/', | ||||||
|  |               r'/([^/]+)/(tarball|zipball)/', | ||||||
|  |               r'/([^/]+)[_.-](bin|dist|stable|src|sources)[_.-]%s' % ver, | ||||||
|  |               r'/([^/]+)[_.-]v?%s' % ver, | ||||||
|  |               r'/([^/]+)%s' % ver, | ||||||
|  |               r'^([^/]+)[_.-]v?%s' % ver, | ||||||
|  |               r'^([^/]+)%s' % ver) | ||||||
|  |  | ||||||
|  |     for nt in ntypes: | ||||||
|  |         match = re.search(nt, spec) | ||||||
|  |         if match: | ||||||
|  |             return match.group(1) | ||||||
|  |     return None | ||||||
|  |  | ||||||
|  | def parse(spec): | ||||||
|  |     ver = parse_version(spec) | ||||||
|  |     name = parse_name(spec, ver) | ||||||
|  |     return (name, ver) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Todd Gamblin
					Todd Gamblin