Improved binary relocation: error checking and reporting (#7314)
Fixes #7237 Fixes #6404 Fixes #6418 Fixes #6369 Identify when binary relocation fails to remove all instances of the source prefix (and report an error to the user unless they specify -a to allow the old root to appear). This check occurs at two stages: during "bincache create" all instances of the root are replaced with a special placeholder string ("@@@@..."), and a failure occurs if the root is detected at this point; when the binary package is extracted there is a second check. This addresses #7237 and #6418. This is intended to be compatible with previously-created binary packages. This also adds: * Better error messages for "spack install --use-cache" (#6404) * Faster relocation on Mac OS (using a single call to install_name_tool for all files rather than a call for each file) * Clean up when "buildcache create" fails (addresses #6369) * Explicit error message when the spack instance extracting the binary package uses a different install layout than the spack instance that created the binary package (since this is currently not supported) * Remove the option to create unsigned binary packages with -y
This commit is contained in:
parent
360feb4193
commit
f5467957bc
@ -29,6 +29,7 @@
|
|||||||
import yaml
|
import yaml
|
||||||
import shutil
|
import shutil
|
||||||
import platform
|
import platform
|
||||||
|
import tempfile
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
from spack.util.gpg import Gpg
|
from spack.util.gpg import Gpg
|
||||||
@ -46,26 +47,57 @@
|
|||||||
|
|
||||||
|
|
||||||
class NoOverwriteException(Exception):
|
class NoOverwriteException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when a file exists and must be overwritten.
|
||||||
|
"""
|
||||||
|
def __init__(self, file_path):
|
||||||
|
err_msg = "\n%s\nexists\n" % file_path
|
||||||
|
err_msg += "Use -f option to overwrite."
|
||||||
|
super(NoOverwriteException, self).__init__(err_msg)
|
||||||
|
|
||||||
|
|
||||||
|
class NoGpgException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised when gpg2 is not in PATH
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoGpgException(Exception):
|
class NoKeyException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised when gpg has no default key added.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PickKeyException(Exception):
|
class PickKeyException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised when multiple keys can be used to sign.
|
||||||
|
"""
|
||||||
|
def __init__(self, keys):
|
||||||
|
err_msg = "Multi keys available for signing\n%s\n" % keys
|
||||||
|
err_msg += "Use spack buildcache create -k <key hash> to pick a key."
|
||||||
|
super(PickKeyException, self).__init__(err_msg)
|
||||||
|
|
||||||
|
|
||||||
|
class NoVerifyException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised if file fails signature verification.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoKeyException(Exception):
|
class NoChecksumException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised if file fails checksum verification.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoVerifyException(Exception):
|
class NewLayoutException(spack.error.SpackError):
|
||||||
pass
|
"""
|
||||||
|
Raised if directory layout is different from buildcache.
|
||||||
|
"""
|
||||||
class NoChecksumException(Exception):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -114,7 +146,8 @@ def write_buildinfo_file(prefix, workdir, rel=False):
|
|||||||
# Check if the file contains a string with the installroot.
|
# Check if the file contains a string with the installroot.
|
||||||
# This cuts down on the number of files added to the list
|
# This cuts down on the number of files added to the list
|
||||||
# of files potentially needing relocation
|
# of files potentially needing relocation
|
||||||
if relocate.strings_contains_installroot(path_name):
|
if relocate.strings_contains_installroot(path_name,
|
||||||
|
spack.store.layout.root):
|
||||||
filetype = relocate.get_filetype(path_name)
|
filetype = relocate.get_filetype(path_name)
|
||||||
if relocate.needs_binary_relocation(filetype, os_id):
|
if relocate.needs_binary_relocation(filetype, os_id):
|
||||||
rel_path_name = os.path.relpath(path_name, prefix)
|
rel_path_name = os.path.relpath(path_name, prefix)
|
||||||
@ -127,6 +160,8 @@ def write_buildinfo_file(prefix, workdir, rel=False):
|
|||||||
buildinfo = {}
|
buildinfo = {}
|
||||||
buildinfo['relative_rpaths'] = rel
|
buildinfo['relative_rpaths'] = rel
|
||||||
buildinfo['buildpath'] = spack.store.layout.root
|
buildinfo['buildpath'] = spack.store.layout.root
|
||||||
|
buildinfo['relative_prefix'] = os.path.relpath(prefix,
|
||||||
|
spack.store.layout.root)
|
||||||
buildinfo['relocate_textfiles'] = text_to_relocate
|
buildinfo['relocate_textfiles'] = text_to_relocate
|
||||||
buildinfo['relocate_binaries'] = binary_to_relocate
|
buildinfo['relocate_binaries'] = binary_to_relocate
|
||||||
filename = buildinfo_file_name(workdir)
|
filename = buildinfo_file_name(workdir)
|
||||||
@ -178,19 +213,24 @@ def checksum_tarball(file):
|
|||||||
return hasher.hexdigest()
|
return hasher.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def sign_tarball(yes_to_all, key, force, specfile_path):
|
def sign_tarball(key, force, specfile_path):
|
||||||
# Sign the packages if keys available
|
# Sign the packages if keys available
|
||||||
if not has_gnupg2():
|
if not has_gnupg2():
|
||||||
raise NoGpgException()
|
raise NoGpgException(
|
||||||
|
"gpg2 is not available in $PATH .\n"
|
||||||
|
"Use spack install gnupg and spack load gnupg.")
|
||||||
else:
|
else:
|
||||||
if key is None:
|
if key is None:
|
||||||
keys = Gpg.signing_keys()
|
keys = Gpg.signing_keys()
|
||||||
if len(keys) == 1:
|
if len(keys) == 1:
|
||||||
key = keys[0]
|
key = keys[0]
|
||||||
if len(keys) > 1:
|
if len(keys) > 1:
|
||||||
raise PickKeyException()
|
raise PickKeyException(str(keys))
|
||||||
if len(keys) == 0:
|
if len(keys) == 0:
|
||||||
raise NoKeyException()
|
msg = "No default key available for signing.\n"
|
||||||
|
msg += "Use spack gpg init and spack gpg create"
|
||||||
|
msg += " to create a default key."
|
||||||
|
raise NoKeyException(msg)
|
||||||
if os.path.exists('%s.asc' % specfile_path):
|
if os.path.exists('%s.asc' % specfile_path):
|
||||||
if force:
|
if force:
|
||||||
os.remove('%s.asc' % specfile_path)
|
os.remove('%s.asc' % specfile_path)
|
||||||
@ -214,7 +254,7 @@ def generate_index(outdir, indexfile_path):
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def build_tarball(spec, outdir, force=False, rel=False, yes_to_all=False,
|
def build_tarball(spec, outdir, force=False, rel=False, allow_root=False,
|
||||||
key=None):
|
key=None):
|
||||||
"""
|
"""
|
||||||
Build a tarball from given spec and put it into the directory structure
|
Build a tarball from given spec and put it into the directory structure
|
||||||
@ -247,9 +287,7 @@ def build_tarball(spec, outdir, force=False, rel=False, yes_to_all=False,
|
|||||||
else:
|
else:
|
||||||
raise NoOverwriteException(str(specfile_path))
|
raise NoOverwriteException(str(specfile_path))
|
||||||
# make a copy of the install directory to work with
|
# make a copy of the install directory to work with
|
||||||
workdir = join_path(outdir, os.path.basename(spec.prefix))
|
workdir = join_path(tempfile.mkdtemp(), os.path.basename(spec.prefix))
|
||||||
if os.path.exists(workdir):
|
|
||||||
shutil.rmtree(workdir)
|
|
||||||
install_tree(spec.prefix, workdir, symlinks=True)
|
install_tree(spec.prefix, workdir, symlinks=True)
|
||||||
|
|
||||||
# create info for later relocation and create tar
|
# create info for later relocation and create tar
|
||||||
@ -258,11 +296,23 @@ def build_tarball(spec, outdir, force=False, rel=False, yes_to_all=False,
|
|||||||
# optinally make the paths in the binaries relative to each other
|
# optinally make the paths in the binaries relative to each other
|
||||||
# in the spack install tree before creating tarball
|
# in the spack install tree before creating tarball
|
||||||
if rel:
|
if rel:
|
||||||
make_package_relative(workdir, spec.prefix)
|
try:
|
||||||
|
make_package_relative(workdir, spec.prefix, allow_root)
|
||||||
|
except Exception as e:
|
||||||
|
shutil.rmtree(workdir)
|
||||||
|
shutil.rmtree(tarfile_dir)
|
||||||
|
tty.die(str(e))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
make_package_placeholder(workdir, allow_root)
|
||||||
|
except Exception as e:
|
||||||
|
shutil.rmtree(workdir)
|
||||||
|
shutil.rmtree(tarfile_dir)
|
||||||
|
tty.die(str(e))
|
||||||
# create compressed tarball of the install prefix
|
# create compressed tarball of the install prefix
|
||||||
with closing(tarfile.open(tarfile_path, 'w:gz')) as tar:
|
with closing(tarfile.open(tarfile_path, 'w:gz')) as tar:
|
||||||
tar.add(name='%s' % workdir,
|
tar.add(name='%s' % workdir,
|
||||||
arcname='%s' % os.path.basename(workdir))
|
arcname='%s' % os.path.basename(spec.prefix))
|
||||||
# remove copy of install directory
|
# remove copy of install directory
|
||||||
shutil.rmtree(workdir)
|
shutil.rmtree(workdir)
|
||||||
|
|
||||||
@ -278,32 +328,26 @@ def build_tarball(spec, outdir, force=False, rel=False, yes_to_all=False,
|
|||||||
bchecksum['hash_algorithm'] = 'sha256'
|
bchecksum['hash_algorithm'] = 'sha256'
|
||||||
bchecksum['hash'] = checksum
|
bchecksum['hash'] = checksum
|
||||||
spec_dict['binary_cache_checksum'] = bchecksum
|
spec_dict['binary_cache_checksum'] = bchecksum
|
||||||
|
# Add original install prefix relative to layout root to spec.yaml.
|
||||||
|
# This will be used to determine is the directory layout has changed.
|
||||||
|
buildinfo = {}
|
||||||
|
buildinfo['relative_prefix'] = os.path.relpath(spec.prefix,
|
||||||
|
spack.store.layout.root)
|
||||||
|
spec_dict['buildinfo'] = buildinfo
|
||||||
with open(specfile_path, 'w') as outfile:
|
with open(specfile_path, 'w') as outfile:
|
||||||
outfile.write(yaml.dump(spec_dict))
|
outfile.write(yaml.dump(spec_dict))
|
||||||
signed = False
|
# sign the tarball and spec file with gpg
|
||||||
if not yes_to_all:
|
sign_tarball(key, force, specfile_path)
|
||||||
# sign the tarball and spec file with gpg
|
|
||||||
try:
|
|
||||||
sign_tarball(yes_to_all, key, force, specfile_path)
|
|
||||||
signed = True
|
|
||||||
except NoGpgException:
|
|
||||||
raise NoGpgException()
|
|
||||||
except PickKeyException:
|
|
||||||
raise PickKeyException()
|
|
||||||
except NoKeyException():
|
|
||||||
raise NoKeyException()
|
|
||||||
# put tarball, spec and signature files in .spack archive
|
# put tarball, spec and signature files in .spack archive
|
||||||
with closing(tarfile.open(spackfile_path, 'w')) as tar:
|
with closing(tarfile.open(spackfile_path, 'w')) as tar:
|
||||||
tar.add(name='%s' % tarfile_path, arcname='%s' % tarfile_name)
|
tar.add(name='%s' % tarfile_path, arcname='%s' % tarfile_name)
|
||||||
tar.add(name='%s' % specfile_path, arcname='%s' % specfile_name)
|
tar.add(name='%s' % specfile_path, arcname='%s' % specfile_name)
|
||||||
if signed:
|
tar.add(name='%s.asc' % specfile_path,
|
||||||
tar.add(name='%s.asc' % specfile_path,
|
arcname='%s.asc' % specfile_name)
|
||||||
arcname='%s.asc' % specfile_name)
|
|
||||||
|
|
||||||
# cleanup file moved to archive
|
# cleanup file moved to archive
|
||||||
os.remove(tarfile_path)
|
os.remove(tarfile_path)
|
||||||
if signed:
|
os.remove('%s.asc' % specfile_path)
|
||||||
os.remove('%s.asc' % specfile_path)
|
|
||||||
|
|
||||||
# create an index.html for the build_cache directory so specs can be found
|
# create an index.html for the build_cache directory so specs can be found
|
||||||
if os.path.exists(indexfile_path):
|
if os.path.exists(indexfile_path):
|
||||||
@ -334,7 +378,7 @@ def download_tarball(spec):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def make_package_relative(workdir, prefix):
|
def make_package_relative(workdir, prefix, allow_root):
|
||||||
"""
|
"""
|
||||||
Change paths in binaries to relative paths
|
Change paths in binaries to relative paths
|
||||||
"""
|
"""
|
||||||
@ -345,15 +389,26 @@ def make_package_relative(workdir, prefix):
|
|||||||
for filename in buildinfo['relocate_binaries']:
|
for filename in buildinfo['relocate_binaries']:
|
||||||
orig_path_names.append(os.path.join(prefix, filename))
|
orig_path_names.append(os.path.join(prefix, filename))
|
||||||
cur_path_names.append(os.path.join(workdir, filename))
|
cur_path_names.append(os.path.join(workdir, filename))
|
||||||
relocate.make_binary_relative(cur_path_names, orig_path_names,
|
relocate.make_binary_relative(cur_path_names, orig_path_names,
|
||||||
old_path)
|
old_path, allow_root)
|
||||||
|
|
||||||
|
|
||||||
def relocate_package(prefix):
|
def make_package_placeholder(workdir, allow_root):
|
||||||
|
"""
|
||||||
|
Change paths in binaries to placeholder paths
|
||||||
|
"""
|
||||||
|
buildinfo = read_buildinfo_file(workdir)
|
||||||
|
cur_path_names = list()
|
||||||
|
for filename in buildinfo['relocate_binaries']:
|
||||||
|
cur_path_names.append(os.path.join(workdir, filename))
|
||||||
|
relocate.make_binary_placeholder(cur_path_names, allow_root)
|
||||||
|
|
||||||
|
|
||||||
|
def relocate_package(workdir, allow_root):
|
||||||
"""
|
"""
|
||||||
Relocate the given package
|
Relocate the given package
|
||||||
"""
|
"""
|
||||||
buildinfo = read_buildinfo_file(prefix)
|
buildinfo = read_buildinfo_file(workdir)
|
||||||
new_path = spack.store.layout.root
|
new_path = spack.store.layout.root
|
||||||
old_path = buildinfo['buildpath']
|
old_path = buildinfo['buildpath']
|
||||||
rel = buildinfo.get('relative_rpaths', False)
|
rel = buildinfo.get('relative_rpaths', False)
|
||||||
@ -364,7 +419,7 @@ def relocate_package(prefix):
|
|||||||
"%s to %s." % (old_path, new_path))
|
"%s to %s." % (old_path, new_path))
|
||||||
path_names = set()
|
path_names = set()
|
||||||
for filename in buildinfo['relocate_textfiles']:
|
for filename in buildinfo['relocate_textfiles']:
|
||||||
path_name = os.path.join(prefix, filename)
|
path_name = os.path.join(workdir, filename)
|
||||||
# Don't add backup files generated by filter_file during install step.
|
# Don't add backup files generated by filter_file during install step.
|
||||||
if not path_name.endswith('~'):
|
if not path_name.endswith('~'):
|
||||||
path_names.add(path_name)
|
path_names.add(path_name)
|
||||||
@ -374,39 +429,46 @@ def relocate_package(prefix):
|
|||||||
if not rel:
|
if not rel:
|
||||||
path_names = set()
|
path_names = set()
|
||||||
for filename in buildinfo['relocate_binaries']:
|
for filename in buildinfo['relocate_binaries']:
|
||||||
path_name = os.path.join(prefix, filename)
|
path_name = os.path.join(workdir, filename)
|
||||||
path_names.add(path_name)
|
path_names.add(path_name)
|
||||||
relocate.relocate_binary(path_names, old_path, new_path)
|
relocate.relocate_binary(path_names, old_path, new_path,
|
||||||
|
allow_root)
|
||||||
|
|
||||||
|
|
||||||
def extract_tarball(spec, filename, yes_to_all=False, force=False):
|
def extract_tarball(spec, filename, allow_root=False, force=False):
|
||||||
"""
|
"""
|
||||||
extract binary tarball for given package into install area
|
extract binary tarball for given package into install area
|
||||||
"""
|
"""
|
||||||
installpath = spec.prefix
|
if os.path.exists(spec.prefix):
|
||||||
if os.path.exists(installpath):
|
|
||||||
if force:
|
if force:
|
||||||
shutil.rmtree(installpath)
|
shutil.rmtree(spec.prefix)
|
||||||
else:
|
else:
|
||||||
raise NoOverwriteException(str(installpath))
|
raise NoOverwriteException(str(spec.prefix))
|
||||||
|
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
stagepath = os.path.dirname(filename)
|
stagepath = os.path.dirname(filename)
|
||||||
spackfile_name = tarball_name(spec, '.spack')
|
spackfile_name = tarball_name(spec, '.spack')
|
||||||
spackfile_path = os.path.join(stagepath, spackfile_name)
|
spackfile_path = os.path.join(stagepath, spackfile_name)
|
||||||
tarfile_name = tarball_name(spec, '.tar.gz')
|
tarfile_name = tarball_name(spec, '.tar.gz')
|
||||||
tarfile_path = os.path.join(stagepath, tarfile_name)
|
tarfile_path = os.path.join(tmpdir, tarfile_name)
|
||||||
specfile_name = tarball_name(spec, '.spec.yaml')
|
specfile_name = tarball_name(spec, '.spec.yaml')
|
||||||
specfile_path = os.path.join(stagepath, specfile_name)
|
specfile_path = os.path.join(tmpdir, specfile_name)
|
||||||
|
|
||||||
with closing(tarfile.open(spackfile_path, 'r')) as tar:
|
with closing(tarfile.open(spackfile_path, 'r')) as tar:
|
||||||
tar.extractall(stagepath)
|
tar.extractall(tmpdir)
|
||||||
|
|
||||||
if not yes_to_all:
|
if os.path.exists('%s.asc' % specfile_path):
|
||||||
if os.path.exists('%s.asc' % specfile_path):
|
try:
|
||||||
Gpg.verify('%s.asc' % specfile_path, specfile_path)
|
Gpg.verify('%s.asc' % specfile_path, specfile_path)
|
||||||
os.remove(specfile_path + '.asc')
|
except Exception as e:
|
||||||
else:
|
shutil.rmtree(tmpdir)
|
||||||
raise NoVerifyException()
|
tty.die(str(e))
|
||||||
|
else:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
raise NoVerifyException(
|
||||||
|
"Package spec file failed signature verification.\n"
|
||||||
|
"Use spack buildcache keys to download "
|
||||||
|
"and install a key for verification from the mirror.")
|
||||||
# get the sha256 checksum of the tarball
|
# get the sha256 checksum of the tarball
|
||||||
checksum = checksum_tarball(tarfile_path)
|
checksum = checksum_tarball(tarfile_path)
|
||||||
|
|
||||||
@ -419,16 +481,48 @@ def extract_tarball(spec, filename, yes_to_all=False, force=False):
|
|||||||
|
|
||||||
# if the checksums don't match don't install
|
# if the checksums don't match don't install
|
||||||
if bchecksum['hash'] != checksum:
|
if bchecksum['hash'] != checksum:
|
||||||
raise NoChecksumException()
|
shutil.rmtree(tmpdir)
|
||||||
|
raise NoChecksumException(
|
||||||
|
"Package tarball failed checksum verification.\n"
|
||||||
|
"It cannot be installed.")
|
||||||
|
|
||||||
# delay creating installpath until verification is complete
|
new_relative_prefix = str(os.path.relpath(spec.prefix,
|
||||||
mkdirp(installpath)
|
spack.store.layout.root))
|
||||||
|
# if the original relative prefix is in the spec file use it
|
||||||
|
buildinfo = spec_dict.get('buildinfo', {})
|
||||||
|
old_relative_prefix = buildinfo.get('relative_prefix', new_relative_prefix)
|
||||||
|
# if the original relative prefix and new relative prefix differ the
|
||||||
|
# directory layout has changed and the buildcache cannot be installed
|
||||||
|
if old_relative_prefix != new_relative_prefix:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
msg = "Package tarball was created from an install "
|
||||||
|
msg += "prefix with a different directory layout.\n"
|
||||||
|
msg += "It cannot be relocated."
|
||||||
|
raise NewLayoutException(msg)
|
||||||
|
|
||||||
|
# extract the tarball in a temp directory
|
||||||
with closing(tarfile.open(tarfile_path, 'r')) as tar:
|
with closing(tarfile.open(tarfile_path, 'r')) as tar:
|
||||||
tar.extractall(path=join_path(installpath, '..'))
|
tar.extractall(path=tmpdir)
|
||||||
|
# the base of the install prefix is used when creating the tarball
|
||||||
|
# so the pathname should be the same now that the directory layout
|
||||||
|
# is confirmed
|
||||||
|
workdir = join_path(tmpdir, os.path.basename(spec.prefix))
|
||||||
|
|
||||||
|
# cleanup
|
||||||
os.remove(tarfile_path)
|
os.remove(tarfile_path)
|
||||||
os.remove(specfile_path)
|
os.remove(specfile_path)
|
||||||
relocate_package(installpath)
|
|
||||||
|
try:
|
||||||
|
relocate_package(workdir, allow_root)
|
||||||
|
except Exception as e:
|
||||||
|
shutil.rmtree(workdir)
|
||||||
|
tty.die(str(e))
|
||||||
|
# Delay creating spec.prefix until verification is complete
|
||||||
|
# and any relocation has been done.
|
||||||
|
else:
|
||||||
|
install_tree(workdir, spec.prefix, symlinks=True)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
def get_specs(force=False):
|
def get_specs(force=False):
|
||||||
|
@ -24,15 +24,11 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
import os
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
import spack
|
import spack
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
import spack.binary_distribution as bindist
|
import spack.binary_distribution as bindist
|
||||||
from spack.binary_distribution import NoOverwriteException, NoGpgException
|
|
||||||
from spack.binary_distribution import NoKeyException, PickKeyException
|
|
||||||
from spack.binary_distribution import NoVerifyException, NoChecksumException
|
|
||||||
|
|
||||||
description = "create, download and install binary packages"
|
description = "create, download and install binary packages"
|
||||||
section = "packaging"
|
section = "packaging"
|
||||||
@ -49,9 +45,9 @@ def setup_parser(subparser):
|
|||||||
" before creating tarballs.")
|
" before creating tarballs.")
|
||||||
create.add_argument('-f', '--force', action='store_true',
|
create.add_argument('-f', '--force', action='store_true',
|
||||||
help="overwrite tarball if it exists.")
|
help="overwrite tarball if it exists.")
|
||||||
create.add_argument('-y', '--yes-to-all', action='store_true',
|
create.add_argument('-a', '--allow_root', action='store_true',
|
||||||
help="answer yes to all create unsigned " +
|
help="allow install root string in binary files " +
|
||||||
"buildcache questions")
|
"after RPATH substitution")
|
||||||
create.add_argument('-k', '--key', metavar='key',
|
create.add_argument('-k', '--key', metavar='key',
|
||||||
type=str, default=None,
|
type=str, default=None,
|
||||||
help="Key for signing.")
|
help="Key for signing.")
|
||||||
@ -66,9 +62,11 @@ def setup_parser(subparser):
|
|||||||
install = subparsers.add_parser('install', help=installtarball.__doc__)
|
install = subparsers.add_parser('install', help=installtarball.__doc__)
|
||||||
install.add_argument('-f', '--force', action='store_true',
|
install.add_argument('-f', '--force', action='store_true',
|
||||||
help="overwrite install directory if it exists.")
|
help="overwrite install directory if it exists.")
|
||||||
install.add_argument('-y', '--yes-to-all', action='store_true',
|
install.add_argument('-m', '--multiple', action='store_true',
|
||||||
help="answer yes to all install unsigned " +
|
help="allow all matching packages ")
|
||||||
"buildcache questions")
|
install.add_argument('-a', '--allow_root', action='store_true',
|
||||||
|
help="allow install root string in binary files " +
|
||||||
|
"after RPATH substitution")
|
||||||
install.add_argument(
|
install.add_argument(
|
||||||
'packages', nargs=argparse.REMAINDER,
|
'packages', nargs=argparse.REMAINDER,
|
||||||
help="specs of packages to install biuldache for")
|
help="specs of packages to install biuldache for")
|
||||||
@ -87,7 +85,7 @@ def setup_parser(subparser):
|
|||||||
'-i', '--install', action='store_true',
|
'-i', '--install', action='store_true',
|
||||||
help="install Keys pulled from mirror")
|
help="install Keys pulled from mirror")
|
||||||
dlkeys.add_argument(
|
dlkeys.add_argument(
|
||||||
'-y', '--yes-to-all', action='store_true',
|
'-y', '--yes_to_all', action='store_true',
|
||||||
help="answer yes to all trust questions")
|
help="answer yes to all trust questions")
|
||||||
dlkeys.add_argument('-f', '--force', action='store_true',
|
dlkeys.add_argument('-f', '--force', action='store_true',
|
||||||
help="force new download of keys")
|
help="force new download of keys")
|
||||||
@ -185,17 +183,17 @@ def createtarball(args):
|
|||||||
" installed package argument")
|
" installed package argument")
|
||||||
pkgs = set(args.packages)
|
pkgs = set(args.packages)
|
||||||
specs = set()
|
specs = set()
|
||||||
outdir = os.getcwd()
|
outdir = '.'
|
||||||
if args.directory:
|
if args.directory:
|
||||||
outdir = args.directory
|
outdir = args.directory
|
||||||
signkey = None
|
signkey = None
|
||||||
if args.key:
|
if args.key:
|
||||||
signkey = args.key
|
signkey = args.key
|
||||||
yes_to_all = False
|
allow_root = False
|
||||||
force = False
|
force = False
|
||||||
relative = False
|
relative = False
|
||||||
if args.yes_to_all:
|
if args.allow_root:
|
||||||
yes_to_all = True
|
allow_root = True
|
||||||
if args.force:
|
if args.force:
|
||||||
force = True
|
force = True
|
||||||
if args.rel:
|
if args.rel:
|
||||||
@ -220,24 +218,12 @@ def createtarball(args):
|
|||||||
tty.msg('adding dependency %s' % node.format())
|
tty.msg('adding dependency %s' % node.format())
|
||||||
specs.add(node)
|
specs.add(node)
|
||||||
|
|
||||||
|
tty.msg('writing tarballs to %s/build_cache' % outdir)
|
||||||
|
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
tty.msg('creating binary cache file for package %s ' % spec.format())
|
tty.msg('creating binary cache file for package %s ' % spec.format())
|
||||||
try:
|
bindist.build_tarball(spec, outdir, force,
|
||||||
bindist.build_tarball(spec, outdir, force,
|
relative, allow_root, signkey)
|
||||||
relative, yes_to_all, signkey)
|
|
||||||
except NoOverwriteException as e:
|
|
||||||
tty.warn("%s exists, use -f to force overwrite." % e)
|
|
||||||
except NoGpgException:
|
|
||||||
tty.die("gpg2 is not available,"
|
|
||||||
" use -y to create unsigned build caches")
|
|
||||||
except NoKeyException:
|
|
||||||
tty.die("no default key available for signing,"
|
|
||||||
" use -y to create unsigned build caches"
|
|
||||||
" or spack gpg init to create a default key")
|
|
||||||
except PickKeyException:
|
|
||||||
tty.die("multi keys available for signing,"
|
|
||||||
" use -y to create unsigned build caches"
|
|
||||||
" or -k <key hash> to pick a key")
|
|
||||||
|
|
||||||
|
|
||||||
def installtarball(args):
|
def installtarball(args):
|
||||||
@ -246,13 +232,13 @@ def installtarball(args):
|
|||||||
tty.die("build cache file installation requires" +
|
tty.die("build cache file installation requires" +
|
||||||
" at least one package spec argument")
|
" at least one package spec argument")
|
||||||
pkgs = set(args.packages)
|
pkgs = set(args.packages)
|
||||||
yes_to_all = False
|
multiple = False
|
||||||
if args.yes_to_all:
|
if args.multiple:
|
||||||
yes_to_all = True
|
multiple = True
|
||||||
force = False
|
force = False
|
||||||
if args.force:
|
if args.force:
|
||||||
force = True
|
force = True
|
||||||
matches = match_downloaded_specs(pkgs, yes_to_all, force)
|
matches = match_downloaded_specs(pkgs, multiple, force)
|
||||||
|
|
||||||
for match in matches:
|
for match in matches:
|
||||||
install_tarball(match, args)
|
install_tarball(match, args)
|
||||||
@ -263,9 +249,9 @@ def install_tarball(spec, args):
|
|||||||
if s.external or s.virtual:
|
if s.external or s.virtual:
|
||||||
tty.warn("Skipping external or virtual package %s" % spec.format())
|
tty.warn("Skipping external or virtual package %s" % spec.format())
|
||||||
return
|
return
|
||||||
yes_to_all = False
|
allow_root = False
|
||||||
if args.yes_to_all:
|
if args.allow_root:
|
||||||
yes_to_all = True
|
allow_root = True
|
||||||
force = False
|
force = False
|
||||||
if args.force:
|
if args.force:
|
||||||
force = True
|
force = True
|
||||||
@ -274,24 +260,13 @@ def install_tarball(spec, args):
|
|||||||
install_tarball(d, args)
|
install_tarball(d, args)
|
||||||
package = spack.repo.get(spec)
|
package = spack.repo.get(spec)
|
||||||
if s.concrete and package.installed and not force:
|
if s.concrete and package.installed and not force:
|
||||||
tty.warn("Package for spec %s already installed." % spec.format(),
|
tty.warn("Package for spec %s already installed." % spec.format())
|
||||||
" Use -f flag to overwrite.")
|
|
||||||
else:
|
else:
|
||||||
tarball = bindist.download_tarball(spec)
|
tarball = bindist.download_tarball(spec)
|
||||||
if tarball:
|
if tarball:
|
||||||
tty.msg('Installing buildcache for spec %s' % spec.format())
|
tty.msg('Installing buildcache for spec %s' % spec.format())
|
||||||
try:
|
bindist.extract_tarball(spec, tarball, allow_root, force)
|
||||||
bindist.extract_tarball(spec, tarball, yes_to_all, force)
|
spack.store.db.reindex(spack.store.layout)
|
||||||
except NoOverwriteException as e:
|
|
||||||
tty.warn("%s exists. use -f to force overwrite." % e.args)
|
|
||||||
except NoVerifyException:
|
|
||||||
tty.die("Package spec file failed signature verification,"
|
|
||||||
" use -y flag to install build cache")
|
|
||||||
except NoChecksumException:
|
|
||||||
tty.die("Package tarball failed checksum verification,"
|
|
||||||
" use -y flag to install build cache")
|
|
||||||
finally:
|
|
||||||
spack.store.db.reindex(spack.store.layout)
|
|
||||||
else:
|
else:
|
||||||
tty.die('Download of binary cache file for spec %s failed.' %
|
tty.die('Download of binary cache file for spec %s failed.' %
|
||||||
spec.format())
|
spec.format())
|
||||||
|
@ -1288,7 +1288,7 @@ def try_install_from_binary_cache(self, explicit):
|
|||||||
tty.msg('Installing %s from binary cache' % self.name)
|
tty.msg('Installing %s from binary cache' % self.name)
|
||||||
tarball = binary_distribution.download_tarball(binary_spec)
|
tarball = binary_distribution.download_tarball(binary_spec)
|
||||||
binary_distribution.extract_tarball(
|
binary_distribution.extract_tarball(
|
||||||
binary_spec, tarball, yes_to_all=False, force=False)
|
binary_spec, tarball, allow_root=False, force=False)
|
||||||
spack.store.db.add(self.spec, spack.store.layout, explicit=explicit)
|
spack.store.db.add(self.spec, spack.store.layout, explicit=explicit)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -33,6 +33,18 @@
|
|||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
|
||||||
|
class InstallRootStringException(spack.error.SpackError):
|
||||||
|
"""
|
||||||
|
Raised when the relocated binary still has the install root string.
|
||||||
|
"""
|
||||||
|
def __init__(self, file_path, root_path):
|
||||||
|
super(InstallRootStringException, self).__init__(
|
||||||
|
"\n %s \ncontains string\n %s \n"
|
||||||
|
"after replacing it in rpaths.\n"
|
||||||
|
"Package should not be relocated.\n Use -a to override." %
|
||||||
|
(file_path, root_path))
|
||||||
|
|
||||||
|
|
||||||
def get_patchelf():
|
def get_patchelf():
|
||||||
"""
|
"""
|
||||||
Builds and installs spack patchelf package on linux platforms
|
Builds and installs spack patchelf package on linux platforms
|
||||||
@ -86,6 +98,29 @@ def get_relative_rpaths(path_name, orig_dir, orig_rpaths):
|
|||||||
return rel_rpaths
|
return rel_rpaths
|
||||||
|
|
||||||
|
|
||||||
|
def set_placeholder(dirname):
|
||||||
|
"""
|
||||||
|
return string of @'s with same length
|
||||||
|
"""
|
||||||
|
return '@' * len(dirname)
|
||||||
|
|
||||||
|
|
||||||
|
def get_placeholder_rpaths(path_name, orig_rpaths):
|
||||||
|
"""
|
||||||
|
Replaces original layout root dir with a placeholder string in all rpaths.
|
||||||
|
"""
|
||||||
|
rel_rpaths = []
|
||||||
|
orig_dir = spack.store.layout.root
|
||||||
|
for rpath in orig_rpaths:
|
||||||
|
if re.match(orig_dir, rpath):
|
||||||
|
placeholder = set_placeholder(orig_dir)
|
||||||
|
rel = re.sub(orig_dir, placeholder, rpath)
|
||||||
|
rel_rpaths.append('%s' % rel)
|
||||||
|
else:
|
||||||
|
rel_rpaths.append(rpath)
|
||||||
|
return rel_rpaths
|
||||||
|
|
||||||
|
|
||||||
def macho_get_paths(path_name):
|
def macho_get_paths(path_name):
|
||||||
"""
|
"""
|
||||||
Examines the output of otool -l path_name for these three fields:
|
Examines the output of otool -l path_name for these three fields:
|
||||||
@ -121,7 +156,7 @@ def macho_get_paths(path_name):
|
|||||||
def macho_make_paths_relative(path_name, old_dir, rpaths, deps, idpath):
|
def macho_make_paths_relative(path_name, old_dir, rpaths, deps, idpath):
|
||||||
"""
|
"""
|
||||||
Replace old_dir with relative path from dirname(path_name)
|
Replace old_dir with relative path from dirname(path_name)
|
||||||
in rpaths and deps; idpaths are replaced with @rpath/basebane(path_name);
|
in rpaths and deps; idpaths are replaced with @rpath/libname as needed;
|
||||||
replacement are returned.
|
replacement are returned.
|
||||||
"""
|
"""
|
||||||
new_idpath = None
|
new_idpath = None
|
||||||
@ -144,6 +179,34 @@ def macho_make_paths_relative(path_name, old_dir, rpaths, deps, idpath):
|
|||||||
return (new_rpaths, new_deps, new_idpath)
|
return (new_rpaths, new_deps, new_idpath)
|
||||||
|
|
||||||
|
|
||||||
|
def macho_make_paths_placeholder(rpaths, deps, idpath):
|
||||||
|
"""
|
||||||
|
Replace old_dir with a placeholder of the same length
|
||||||
|
in rpaths and deps and idpaths is needed.
|
||||||
|
replacement are returned.
|
||||||
|
"""
|
||||||
|
new_idpath = None
|
||||||
|
old_dir = spack.store.layout.root
|
||||||
|
placeholder = set_placeholder(old_dir)
|
||||||
|
if idpath:
|
||||||
|
new_idpath = re.sub(old_dir, placeholder, idpath)
|
||||||
|
new_rpaths = list()
|
||||||
|
new_deps = list()
|
||||||
|
for rpath in rpaths:
|
||||||
|
if re.match(old_dir, rpath):
|
||||||
|
ph = re.sub(old_dir, placeholder, rpath)
|
||||||
|
new_rpaths.append('%s' % ph)
|
||||||
|
else:
|
||||||
|
new_rpaths.append(rpath)
|
||||||
|
for dep in deps:
|
||||||
|
if re.match(old_dir, dep):
|
||||||
|
ph = re.sub(old_dir, placeholder, dep)
|
||||||
|
new_deps.append('%s' % ph)
|
||||||
|
else:
|
||||||
|
new_deps.append(dep)
|
||||||
|
return (new_rpaths, new_deps, new_idpath)
|
||||||
|
|
||||||
|
|
||||||
def macho_replace_paths(old_dir, new_dir, rpaths, deps, idpath):
|
def macho_replace_paths(old_dir, new_dir, rpaths, deps, idpath):
|
||||||
"""
|
"""
|
||||||
Replace old_dir with new_dir in rpaths, deps and idpath
|
Replace old_dir with new_dir in rpaths, deps and idpath
|
||||||
@ -179,15 +242,17 @@ def modify_macho_object(cur_path, rpaths, deps, idpath,
|
|||||||
if 'libgcc_' in cur_path:
|
if 'libgcc_' in cur_path:
|
||||||
return
|
return
|
||||||
install_name_tool = Executable('install_name_tool')
|
install_name_tool = Executable('install_name_tool')
|
||||||
|
args = []
|
||||||
if new_idpath:
|
if new_idpath:
|
||||||
install_name_tool('-id', new_idpath, str(cur_path),
|
args.extend(['-id', new_idpath])
|
||||||
output=str, err=str)
|
|
||||||
|
|
||||||
for orig, new in zip(deps, new_deps):
|
for orig, new in zip(deps, new_deps):
|
||||||
install_name_tool('-change', orig, new, str(cur_path))
|
args.extend(['-change', orig, new])
|
||||||
|
|
||||||
for orig, new in zip(rpaths, new_rpaths):
|
for orig, new in zip(rpaths, new_rpaths):
|
||||||
install_name_tool('-rpath', orig, new, str(cur_path))
|
args.extend(['-rpath', orig, new])
|
||||||
|
args.append(str(cur_path))
|
||||||
|
install_name_tool(*args)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@ -202,14 +267,14 @@ def get_filetype(path_name):
|
|||||||
return output.strip()
|
return output.strip()
|
||||||
|
|
||||||
|
|
||||||
def strings_contains_installroot(path_name):
|
def strings_contains_installroot(path_name, root_dir):
|
||||||
"""
|
"""
|
||||||
Check if the file contain the install root string.
|
Check if the file contain the install root string.
|
||||||
"""
|
"""
|
||||||
strings = Executable('strings')
|
strings = Executable('strings')
|
||||||
output = strings('%s' % path_name,
|
output = strings('%s' % path_name,
|
||||||
output=str, err=str)
|
output=str, err=str)
|
||||||
return (spack.store.layout.root in output)
|
return (root_dir in output)
|
||||||
|
|
||||||
|
|
||||||
def modify_elf_object(path_name, new_rpaths):
|
def modify_elf_object(path_name, new_rpaths):
|
||||||
@ -257,34 +322,66 @@ def needs_text_relocation(filetype):
|
|||||||
return ("text" in filetype)
|
return ("text" in filetype)
|
||||||
|
|
||||||
|
|
||||||
def relocate_binary(path_names, old_dir, new_dir):
|
def relocate_binary(path_names, old_dir, new_dir, allow_root):
|
||||||
"""
|
"""
|
||||||
Change old_dir to new_dir in RPATHs of elf or mach-o files
|
Change old_dir to new_dir in RPATHs of elf or mach-o files
|
||||||
|
Account for the case where old_dir is now a placeholder
|
||||||
"""
|
"""
|
||||||
|
placeholder = set_placeholder(old_dir)
|
||||||
if platform.system() == 'Darwin':
|
if platform.system() == 'Darwin':
|
||||||
for path_name in path_names:
|
for path_name in path_names:
|
||||||
rpaths, deps, idpath = macho_get_paths(path_name)
|
(rpaths, deps, idpath) = macho_get_paths(path_name)
|
||||||
new_rpaths, new_deps, new_idpath = macho_replace_paths(old_dir,
|
# new style buildaches with placeholder in binaries
|
||||||
new_dir,
|
if (deps[0].startswith(placeholder) or
|
||||||
rpaths,
|
rpaths[0].startswith(placeholder) or
|
||||||
deps,
|
(idpath and idpath.startswith(placeholder))):
|
||||||
idpath)
|
(new_rpaths,
|
||||||
|
new_deps,
|
||||||
|
new_idpath) = macho_replace_paths(placeholder,
|
||||||
|
new_dir,
|
||||||
|
rpaths,
|
||||||
|
deps,
|
||||||
|
idpath)
|
||||||
|
# old style buildcaches with original install root in binaries
|
||||||
|
else:
|
||||||
|
(new_rpaths,
|
||||||
|
new_deps,
|
||||||
|
new_idpath) = macho_replace_paths(old_dir,
|
||||||
|
new_dir,
|
||||||
|
rpaths,
|
||||||
|
deps,
|
||||||
|
idpath)
|
||||||
modify_macho_object(path_name,
|
modify_macho_object(path_name,
|
||||||
rpaths, deps, idpath,
|
rpaths, deps, idpath,
|
||||||
new_rpaths, new_deps, new_idpath)
|
new_rpaths, new_deps, new_idpath)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(path_name, old_dir)):
|
||||||
|
raise InstallRootStringException(path_name, old_dir)
|
||||||
|
|
||||||
elif platform.system() == 'Linux':
|
elif platform.system() == 'Linux':
|
||||||
for path_name in path_names:
|
for path_name in path_names:
|
||||||
orig_rpaths = get_existing_elf_rpaths(path_name)
|
orig_rpaths = get_existing_elf_rpaths(path_name)
|
||||||
if orig_rpaths:
|
if orig_rpaths:
|
||||||
new_rpaths = substitute_rpath(orig_rpaths, old_dir, new_dir)
|
if orig_rpaths[0].startswith(placeholder):
|
||||||
|
# new style buildaches with placeholder in binaries
|
||||||
|
new_rpaths = substitute_rpath(orig_rpaths,
|
||||||
|
placeholder, new_dir)
|
||||||
|
else:
|
||||||
|
# old style buildcaches with original install
|
||||||
|
# root in binaries
|
||||||
|
new_rpaths = substitute_rpath(orig_rpaths,
|
||||||
|
old_dir, new_dir)
|
||||||
modify_elf_object(path_name, new_rpaths)
|
modify_elf_object(path_name, new_rpaths)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(path_name, old_dir)):
|
||||||
|
raise InstallRootStringException(path_name, old_dir)
|
||||||
else:
|
else:
|
||||||
tty.die("Relocation not implemented for %s" % platform.system())
|
tty.die("Relocation not implemented for %s" % platform.system())
|
||||||
|
|
||||||
|
|
||||||
def make_binary_relative(cur_path_names, orig_path_names, old_dir):
|
def make_binary_relative(cur_path_names, orig_path_names, old_dir, allow_root):
|
||||||
"""
|
"""
|
||||||
Make RPATHs relative to old_dir in given elf or mach-o files
|
Replace old RPATHs with paths relative to old_dir in binary files
|
||||||
"""
|
"""
|
||||||
if platform.system() == 'Darwin':
|
if platform.system() == 'Darwin':
|
||||||
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
||||||
@ -296,6 +393,9 @@ def make_binary_relative(cur_path_names, orig_path_names, old_dir):
|
|||||||
modify_macho_object(cur_path,
|
modify_macho_object(cur_path,
|
||||||
rpaths, deps, idpath,
|
rpaths, deps, idpath,
|
||||||
new_rpaths, new_deps, new_idpath)
|
new_rpaths, new_deps, new_idpath)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(cur_path)):
|
||||||
|
raise InstallRootStringException(cur_path)
|
||||||
elif platform.system() == 'Linux':
|
elif platform.system() == 'Linux':
|
||||||
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
for cur_path, orig_path in zip(cur_path_names, orig_path_names):
|
||||||
orig_rpaths = get_existing_elf_rpaths(cur_path)
|
orig_rpaths = get_existing_elf_rpaths(cur_path)
|
||||||
@ -303,10 +403,46 @@ def make_binary_relative(cur_path_names, orig_path_names, old_dir):
|
|||||||
new_rpaths = get_relative_rpaths(orig_path, old_dir,
|
new_rpaths = get_relative_rpaths(orig_path, old_dir,
|
||||||
orig_rpaths)
|
orig_rpaths)
|
||||||
modify_elf_object(cur_path, new_rpaths)
|
modify_elf_object(cur_path, new_rpaths)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(cur_path, old_dir)):
|
||||||
|
raise InstallRootStringException(cur_path, old_dir)
|
||||||
else:
|
else:
|
||||||
tty.die("Prelocation not implemented for %s" % platform.system())
|
tty.die("Prelocation not implemented for %s" % platform.system())
|
||||||
|
|
||||||
|
|
||||||
|
def make_binary_placeholder(cur_path_names, allow_root):
|
||||||
|
"""
|
||||||
|
Replace old install root in RPATHs with placeholder in binary files
|
||||||
|
"""
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
for cur_path in cur_path_names:
|
||||||
|
rpaths, deps, idpath = macho_get_paths(cur_path)
|
||||||
|
(new_rpaths,
|
||||||
|
new_deps,
|
||||||
|
new_idpath) = macho_make_paths_placeholder(rpaths, deps, idpath)
|
||||||
|
modify_macho_object(cur_path,
|
||||||
|
rpaths, deps, idpath,
|
||||||
|
new_rpaths, new_deps, new_idpath)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(cur_path,
|
||||||
|
spack.store.layout.root)):
|
||||||
|
raise InstallRootStringException(cur_path,
|
||||||
|
spack.store.layout.root)
|
||||||
|
elif platform.system() == 'Linux':
|
||||||
|
for cur_path in cur_path_names:
|
||||||
|
orig_rpaths = get_existing_elf_rpaths(cur_path)
|
||||||
|
if orig_rpaths:
|
||||||
|
new_rpaths = get_placeholder_rpaths(cur_path, orig_rpaths)
|
||||||
|
modify_elf_object(cur_path, new_rpaths)
|
||||||
|
if (not allow_root and
|
||||||
|
strings_contains_installroot(cur_path,
|
||||||
|
spack.store.layout.root)):
|
||||||
|
raise InstallRootStringException(cur_path,
|
||||||
|
spack.store.layout.root)
|
||||||
|
else:
|
||||||
|
tty.die("Placeholder not implemented for %s" % platform.system())
|
||||||
|
|
||||||
|
|
||||||
def relocate_text(path_names, old_dir, new_dir):
|
def relocate_text(path_names, old_dir, new_dir):
|
||||||
"""
|
"""
|
||||||
Replace old path with new path in text file path_name
|
Replace old path with new path in text file path_name
|
||||||
|
@ -73,7 +73,7 @@ def fake_fetchify(url, pkg):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures('install_mockery', 'testing_gpg_directory')
|
@pytest.mark.usefixtures('install_mockery', 'testing_gpg_directory')
|
||||||
def test_packaging(mock_archive, tmpdir):
|
def test_buildcache(mock_archive, tmpdir):
|
||||||
# tweak patchelf to only do a download
|
# tweak patchelf to only do a download
|
||||||
spec = Spec("patchelf")
|
spec = Spec("patchelf")
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
@ -218,22 +218,20 @@ def test_packaging(mock_archive, tmpdir):
|
|||||||
|
|
||||||
|
|
||||||
def test_relocate_text(tmpdir):
|
def test_relocate_text(tmpdir):
|
||||||
# Validate the text path replacement
|
with tmpdir.as_cwd():
|
||||||
old_dir = '/home/spack/opt/spack'
|
# Validate the text path replacement
|
||||||
filename = str(tmpdir) + '/dummy.txt'
|
old_dir = '/home/spack/opt/spack'
|
||||||
with open(filename, "w") as script:
|
filename = 'dummy.txt'
|
||||||
script.write(old_dir)
|
with open(filename, "w") as script:
|
||||||
script.close()
|
script.write(old_dir)
|
||||||
|
script.close()
|
||||||
filenames = [filename]
|
filenames = [filename]
|
||||||
new_dir = '/opt/rh/devtoolset/'
|
new_dir = '/opt/rh/devtoolset/'
|
||||||
relocate_text(filenames, old_dir, new_dir)
|
relocate_text(filenames, old_dir, new_dir)
|
||||||
|
with open(filename, "r")as script:
|
||||||
assert(strings_contains_installroot(filename) is False)
|
for line in script:
|
||||||
|
assert(new_dir in line)
|
||||||
with open(filename, "r") as script:
|
assert(strings_contains_installroot(filename, old_dir) is False)
|
||||||
for line in script:
|
|
||||||
assert(new_dir in line)
|
|
||||||
|
|
||||||
|
|
||||||
def test_needs_relocation():
|
def test_needs_relocation():
|
||||||
|
Loading…
Reference in New Issue
Block a user