summaryrefslogtreecommitdiffstats
path: root/pre_commit/languages/dart.py
blob: 16e755461fff59fc728f50eb00c66b30beeab6b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import contextlib
import os.path
import shutil
import tempfile
from typing import Generator
from typing import Sequence
from typing import Tuple

import pre_commit.constants as C
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
from pre_commit.envcontext import Var
from pre_commit.hook import Hook
from pre_commit.languages import helpers
from pre_commit.prefix import Prefix
from pre_commit.util import clean_path_on_failure
from pre_commit.util import win_exe
from pre_commit.util import yaml_load

ENVIRONMENT_DIR = 'dartenv'

get_default_version = helpers.basic_get_default_version
healthy = helpers.basic_healthy


def get_env_patch(venv: str) -> PatchesT:
    return (
        ('PATH', (os.path.join(venv, 'bin'), os.pathsep, Var('PATH'))),
    )


@contextlib.contextmanager
def in_env(prefix: Prefix) -> Generator[None, None, None]:
    directory = helpers.environment_dir(ENVIRONMENT_DIR, C.DEFAULT)
    envdir = prefix.path(directory)
    with envcontext(get_env_patch(envdir)):
        yield


def install_environment(
        prefix: Prefix,
        version: str,
        additional_dependencies: Sequence[str],
) -> None:
    helpers.assert_version_default('dart', version)

    envdir = prefix.path(helpers.environment_dir(ENVIRONMENT_DIR, version))
    bin_dir = os.path.join(envdir, 'bin')

    def _install_dir(prefix_p: Prefix, pub_cache: str) -> None:
        dart_env = {**os.environ, 'PUB_CACHE': pub_cache}

        with open(prefix_p.path('pubspec.yaml')) as f:
            pubspec_contents = yaml_load(f)

        helpers.run_setup_cmd(prefix_p, ('dart', 'pub', 'get'), env=dart_env)

        for executable in pubspec_contents['executables']:
            helpers.run_setup_cmd(
                prefix_p,
                (
                    'dart', 'compile', 'exe',
                    '--output', os.path.join(bin_dir, win_exe(executable)),
                    prefix_p.path('bin', f'{executable}.dart'),
                ),
                env=dart_env,
            )

    with clean_path_on_failure(envdir):
        os.makedirs(bin_dir)

        with tempfile.TemporaryDirectory() as tmp:
            _install_dir(prefix, tmp)

        for dep_s in additional_dependencies:
            with tempfile.TemporaryDirectory() as dep_tmp:
                dep, _, version = dep_s.partition(':')
                if version:
                    dep_cmd: Tuple[str, ...] = (dep, '--version', version)
                else:
                    dep_cmd = (dep,)

                helpers.run_setup_cmd(
                    prefix,
                    ('dart', 'pub', 'cache', 'add', *dep_cmd),
                    env={**os.environ, 'PUB_CACHE': dep_tmp},
                )

                # try and find the 'pubspec.yaml' that just got added
                for root, _, filenames in os.walk(dep_tmp):
                    if 'pubspec.yaml' in filenames:
                        with tempfile.TemporaryDirectory() as copied:
                            pkg = os.path.join(copied, 'pkg')
                            shutil.copytree(root, pkg)
                            _install_dir(Prefix(pkg), dep_tmp)
                        break
                else:
                    raise AssertionError(
                        f'could not find pubspec.yaml for {dep_s}',
                    )


def run_hook(
        hook: Hook,
        file_args: Sequence[str],
        color: bool,
) -> Tuple[int, bytes]:
    with in_env(hook.prefix):
        return helpers.run_xargs(hook, hook.cmd, file_args, color=color)