Source code for quixote.build.shell

from os import path
from shlex import quote
from typing import Dict, Iterable, List, Union

from quixote.build.utils import setup_function
from quixote.build import GeneratorType
from quixote import get_context


@setup_function
def command(cmd: str, env: Dict[str, str] = None) -> str:
    """
    Execute a shell command

    :param cmd:                 the command to execute
    :param env:                 the additional environment to use for this command execution
    """
    env = env or {}
    env = (name + "=" + quote(value) for name, value in env.items())
    if get_context()["generator"] == GeneratorType.DOCKER:
        cmd = cmd.strip().replace('\n', '\\\n')
        return " ".join(("RUN", *env, cmd))
    else:
        return " ".join((*env, cmd))


@setup_function
def set_env(**kwargs) -> str:
    """
    Set environment variables

    :param kwargs:              a dictionary with variable names as keys and their values as values
    """
    to_set = ' '.join(name + "=" + quote(value) for name, value in kwargs.items())
    if get_context()["generator"] == GeneratorType.DOCKER:
        return f"ENV {to_set}"
    else:
        return f"export {to_set}"


@setup_function
def change_work_directory(path: str) -> str:
    """
    Change the current working directory

    :param path:                the path to the new working directory
    """
    if get_context()["generator"] == GeneratorType.DOCKER:
        return f"WORKDIR {path}"
    else:
        return f"cd {path}"


[docs]def add_user( username: str, *, home_dir: str = None, groups: Iterable[str] = None, create_home_dir: bool = None, shell: str = None ) -> str: """ Create a user :param username: the username of the new user :param home_dir: the path to the directory to use as home directory for the new user :param groups: the groups to which the new user should be added :param create_home_dir: whether or not a home directory should be created for the user (if it does not exist) :param shell: the path to the executable to set as shell for the new user """ args = ["useradd", username] if home_dir is not None: args += ("--home-dir", home_dir) if groups is not None: args += ("--groups", ','.join(groups)) if create_home_dir is not None: if create_home_dir is True: args.append("--create-home") else: args.append("--no-create-home") if shell is not None: args += ("--shell", shell) return command(' '.join(args))
[docs]def change_user_passwd(username: str, new_password: str) -> str: """ Change the password for a given user :param username: the username of the user :param new_password: the new password """ arg = f"{username}:{new_password}" return command(f"echo {quote(arg)} | chpasswd")
def _dirname(p: str): if p[-1] == '/': return path.dirname(path.dirname(p)) return path.dirname(p) @setup_function def add_file(src: Union[str, List[str]], dest: str): """ Add some files to the setup :param src: a single or list of files to add :param dest: the path at which to put the files (must be a directory if multiples files are provided in src) """ resources_path = path.realpath(get_context()["resources_path"]) if isinstance(src, str): src = path.realpath(src) if path.commonprefix([src, resources_path]) != resources_path: raise PermissionError(f"Source file should be in {resources_path}") src = path.relpath(src, _dirname(resources_path)) if get_context()["generator"] == GeneratorType.DOCKER: return f"COPY {src} {dest}" else: return f"cp -r {src} {dest}" else: src = list(map(path.realpath, src)) if path.commonprefix(src + [resources_path]) != resources_path: raise PermissionError(f"Source files should be in {resources_path}") src = map(lambda p: path.relpath(p, _dirname(resources_path)), src) if get_context()["generator"] == GeneratorType.DOCKER: return f"COPY {' '.join(src)} {dest}" else: return f"cp -rt {dest} {' '.join(src)}"