132 lines
4.3 KiB
Python
132 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import contextlib
|
|
import os
|
|
import shutil
|
|
from collections.abc import Generator
|
|
from collections.abc import Sequence
|
|
|
|
from pre_commit import lang_base
|
|
from pre_commit.envcontext import envcontext
|
|
from pre_commit.envcontext import PatchesT
|
|
from pre_commit.envcontext import UNSET
|
|
from pre_commit.prefix import Prefix
|
|
from pre_commit.util import cmd_output_b
|
|
|
|
ENVIRONMENT_DIR = 'juliaenv'
|
|
health_check = lang_base.basic_health_check
|
|
get_default_version = lang_base.basic_get_default_version
|
|
|
|
|
|
def run_hook(
|
|
prefix: Prefix,
|
|
entry: str,
|
|
args: Sequence[str],
|
|
file_args: Sequence[str],
|
|
*,
|
|
is_local: bool,
|
|
require_serial: bool,
|
|
color: bool,
|
|
) -> tuple[int, bytes]:
|
|
# `entry` is a (hook-repo relative) file followed by (optional) args, e.g.
|
|
# `bin/id.jl` or `bin/hook.jl --arg1 --arg2` so we
|
|
# 1) shell parse it and join with args with hook_cmd
|
|
# 2) prepend the hooks prefix path to the first argument (the file), unless
|
|
# it is a local script
|
|
# 3) prepend `julia` as the interpreter
|
|
|
|
cmd = lang_base.hook_cmd(entry, args)
|
|
script = cmd[0] if is_local else prefix.path(cmd[0])
|
|
cmd = ('julia', script, *cmd[1:])
|
|
return lang_base.run_xargs(
|
|
cmd,
|
|
file_args,
|
|
require_serial=require_serial,
|
|
color=color,
|
|
)
|
|
|
|
|
|
def get_env_patch(target_dir: str, version: str) -> PatchesT:
|
|
return (
|
|
('JULIA_LOAD_PATH', target_dir),
|
|
# May be set, remove it to not interfer with LOAD_PATH
|
|
('JULIA_PROJECT', UNSET),
|
|
)
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def in_env(prefix: Prefix, version: str) -> Generator[None]:
|
|
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
|
|
with envcontext(get_env_patch(envdir, version)):
|
|
yield
|
|
|
|
|
|
def install_environment(
|
|
prefix: Prefix,
|
|
version: str,
|
|
additional_dependencies: Sequence[str],
|
|
) -> None:
|
|
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
|
|
with in_env(prefix, version):
|
|
# TODO: Support language_version with juliaup similar to rust via
|
|
# rustup
|
|
# if version != 'system':
|
|
# ...
|
|
|
|
# Copy Project.toml to hook env if it exist
|
|
os.makedirs(envdir, exist_ok=True)
|
|
project_names = ('JuliaProject.toml', 'Project.toml')
|
|
project_found = False
|
|
for project_name in project_names:
|
|
project_file = prefix.path(project_name)
|
|
if not os.path.isfile(project_file):
|
|
continue
|
|
shutil.copy(project_file, envdir)
|
|
project_found = True
|
|
break
|
|
|
|
# If no project file was found we create an empty one so that the
|
|
# package manager doesn't error
|
|
if not project_found:
|
|
open(os.path.join(envdir, 'Project.toml'), 'a').close()
|
|
|
|
# Copy Manifest.toml to hook env if it exists
|
|
manifest_names = ('JuliaManifest.toml', 'Manifest.toml')
|
|
for manifest_name in manifest_names:
|
|
manifest_file = prefix.path(manifest_name)
|
|
if not os.path.isfile(manifest_file):
|
|
continue
|
|
shutil.copy(manifest_file, envdir)
|
|
break
|
|
|
|
# Julia code to instantiate the hook environment
|
|
julia_code = """
|
|
@assert length(ARGS) > 0
|
|
hook_env = ARGS[1]
|
|
deps = join(ARGS[2:end], " ")
|
|
|
|
# We prepend @stdlib here so that we can load the package manager even
|
|
# though `get_env_patch` limits `JULIA_LOAD_PATH` to just the hook env.
|
|
pushfirst!(LOAD_PATH, "@stdlib")
|
|
using Pkg
|
|
popfirst!(LOAD_PATH)
|
|
|
|
# Instantiate the environment shipped with the hook repo. If we have
|
|
# additional dependencies we disable precompilation in this step to
|
|
# avoid double work.
|
|
precompile = isempty(deps) ? "1" : "0"
|
|
withenv("JULIA_PKG_PRECOMPILE_AUTO" => precompile) do
|
|
Pkg.instantiate()
|
|
end
|
|
|
|
# Add additional dependencies (with precompilation)
|
|
if !isempty(deps)
|
|
withenv("JULIA_PKG_PRECOMPILE_AUTO" => "1") do
|
|
Pkg.REPLMode.pkgstr("add " * deps)
|
|
end
|
|
end
|
|
"""
|
|
cmd_output_b(
|
|
'julia', '-e', julia_code, '--', envdir, *additional_dependencies,
|
|
cwd=prefix.prefix_dir,
|
|
)
|