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:
		
				
					committed by
					
						
						Todd Gamblin
					
				
			
			
				
	
			
			
			
						parent
						
							c0699539d5
						
					
				
				
					commit
					73c978ddd9
				
			@@ -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):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user