Exemple #1
0
def main(opts):

    environ = {}

    # Get the initial environment
    if not opts.ignore_environment:
        environ.update(os.environ)

    # Update environment from stdin
    if opts.stdin:
        input_env_str = sys.stdin.read()

        environ.update(parse_env_str(input_env_str))

    # Finally, update with explicit vars
    environ.update(opts.envs)

    if len(opts.cmd) == 0:
        # Print environment and exit if there's no command
        print(format_env_dict(environ))
    else:
        # Run the subcommand with the modified environment
        for ret in execute_process(opts.cmd, env=environ, emulate_tty=True):
            if ret:
                if isinstance(ret, int):
                    return ret
                else:
                    print(ret, end='')

    # Flush stdout
    # NOTE: This is done to ensure that automated use of this tool doesn't miss
    # the output
    sys.stdout.flush()
    return 0
Exemple #2
0
def get_resultspace_environment(result_space_path,
                                base_env=None,
                                quiet=False,
                                cached=True,
                                strict=True):
    """Get the environemt variables which result from sourcing another catkin
    workspace's setup files as the string output of `cmake -E environment`.
    This cmake command is used to be as portable as possible.

    :param result_space_path: path to a Catkin result-space whose environment should be loaded, ``str``
    :type result_space_path: str
    :param quiet: don't throw exceptions, ``bool``
    :type quiet: bool
    :param cached: use the cached environment
    :type cached: bool
    :param strict: require the ``.catkin`` file exists in the resultspace
    :type strict: bool

    :returns: a dictionary of environment variables and their values
    """

    # Set bae environment to the current environment
    if base_env is None:
        base_env = dict(os.environ)

    # Get the MD5 checksums for the current env hooks
    # TODO: the env hooks path should be defined somewhere
    env_hooks_path = os.path.join(result_space_path, 'etc', 'catkin',
                                  'profile.d')
    if os.path.exists(env_hooks_path):
        env_hooks = [
            md5(open(os.path.join(env_hooks_path, path),
                     "rb").read()).hexdigest()
            for path in os.listdir(env_hooks_path)
        ]
    else:
        env_hooks = []

    # Check the cache first, if desired
    if cached and result_space_path in _resultspace_env_cache:
        (cached_base_env, cached_env_hooks,
         result_env) = _resultspace_env_cache.get(result_space_path)
        if env_hooks == cached_env_hooks and cached_base_env == base_env:
            return dict(result_env)

    # Check to make sure result_space_path is a valid directory
    if not os.path.isdir(result_space_path):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because it does not "
            "exist." % result_space_path)

    # Check to make sure result_space_path contains a `.catkin` file
    # TODO: `.catkin` should be defined somewhere as an atom in catkin_pkg
    if strict and not os.path.exists(os.path.join(result_space_path,
                                                  '.catkin')):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because it does not "
            "appear to be a catkin-generated resultspace (missing .catkin marker "
            "file)." % result_space_path)

    # Determine the shell to use to source the setup file
    shell_path = os.environ.get('SHELL', '')
    if not shell_path:
        shell_path = DEFAULT_SHELL
    if not os.path.isfile(shell_path):
        raise RuntimeError(
            "Cannot determine shell executable. "
            "The 'SHELL' environment variable is not set and "
            "the default '{0}' does not exist.".format(shell_path))
    (_, shell_name) = os.path.split(shell_path)

    # Use fallback shell if using a non-standard shell
    if shell_name not in ['bash', 'zsh']:
        shell_path = DEFAULT_SHELL
        (_, shell_name) = os.path.split(shell_path)

    # Check to make sure result_space_path contains the appropriate setup file
    setup_file_path = os.path.join(result_space_path, 'env.sh')
    if not os.path.exists(setup_file_path):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because the "
            "required setup file \"%s\" does not exist." %
            (result_space_path, setup_file_path))

    # Construct a command list which sources the setup file and prints the env to stdout
    norc_flags = {'bash': '--norc', 'zsh': '-f'}

    command = ' '.join([
        cmd_quote(setup_file_path), shell_path, norc_flags[shell_name], '-c',
        '"typeset -px"'
    ])

    # Define some "blacklisted" environment variables which shouldn't be copied
    blacklisted_keys = ('_', 'PWD')
    env_dict = {}

    try:
        # Run the command synchronously to get the resultspace environmnet
        if 0:
            # NOTE: This sometimes fails to get all output (returns prematurely)
            lines = ''
            for ret in execute_process(command,
                                       cwd=os.getcwd(),
                                       env=base_env,
                                       emulate_tty=False,
                                       shell=True):
                if type(ret) is bytes:
                    ret = ret.decode()
                if isinstance(ret, string_type):
                    lines += ret
        else:
            p = subprocess.Popen(command,
                                 cwd=os.getcwd(),
                                 env=base_env,
                                 shell=True,
                                 stdout=subprocess.PIPE)
            lines, _ = p.communicate()

        # Extract the environment variables
        env_dict = {
            k: v
            for k, v in parse_env_str(lines).items()
            if k not in blacklisted_keys
        }

        # Check to make sure we got some kind of environment
        if len(env_dict) > 0:
            # Cache the result
            _resultspace_env_cache[result_space_path] = (base_env, env_hooks,
                                                         env_dict)
        else:
            print(
                "WARNING: Sourced environment from `{}` has no environment variables. Something is wrong."
                .format(setup_file_path))

    except IOError as err:
        print(
            "WARNING: Failed to extract environment from resultspace: {}: {}".
            format(result_space_path, str(err)),
            file=sys.stderr)

    return dict(env_dict)
