summaryrefslogtreecommitdiffstats
path: root/pre_commit/languages
diff options
context:
space:
mode:
Diffstat (limited to 'pre_commit/languages')
-rw-r--r--pre_commit/languages/docker.py33
-rw-r--r--pre_commit/languages/r.py53
2 files changed, 63 insertions, 23 deletions
diff --git a/pre_commit/languages/docker.py b/pre_commit/languages/docker.py
index 9d30568..5b21ec9 100644
--- a/pre_commit/languages/docker.py
+++ b/pre_commit/languages/docker.py
@@ -1,5 +1,7 @@
import hashlib
+import json
import os
+import socket
from typing import Sequence
from typing import Tuple
@@ -8,6 +10,7 @@ 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 cmd_output_b
ENVIRONMENT_DIR = 'docker'
PRE_COMMIT_LABEL = 'PRE_COMMIT'
@@ -15,6 +18,34 @@ get_default_version = helpers.basic_get_default_version
healthy = helpers.basic_healthy
+def _is_in_docker() -> bool:
+ try:
+ with open('/proc/1/cgroup', 'rb') as f:
+ return b'docker' in f.read()
+ except FileNotFoundError:
+ return False
+
+
+def _get_docker_path(path: str) -> str:
+ if not _is_in_docker():
+ return path
+ hostname = socket.gethostname()
+
+ _, out, _ = cmd_output_b('docker', 'inspect', hostname)
+
+ container, = json.loads(out)
+ for mount in container['Mounts']:
+ src_path = mount['Source']
+ to_path = mount['Destination']
+ if os.path.commonpath((path, to_path)) == to_path:
+ # So there is something in common,
+ # and we can proceed remapping it
+ return path.replace(to_path, src_path)
+ # we're in Docker, but the path is not mounted, cannot really do anything,
+ # so fall back to original path
+ return path
+
+
def md5(s: str) -> str: # pragma: win32 no cover
return hashlib.md5(s.encode()).hexdigest()
@@ -73,7 +104,7 @@ def docker_cmd() -> Tuple[str, ...]: # pragma: win32 no cover
# https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from
# The `Z` option tells Docker to label the content with a private
# unshared label. Only the current container can use a private volume.
- '-v', f'{os.getcwd()}:/src:rw,Z',
+ '-v', f'{_get_docker_path(os.getcwd())}:/src:rw,Z',
'--workdir', '/src',
)
diff --git a/pre_commit/languages/r.py b/pre_commit/languages/r.py
index 83e6000..d573775 100644
--- a/pre_commit/languages/r.py
+++ b/pre_commit/languages/r.py
@@ -15,6 +15,7 @@ from pre_commit.util import clean_path_on_failure
from pre_commit.util import cmd_output_b
ENVIRONMENT_DIR = 'renv'
+RSCRIPT_OPTS = ('--no-save', '--no-restore', '--no-site-file', '--no-environ')
get_default_version = helpers.basic_get_default_version
healthy = helpers.basic_healthy
@@ -39,14 +40,19 @@ def _get_env_dir(prefix: Prefix, version: str) -> str:
return prefix.path(helpers.environment_dir(ENVIRONMENT_DIR, version))
-def _prefix_if_file_entry(
+def _prefix_if_non_local_file_entry(
entry: Sequence[str],
prefix: Prefix,
+ src: str,
) -> Sequence[str]:
if entry[1] == '-e':
return entry[1:]
else:
- return (prefix.path(entry[1]),)
+ if src == 'local':
+ path = entry[1]
+ else:
+ path = prefix.path(entry[1])
+ return (path,)
def _entry_validate(entry: Sequence[str]) -> None:
@@ -69,13 +75,12 @@ def _entry_validate(entry: Sequence[str]) -> None:
def _cmd_from_hook(hook: Hook) -> Tuple[str, ...]:
- opts = ('--no-save', '--no-restore', '--no-site-file', '--no-environ')
entry = shlex.split(hook.entry)
_entry_validate(entry)
return (
- *entry[:1], *opts,
- *_prefix_if_file_entry(entry, hook.prefix),
+ *entry[:1], *RSCRIPT_OPTS,
+ *_prefix_if_non_local_file_entry(entry, hook.prefix, hook.src),
*hook.args,
)
@@ -89,29 +94,32 @@ def install_environment(
with clean_path_on_failure(env_dir):
os.makedirs(env_dir, exist_ok=True)
shutil.copy(prefix.path('renv.lock'), env_dir)
+ shutil.copytree(prefix.path('renv'), os.path.join(env_dir, 'renv'))
cmd_output_b(
'Rscript', '--vanilla', '-e',
f"""\
prefix_dir <- {prefix.prefix_dir!r}
- missing_pkgs <- setdiff(
- "renv", unname(installed.packages()[, "Package"])
- )
options(
repos = c(CRAN = "https://cran.rstudio.com"),
renv.consent = TRUE
)
- install.packages(missing_pkgs)
- renv::activate()
+ source("renv/activate.R")
renv::restore()
activate_statement <- paste0(
- 'renv::activate("', file.path(getwd()), '"); '
+ 'suppressWarnings({{',
+ 'old <- setwd("', getwd(), '"); ',
+ 'source("renv/activate.R"); ',
+ 'setwd(old); ',
+ 'renv::load("', getwd(), '");}})'
)
writeLines(activate_statement, 'activate.R')
- is_package <- tryCatch({{
- content_desc <- read.dcf(file.path(prefix_dir, 'DESCRIPTION'))
- suppressWarnings(unname(content_desc[,'Type']) == "Package")
- }},
- error = function(...) FALSE
+ is_package <- tryCatch(
+ {{
+ path_desc <- file.path(prefix_dir, 'DESCRIPTION')
+ suppressWarnings(desc <- read.dcf(path_desc))
+ "Package" %in% colnames(desc)
+ }},
+ error = function(...) FALSE
)
if (is_package) {{
renv::install(prefix_dir)
@@ -120,12 +128,13 @@ def install_environment(
cwd=env_dir,
)
if additional_dependencies:
- cmd_output_b(
- 'Rscript', '-e',
- 'renv::install(commandArgs(trailingOnly = TRUE))',
- *additional_dependencies,
- cwd=env_dir,
- )
+ with in_env(prefix, version):
+ cmd_output_b(
+ 'Rscript', *RSCRIPT_OPTS, '-e',
+ 'renv::install(commandArgs(trailingOnly = TRUE))',
+ *additional_dependencies,
+ cwd=env_dir,
+ )
def run_hook(