summaryrefslogtreecommitdiffstats
path: root/testing
diff options
context:
space:
mode:
Diffstat (limited to 'testing')
-rwxr-xr-xtesting/gen-languages-all5
-rwxr-xr-xtesting/get-coursier.ps111
-rwxr-xr-xtesting/get-coursier.sh13
-rw-r--r--testing/resources/coursier_hooks_repo/.pre-commit-channel/echo-java.json8
-rw-r--r--testing/resources/coursier_hooks_repo/.pre-commit-hooks.yaml5
-rw-r--r--testing/resources/dotnet_hooks_csproj_repo/.gitignore3
-rw-r--r--testing/resources/dotnet_hooks_csproj_repo/.pre-commit-hooks.yaml5
-rw-r--r--testing/resources/dotnet_hooks_csproj_repo/Program.cs12
-rw-r--r--testing/resources/dotnet_hooks_csproj_repo/dotnet_hooks_csproj_repo.csproj9
-rw-r--r--testing/resources/dotnet_hooks_sln_repo/.gitignore3
-rw-r--r--testing/resources/dotnet_hooks_sln_repo/.pre-commit-hooks.yaml5
-rw-r--r--testing/resources/dotnet_hooks_sln_repo/Program.cs12
-rw-r--r--testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.csproj9
-rw-r--r--testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.sln34
-rw-r--r--testing/util.py4
-rw-r--r--testing/zipapp/Dockerfile14
-rwxr-xr-xtesting/zipapp/entry71
-rwxr-xr-xtesting/zipapp/make106
-rwxr-xr-xtesting/zipapp/python48
19 files changed, 375 insertions, 2 deletions
diff --git a/testing/gen-languages-all b/testing/gen-languages-all
index 2bff7be..d9b01bd 100755
--- a/testing/gen-languages-all
+++ b/testing/gen-languages-all
@@ -2,8 +2,9 @@
import sys
LANGUAGES = [
- 'conda', 'docker', 'docker_image', 'fail', 'golang', 'node', 'perl',
- 'pygrep', 'python', 'ruby', 'rust', 'script', 'swift', 'system',
+ 'conda', 'coursier', 'docker', 'dotnet', 'docker_image', 'fail', 'golang',
+ 'node', 'perl', 'pygrep', 'python', 'ruby', 'rust', 'script', 'swift',
+ 'system',
]
FIELDS = [
'ENVIRONMENT_DIR', 'get_default_version', 'healthy', 'install_environment',
diff --git a/testing/get-coursier.ps1 b/testing/get-coursier.ps1
new file mode 100755
index 0000000..42e5635
--- /dev/null
+++ b/testing/get-coursier.ps1
@@ -0,0 +1,11 @@
+$wc = New-Object System.Net.WebClient
+
+$coursier_url = "https://github.com/coursier/coursier/releases/download/v2.0.5/cs-x86_64-pc-win32.exe"
+$coursier_dest = "C:\coursier\cs.exe"
+$coursier_hash ="d63d497f7805261e1cd657b8aaa626f6b8f7264cdb68219b2e6be9dd882033a9"
+
+New-Item -Path "C:\" -Name "coursier" -ItemType "directory"
+$wc.DownloadFile($coursier_url, $coursier_dest)
+if ((Get-FileHash $coursier_dest -Algorithm SHA256).Hash -ne $coursier_hash) {
+ throw "Invalid coursier file"
+}
diff --git a/testing/get-coursier.sh b/testing/get-coursier.sh
new file mode 100755
index 0000000..760c6c1
--- /dev/null
+++ b/testing/get-coursier.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# This is a script used in CI to install coursier
+set -euxo pipefail
+
+COURSIER_URL="https://github.com/coursier/coursier/releases/download/v2.0.0/cs-x86_64-pc-linux"
+COURSIER_HASH="e2e838b75bc71b16bcb77ce951ad65660c89bda7957c79a0628ec7146d35122f"
+ARTIFACT="/tmp/coursier/cs"
+
+mkdir -p /tmp/coursier
+rm -f "$ARTIFACT"
+curl --location --silent --output "$ARTIFACT" "$COURSIER_URL"
+echo "$COURSIER_HASH $ARTIFACT" | sha256sum --check
+chmod ugo+x /tmp/coursier/cs
diff --git a/testing/resources/coursier_hooks_repo/.pre-commit-channel/echo-java.json b/testing/resources/coursier_hooks_repo/.pre-commit-channel/echo-java.json
new file mode 100644
index 0000000..37f401e
--- /dev/null
+++ b/testing/resources/coursier_hooks_repo/.pre-commit-channel/echo-java.json
@@ -0,0 +1,8 @@
+{
+ "repositories": [
+ "central"
+ ],
+ "dependencies": [
+ "io.get-coursier:echo:latest.stable"
+ ]
+}
diff --git a/testing/resources/coursier_hooks_repo/.pre-commit-hooks.yaml b/testing/resources/coursier_hooks_repo/.pre-commit-hooks.yaml
new file mode 100644
index 0000000..d4a143b
--- /dev/null
+++ b/testing/resources/coursier_hooks_repo/.pre-commit-hooks.yaml
@@ -0,0 +1,5 @@
+- id: echo-java
+ name: echo-java
+ description: echo from java
+ entry: echo-java
+ language: coursier
diff --git a/testing/resources/dotnet_hooks_csproj_repo/.gitignore b/testing/resources/dotnet_hooks_csproj_repo/.gitignore
new file mode 100644
index 0000000..edcd28f
--- /dev/null
+++ b/testing/resources/dotnet_hooks_csproj_repo/.gitignore
@@ -0,0 +1,3 @@
+bin/
+obj/
+nupkg/
diff --git a/testing/resources/dotnet_hooks_csproj_repo/.pre-commit-hooks.yaml b/testing/resources/dotnet_hooks_csproj_repo/.pre-commit-hooks.yaml
new file mode 100644
index 0000000..d005a74
--- /dev/null
+++ b/testing/resources/dotnet_hooks_csproj_repo/.pre-commit-hooks.yaml
@@ -0,0 +1,5 @@
+- id: dotnet example hook
+ name: dotnet example hook
+ entry: testeroni
+ language: dotnet
+ files: ''
diff --git a/testing/resources/dotnet_hooks_csproj_repo/Program.cs b/testing/resources/dotnet_hooks_csproj_repo/Program.cs
new file mode 100644
index 0000000..1456e8e
--- /dev/null
+++ b/testing/resources/dotnet_hooks_csproj_repo/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace dotnet_hooks_repo
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from dotnet!");
+ }
+ }
+}
diff --git a/testing/resources/dotnet_hooks_csproj_repo/dotnet_hooks_csproj_repo.csproj b/testing/resources/dotnet_hooks_csproj_repo/dotnet_hooks_csproj_repo.csproj
new file mode 100644
index 0000000..d2e556a
--- /dev/null
+++ b/testing/resources/dotnet_hooks_csproj_repo/dotnet_hooks_csproj_repo.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ <PackAsTool>true</PackAsTool>
+ <ToolCommandName>testeroni</ToolCommandName>
+ <PackageOutputPath>./nupkg</PackageOutputPath>
+ </PropertyGroup>
+</Project>
diff --git a/testing/resources/dotnet_hooks_sln_repo/.gitignore b/testing/resources/dotnet_hooks_sln_repo/.gitignore
new file mode 100644
index 0000000..edcd28f
--- /dev/null
+++ b/testing/resources/dotnet_hooks_sln_repo/.gitignore
@@ -0,0 +1,3 @@
+bin/
+obj/
+nupkg/
diff --git a/testing/resources/dotnet_hooks_sln_repo/.pre-commit-hooks.yaml b/testing/resources/dotnet_hooks_sln_repo/.pre-commit-hooks.yaml
new file mode 100644
index 0000000..d005a74
--- /dev/null
+++ b/testing/resources/dotnet_hooks_sln_repo/.pre-commit-hooks.yaml
@@ -0,0 +1,5 @@
+- id: dotnet example hook
+ name: dotnet example hook
+ entry: testeroni
+ language: dotnet
+ files: ''
diff --git a/testing/resources/dotnet_hooks_sln_repo/Program.cs b/testing/resources/dotnet_hooks_sln_repo/Program.cs
new file mode 100644
index 0000000..04ad4e0
--- /dev/null
+++ b/testing/resources/dotnet_hooks_sln_repo/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace dotnet_hooks_sln_repo
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello from dotnet!");
+ }
+ }
+}
diff --git a/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.csproj b/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.csproj
new file mode 100644
index 0000000..e372964
--- /dev/null
+++ b/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.csproj
@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ <PackAsTool>true</PackAsTool>
+ <ToolCommandName>testeroni</ToolCommandName>
+ <PackageOutputPath>./nupkg</PackageOutputPath>
+ </PropertyGroup>
+</Project>
diff --git a/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.sln b/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.sln
new file mode 100644
index 0000000..87d2afb
--- /dev/null
+++ b/testing/resources/dotnet_hooks_sln_repo/dotnet_hooks_sln_repo.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnet_hooks_sln_repo", "dotnet_hooks_sln_repo.csproj", "{6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x64.Build.0 = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Debug|x86.Build.0 = Debug|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x64.ActiveCfg = Release|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x64.Build.0 = Release|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x86.ActiveCfg = Release|Any CPU
+ {6568CFDB-6F6F-45A9-932C-8C7DAABC8E56}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/testing/util.py b/testing/util.py
index f556a8d..18cd734 100644
--- a/testing/util.py
+++ b/testing/util.py
@@ -40,6 +40,10 @@ def cmd_output_mocked_pre_commit_home(
return ret, out.replace('\r\n', '\n'), None
+skipif_cant_run_coursier = pytest.mark.skipif(
+ os.name == 'nt' or parse_shebang.find_executable('cs') is None,
+ reason="coursier isn't installed or can't be found",
+)
skipif_cant_run_docker = pytest.mark.skipif(
os.name == 'nt' or not docker_is_running(),
reason="Docker isn't running or can't be accessed",
diff --git a/testing/zipapp/Dockerfile b/testing/zipapp/Dockerfile
new file mode 100644
index 0000000..e21d5fe
--- /dev/null
+++ b/testing/zipapp/Dockerfile
@@ -0,0 +1,14 @@
+FROM ubuntu:bionic
+RUN : \
+ && apt-get update \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ python3 \
+ python3-distutils \
+ python3-venv \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+ENV LANG=C.UTF-8 PATH=/venv/bin:$PATH
+RUN : \
+ && python3.6 -mvenv /venv \
+ && pip install --no-cache-dir pip setuptools wheel no-manylinux --upgrade
diff --git a/testing/zipapp/entry b/testing/zipapp/entry
new file mode 100755
index 0000000..f0a345e
--- /dev/null
+++ b/testing/zipapp/entry
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+import os.path
+import shutil
+import stat
+import sys
+import tempfile
+import zipfile
+
+from pre_commit.file_lock import lock
+
+CACHE_DIR = os.path.expanduser('~/.cache/pre-commit-zipapp')
+
+
+def _make_executable(filename: str) -> None:
+ os.chmod(filename, os.stat(filename).st_mode | stat.S_IXUSR)
+
+
+def _ensure_cache(zipf: zipfile.ZipFile, cache_key: str) -> str:
+ os.makedirs(CACHE_DIR, exist_ok=True)
+
+ cache_dest = os.path.join(CACHE_DIR, cache_key)
+ lock_filename = os.path.join(CACHE_DIR, f'{cache_key}.lock')
+
+ if os.path.exists(cache_dest):
+ return cache_dest
+
+ with lock(lock_filename, blocked_cb=lambda: None):
+ # another process may have completed this work
+ if os.path.exists(cache_dest):
+ return cache_dest
+
+ tmpdir = tempfile.mkdtemp(prefix=os.path.join(CACHE_DIR, ''))
+ try:
+ zipf.extractall(tmpdir)
+ # zip doesn't maintain permissions
+ _make_executable(os.path.join(tmpdir, 'python'))
+ _make_executable(os.path.join(tmpdir, 'python.exe'))
+ os.rename(tmpdir, cache_dest)
+ except BaseException:
+ shutil.rmtree(tmpdir)
+ raise
+
+ return cache_dest
+
+
+def main() -> int:
+ with zipfile.ZipFile(os.path.dirname(__file__)) as zipf:
+ with zipf.open('CACHE_KEY') as f:
+ cache_key = f.read().decode().strip()
+
+ cache_dest = _ensure_cache(zipf, cache_key)
+
+ if sys.platform != 'win32':
+ exe = os.path.join(cache_dest, 'python')
+ else:
+ exe = os.path.join(cache_dest, 'python.exe')
+
+ cmd = (exe, '-mpre_commit', *sys.argv[1:])
+ if sys.platform == 'win32': # https://bugs.python.org/issue19124
+ import subprocess
+
+ if sys.version_info < (3, 7): # https://bugs.python.org/issue25942
+ return subprocess.Popen(cmd).wait()
+ else:
+ return subprocess.call(cmd)
+ else:
+ os.execvp(cmd[0], cmd)
+
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/testing/zipapp/make b/testing/zipapp/make
new file mode 100755
index 0000000..a644946
--- /dev/null
+++ b/testing/zipapp/make
@@ -0,0 +1,106 @@
+#!/usr/bin/env python3
+import argparse
+import base64
+import hashlib
+import importlib.resources
+import io
+import os.path
+import shutil
+import subprocess
+import tempfile
+import zipapp
+import zipfile
+
+HERE = os.path.dirname(os.path.realpath(__file__))
+IMG = 'make-pre-commit-zipapp'
+
+
+def _msg(s: str) -> None:
+ print(f'\033[7m{s}\033[m')
+
+
+def _exit_if_retv(*cmd: str) -> None:
+ if subprocess.call(cmd):
+ raise SystemExit(1)
+
+
+def _check_no_shared_objects(wheeldir: str) -> None:
+ for zip_filename in os.listdir(wheeldir):
+ with zipfile.ZipFile(os.path.join(wheeldir, zip_filename)) as zipf:
+ for filename in zipf.namelist():
+ if filename.endswith('.so') or '.so.' in filename:
+ raise AssertionError(zip_filename, filename)
+
+
+def _add_shim(dest: str) -> None:
+ shim = os.path.join(HERE, 'python')
+ shutil.copy(shim, dest)
+
+ bio = io.BytesIO()
+ with zipfile.ZipFile(bio, 'w') as zipf:
+ zipf.write(shim, arcname='__main__.py')
+
+ with open(os.path.join(dest, 'python.exe'), 'wb') as f:
+ f.write(importlib.resources.read_binary('distlib', 't32.exe'))
+ f.write(b'#!py.exe -3\n')
+ f.write(bio.getvalue())
+
+
+def _write_cache_key(version: str, wheeldir: str, dest: str) -> None:
+ cache_hash = hashlib.sha256(f'{version}\n'.encode())
+ for filename in sorted(os.listdir(wheeldir)):
+ cache_hash.update(f'{filename}\n'.encode())
+ with open(os.path.join(HERE, 'python'), 'rb') as f:
+ cache_hash.update(f.read())
+ with open(os.path.join(dest, 'CACHE_KEY'), 'wb') as f:
+ f.write(base64.urlsafe_b64encode(cache_hash.digest()).rstrip(b'='))
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser()
+ parser.add_argument('version')
+ args = parser.parse_args()
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ wheeldir = os.path.join(tmpdir, 'wheels')
+ os.mkdir(wheeldir)
+
+ _msg('building podman image...')
+ _exit_if_retv('podman', 'build', '-q', '-t', IMG, HERE)
+
+ _msg('populating wheels...')
+ _exit_if_retv(
+ 'podman', 'run', '--rm', '--volume', f'{wheeldir}:/wheels:rw', IMG,
+ 'pip', 'wheel', f'pre_commit=={args.version}',
+ '--wheel-dir', '/wheels',
+ )
+
+ _msg('validating wheels...')
+ _check_no_shared_objects(wheeldir)
+
+ _msg('adding __main__.py...')
+ mainfile = os.path.join(tmpdir, '__main__.py')
+ shutil.copy(os.path.join(HERE, 'entry'), mainfile)
+
+ _msg('adding shim...')
+ _add_shim(tmpdir)
+
+ _msg('copying file_lock.py...')
+ file_lock_py = os.path.join(HERE, '../../pre_commit/file_lock.py')
+ file_lock_py_dest = os.path.join(tmpdir, 'pre_commit/file_lock.py')
+ os.makedirs(os.path.dirname(file_lock_py_dest))
+ shutil.copy(file_lock_py, file_lock_py_dest)
+
+ _msg('writing CACHE_KEY...')
+ _write_cache_key(args.version, wheeldir, tmpdir)
+
+ filename = f'pre-commit-{args.version}.pyz'
+ _msg(f'writing {filename}...')
+ shebang = '/usr/bin/env python3'
+ zipapp.create_archive(tmpdir, filename, interpreter=shebang)
+
+ return 0
+
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/testing/zipapp/python b/testing/zipapp/python
new file mode 100755
index 0000000..97c5928
--- /dev/null
+++ b/testing/zipapp/python
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+"""A shim executable to put dependencies on sys.path"""
+import argparse
+import os.path
+import runpy
+import sys
+
+# an exe-zipapp will have a __file__ of shim.exe/__main__.py
+EXE = __file__ if os.path.isfile(__file__) else os.path.dirname(__file__)
+EXE = os.path.realpath(EXE)
+HERE = os.path.dirname(EXE)
+WHEELDIR = os.path.join(HERE, 'wheels')
+SITE_DIRS = frozenset(('dist-packages', 'site-packages'))
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(add_help=False)
+ parser.add_argument('-m')
+ args, rest = parser.parse_known_args()
+
+ if args.m:
+ # try and remove site-packages from sys.path so our packages win
+ sys.path[:] = [
+ p for p in sys.path
+ if os.path.split(p)[1] not in SITE_DIRS
+ ]
+ for wheel in sorted(os.listdir(WHEELDIR)):
+ sys.path.append(os.path.join(WHEELDIR, wheel))
+ if args.m == 'pre_commit' or args.m.startswith('pre_commit.'):
+ sys.executable = EXE
+ sys.argv[1:] = rest
+ runpy.run_module(args.m, run_name='__main__', alter_sys=True)
+ return 0
+ else:
+ cmd = (sys.executable, *sys.argv[1:])
+ if sys.platform == 'win32': # https://bugs.python.org/issue19124
+ import subprocess
+
+ if sys.version_info < (3, 7): # https://bugs.python.org/issue25942
+ return subprocess.Popen(cmd).wait()
+ else:
+ return subprocess.call(cmd)
+ else:
+ os.execvp(cmd[0], cmd)
+
+
+if __name__ == '__main__':
+ exit(main())