Exemple #3
0
def get_resultspace_environment(result_space_path, base_env=None, quiet=False, cached=True, strict=True):
    """Get the environemt variables which result from sourcing another catkin
    workspace's setup files as the string output of `cmake -E environment`.
    This cmake command is used to be as portable as possible.

    :param result_space_path: path to a Catkin result-space whose environment should be loaded, ``str``
    :type result_space_path: str
    :param quiet: don't throw exceptions, ``bool``
    :type quiet: bool
    :param cached: use the cached environment
    :type cached: bool
    :param strict: require the ``.catkin`` file exists in the resultspace
    :type strict: bool

    :returns: a dictionary of environment variables and their values
    """

    # Set bae environment to the current environment
    if base_env is None:
        base_env = dict(os.environ)

    # Get the MD5 checksums for the current env hooks
    # TODO: the env hooks path should be defined somewhere
    env_hooks_path = os.path.join(result_space_path, 'etc', 'catkin', 'profile.d')
    if os.path.exists(env_hooks_path):
        env_hooks = [
            md5(open(os.path.join(env_hooks_path, path)).read().encode('utf-8')).hexdigest()
            for path in os.listdir(env_hooks_path)]
    else:
        env_hooks = []

    # Check the cache first, if desired
    if cached and result_space_path in _resultspace_env_cache:
        (cached_base_env, cached_env_hooks, result_env) = _resultspace_env_cache.get(result_space_path)
        if env_hooks == cached_env_hooks and cached_base_env == base_env:
            return dict(result_env)

    # Check to make sure result_space_path is a valid directory
    if not os.path.isdir(result_space_path):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because it does not "
            "exist." % result_space_path
        )

    # Check to make sure result_space_path contains a `.catkin` file
    # TODO: `.catkin` should be defined somewhere as an atom in catkin_pkg
    if strict and not os.path.exists(os.path.join(result_space_path, '.catkin')):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because it does not "
            "appear to be a catkin-generated resultspace (missing .catkin marker "
            "file)." % result_space_path
        )

    # Determine the shell to use to source the setup file
    shell_path = os.environ.get('SHELL', None)
    if shell_path is None:
        shell_path = DEFAULT_SHELL
        if not os.path.isfile(shell_path):
            raise RuntimeError(
                "Cannot determine shell executable. "
                "The 'SHELL' environment variable is not set and "
                "the default '{0}' does not exist.".format(shell_path)
            )
    (_, shell_name) = os.path.split(shell_path)

    # Use fallback shell if using a non-standard shell
    if shell_name not in ['bash', 'zsh']:
        shell_name = 'bash'

    # Check to make sure result_space_path contains the appropriate setup file
    setup_file_path = os.path.join(result_space_path, 'env.sh')
    if not os.path.exists(setup_file_path):
        if quiet:
            return dict()
        raise IOError(
            "Cannot load environment from resultspace \"%s\" because the "
            "required setup file \"%s\" does not exist." % (result_space_path, setup_file_path)
        )

    # Construct a command list which sources the setup file and prints the env to stdout
    norc_flags = {
        'bash': '--norc',
        'zsh': '-f'
    }

    command = ' '.join([
        cmd_quote(setup_file_path),
        shell_path,
        norc_flags[shell_name],
        '-c',
        '"typeset -px"'
    ])

    # Define some "blacklisted" environment variables which shouldn't be copied
    blacklisted_keys = ('_', 'PWD')
    env_dict = {}

    try:
        # Run the command synchronously to get the resultspace environmnet
        if 0:
            # NOTE: This sometimes fails to get all output (returns prematurely)
            lines = ''
            for ret in execute_process(command, cwd=os.getcwd(), env=base_env, emulate_tty=False, shell=True):
                if type(ret) is bytes:
                    ret = ret.decode()
                if isinstance(ret, string_type):
                    lines += ret
        else:
            p = subprocess.Popen(command, cwd=os.getcwd(), env=base_env, shell=True, stdout=subprocess.PIPE)
            lines, _ = p.communicate()

        # Extract the environment variables
        env_dict = {
            k: v
            for k, v in parse_env_str(lines).items()
            if k not in blacklisted_keys
        }

        # Check to make sure we got some kind of environment
        if len(env_dict) > 0:
            # Cache the result
            _resultspace_env_cache[result_space_path] = (base_env, env_hooks, env_dict)
        else:
            print("WARNING: Sourced environment from `{}` has no environment variables. Something is wrong.".format(
                setup_file_path))

    except IOError as err:
        print("WARNING: Failed to extract environment from resultspace: {}: {}".format(
            result_space_path, str(err)),
            file=sys.stderr)

    return dict(env_dict)