install_tree, copy_tree can install into existing directory structures (#8289)

Replace use of `shutil.copytree` with `copy_tree` and `install_tree` functions in `llnl.util.filesystem`.

- `copy_tree` copies without setting permissions.  It should be used to copy files around in the build directory.
- `install_tree` copies files and sets permissions.  It should be used to copy files into the installation directory.
- `install` and `copy` are analogous single-file functions.
- add more extensive tests for these functions
- update packages to use these functions.
This commit is contained in:
Adam J. Stewart
2018-08-15 11:30:09 -05:00
committed by Todd Gamblin
parent c0699539d5
commit 73c978ddd9
82 changed files with 422 additions and 344 deletions

View File

@@ -60,7 +60,9 @@
'fix_darwin_install_name',
'force_remove',
'force_symlink',
'copy',
'install',
'copy_tree',
'install_tree',
'is_exe',
'join_path',
@@ -264,27 +266,98 @@ def unset_executable_mode(path):
os.chmod(path, mode)
def install(src, dest):
"""Manually install a file to a particular location."""
tty.debug("Installing %s to %s" % (src, dest))
def copy(src, dest, _permissions=False):
"""Copies the file *src* to the file or directory *dest*.
If *dest* specifies a directory, the file will be copied into *dest*
using the base filename from *src*.
Parameters:
src (str): the file to copy
dest (str): the destination file or directory
_permissions (bool): for internal use only
"""
if _permissions:
tty.debug('Installing {0} to {1}'.format(src, dest))
else:
tty.debug('Copying {0} to {1}'.format(src, dest))
# Expand dest to its eventual full path if it is a directory.
if os.path.isdir(dest):
dest = join_path(dest, os.path.basename(src))
shutil.copy(src, dest)
set_install_permissions(dest)
copy_mode(src, dest)
if _permissions:
set_install_permissions(dest)
copy_mode(src, dest)
def install_tree(src, dest, **kwargs):
"""Manually install a directory tree to a particular location."""
tty.debug("Installing %s to %s" % (src, dest))
shutil.copytree(src, dest, **kwargs)
def install(src, dest):
"""Installs the file *src* to the file or directory *dest*.
for s, d in traverse_tree(src, dest, follow_nonexisting=False):
set_install_permissions(d)
copy_mode(s, d)
Same as :py:func:`copy` with the addition of setting proper
permissions on the installed file.
Parameters:
src (str): the file to install
dest (str): the destination file or directory
"""
copy(src, dest, _permissions=True)
def copy_tree(src, dest, symlinks=True, _permissions=False):
"""Recursively copy an entire directory tree rooted at *src*.
If the destination directory *dest* does not already exist, it will
be created as well as missing parent directories.
If *symlinks* is true, symbolic links in the source tree are represented
as symbolic links in the new tree and the metadata of the original links
will be copied as far as the platform allows; if false, the contents and
metadata of the linked files are copied to the new tree.
Parameters:
src (str): the directory to copy
dest (str): the destination directory
symlinks (bool): whether or not to preserve symlinks
_permissions (bool): for internal use only
"""
if _permissions:
tty.debug('Installing {0} to {1}'.format(src, dest))
else:
tty.debug('Copying {0} to {1}'.format(src, dest))
mkdirp(dest)
for s, d in traverse_tree(src, dest, order='pre', follow_nonexisting=True):
if symlinks and os.path.islink(s):
# Note that this won't rewrite absolute links into the old
# root to point at the new root. Should we handle that case?
target = os.readlink(s)
os.symlink(os.path.abspath(target), d)
elif os.path.isdir(s):
mkdirp(d)
else:
shutil.copyfile(s, d)
if _permissions:
set_install_permissions(d)
copy_mode(s, d)
def install_tree(src, dest, symlinks=True):
"""Recursively install an entire directory tree rooted at *src*.
Same as :py:func:`copy_tree` with the addition of setting proper
permissions on the installed files and directories.
Parameters:
src (str): the directory to install
dest (str): the destination directory
symlinks (bool): whether or not to preserve symlinks
"""
copy_tree(src, dest, symlinks, _permissions=True)
def is_exe(path):