1import contextlib
2import os
3
4from pre_commit.envcontext import envcontext
5from pre_commit.envcontext import UNSET
6from pre_commit.envcontext import Var
7from pre_commit.languages import helpers
8from pre_commit.util import clean_path_on_failure
9from pre_commit.util import cmd_output_b
10
11ENVIRONMENT_DIR = 'conda'
12get_default_version = helpers.basic_get_default_version
13healthy = helpers.basic_healthy
14
15
16def get_env_patch(env):
17    # On non-windows systems executable live in $CONDA_PREFIX/bin, on Windows
18    # they can be in $CONDA_PREFIX/bin, $CONDA_PREFIX/Library/bin,
19    # $CONDA_PREFIX/Scripts and $CONDA_PREFIX. Whereas the latter only
20    # seems to be used for python.exe.
21    path = (os.path.join(env, 'bin'), os.pathsep, Var('PATH'))
22    if os.name == 'nt':  # pragma: no cover (platform specific)
23        path = (env, os.pathsep) + path
24        path = (os.path.join(env, 'Scripts'), os.pathsep) + path
25        path = (os.path.join(env, 'Library', 'bin'), os.pathsep) + path
26
27    return (
28        ('PYTHONHOME', UNSET),
29        ('VIRTUAL_ENV', UNSET),
30        ('CONDA_PREFIX', env),
31        ('PATH', path),
32    )
33
34
35@contextlib.contextmanager
36def in_env(prefix, language_version):
37    directory = helpers.environment_dir(ENVIRONMENT_DIR, language_version)
38    envdir = prefix.path(directory)
39    with envcontext(get_env_patch(envdir)):
40        yield
41
42
43def install_environment(prefix, version, additional_dependencies):
44    helpers.assert_version_default('conda', version)
45    directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
46
47    env_dir = prefix.path(directory)
48    with clean_path_on_failure(env_dir):
49        cmd_output_b(
50            'conda', 'env', 'create', '-p', env_dir, '--file',
51            'environment.yml', cwd=prefix.prefix_dir,
52        )
53        if additional_dependencies:
54            cmd_output_b(
55                'conda', 'install', '-p', env_dir, *additional_dependencies,
56                cwd=prefix.prefix_dir
57            )
58
59
60def run_hook(hook, file_args, color):
61    # TODO: Some rare commands need to be run using `conda run` but mostly we
62    #       can run them withot which is much quicker and produces a better
63    #       output.
64    # cmd = ('conda', 'run', '-p', env_dir) + hook.cmd
65    with in_env(hook.prefix, hook.language_version):
66        return helpers.run_xargs(hook, hook.cmd, file_args, color=color)
67