spack view copy: relocate symlinks (#32306)

This commit is contained in:
Harmen Stoppels 2023-05-09 12:17:16 +02:00 committed by GitHub
parent 71cd94e524
commit 9e1440ec7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,13 +3,14 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import collections
import functools as ft import functools as ft
import itertools import itertools
import os import os
import re import re
import shutil import shutil
import stat
import sys import sys
from typing import Optional
from llnl.util import tty from llnl.util import tty
from llnl.util.filesystem import ( from llnl.util.filesystem import (
@ -32,12 +33,14 @@
import spack.config import spack.config
import spack.projections import spack.projections
import spack.relocate
import spack.schema.projections import spack.schema.projections
import spack.spec import spack.spec
import spack.store import spack.store
import spack.util.spack_json as s_json import spack.util.spack_json as s_json
import spack.util.spack_yaml as s_yaml import spack.util.spack_yaml as s_yaml
from spack.error import SpackError from spack.error import SpackError
from spack.hooks import sbang
__all__ = ["FilesystemView", "YamlFilesystemView"] __all__ = ["FilesystemView", "YamlFilesystemView"]
@ -57,50 +60,47 @@ def view_hardlink(src, dst, **kwargs):
os.link(src, dst) os.link(src, dst)
def view_copy(src, dst, view, spec=None): def view_copy(src: str, dst: str, view, spec: Optional[spack.spec.Spec] = None):
""" """
Copy a file from src to dst. Copy a file from src to dst.
Use spec and view to generate relocations Use spec and view to generate relocations
""" """
shutil.copy2(src, dst) shutil.copy2(src, dst, follow_symlinks=False)
if spec and not spec.external:
# Not metadata, we have to relocate it
# Get information on where to relocate from/to # No need to relocate if no metadata or external.
if not spec or spec.external:
return
# This is vestigial code for the *old* location of sbang. Previously, # Order of this dict is somewhat irrelevant
# sbang was a bash script, and it lived in the spack prefix. It is prefix_to_projection = {
# now a POSIX script that lives in the install prefix. Old packages s.prefix: view.get_projection_for_spec(s)
# will have the old sbang location in their shebangs. for s in spec.traverse(root=True, order="breadth")
# TODO: Not sure which one to use... if not s.external
import spack.hooks.sbang as sbang }
# Break a package include cycle src_stat = os.lstat(src)
import spack.relocate
orig_sbang = "#!/bin/bash {0}/bin/sbang".format(spack.paths.spack_root) # TODO: change this into a bulk operation instead of a per-file operation
new_sbang = sbang.sbang_shebang_line()
prefix_to_projection = collections.OrderedDict( if stat.S_ISLNK(src_stat.st_mode):
{spec.prefix: view.get_projection_for_spec(spec)} spack.relocate.relocate_links(links=[dst], prefix_to_prefix=prefix_to_projection)
) elif spack.relocate.is_binary(dst):
spack.relocate.relocate_text_bin(binaries=[dst], prefixes=prefix_to_projection)
else:
prefix_to_projection[spack.store.layout.root] = view._root
for dep in spec.traverse(): # This is vestigial code for the *old* location of sbang.
if not dep.external: prefix_to_projection[
prefix_to_projection[dep.prefix] = view.get_projection_for_spec(dep) "#!/bin/bash {0}/bin/sbang".format(spack.paths.spack_root)
] = sbang.sbang_shebang_line()
if spack.relocate.is_binary(dst): spack.relocate.relocate_text(files=[dst], prefixes=prefix_to_projection)
spack.relocate.relocate_text_bin(binaries=[dst], prefixes=prefix_to_projection)
else: try:
prefix_to_projection[spack.store.layout.root] = view._root os.chown(dst, src_stat.st_uid, src_stat.st_gid)
prefix_to_projection[orig_sbang] = new_sbang except OSError:
spack.relocate.relocate_text(files=[dst], prefixes=prefix_to_projection) tty.debug("Can't change the permissions for %s" % dst)
try:
stat = os.stat(src)
os.chown(dst, stat.st_uid, stat.st_gid)
except OSError:
tty.debug("Can't change the permissions for %s" % dst)
def view_func_parser(parsed_name): def view_func_parser(parsed_name):