1
0
Fork 0

Adding upstream version 2.2.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 21:10:22 +01:00
parent 18c908e4f3
commit c0d06915b7
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
199 changed files with 14930 additions and 0 deletions

0
testing/__init__.py Normal file
View file

View file

@ -0,0 +1,11 @@
import collections
def auto_namedtuple(classname='auto_namedtuple', **kwargs):
"""Returns an automatic namedtuple object.
Args:
classname - The class name for the returned object.
**kwargs - Properties to give the returned object.
"""
return (collections.namedtuple(classname, kwargs.keys())(**kwargs))

146
testing/fixtures.py Normal file
View file

@ -0,0 +1,146 @@
import contextlib
import os.path
import shutil
from cfgv import apply_defaults
from cfgv import validate
import pre_commit.constants as C
from pre_commit import git
from pre_commit.clientlib import CONFIG_SCHEMA
from pre_commit.clientlib import load_manifest
from pre_commit.util import cmd_output
from pre_commit.util import yaml_dump
from pre_commit.util import yaml_load
from testing.util import get_resource_path
from testing.util import git_commit
def copy_tree_to_path(src_dir, dest_dir):
"""Copies all of the things inside src_dir to an already existing dest_dir.
This looks eerily similar to shutil.copytree, but copytree has no option
for not creating dest_dir.
"""
names = os.listdir(src_dir)
for name in names:
srcname = os.path.join(src_dir, name)
destname = os.path.join(dest_dir, name)
if os.path.isdir(srcname):
shutil.copytree(srcname, destname)
else:
shutil.copy(srcname, destname)
def git_dir(tempdir_factory):
path = tempdir_factory.get()
cmd_output('git', 'init', path)
return path
def make_repo(tempdir_factory, repo_source):
path = git_dir(tempdir_factory)
copy_tree_to_path(get_resource_path(repo_source), path)
cmd_output('git', 'add', '.', cwd=path)
git_commit(msg=make_repo.__name__, cwd=path)
return path
@contextlib.contextmanager
def modify_manifest(path, commit=True):
"""Modify the manifest yielded by this context to write to
.pre-commit-hooks.yaml.
"""
manifest_path = os.path.join(path, C.MANIFEST_FILE)
with open(manifest_path) as f:
manifest = yaml_load(f.read())
yield manifest
with open(manifest_path, 'w') as manifest_file:
manifest_file.write(yaml_dump(manifest))
if commit:
git_commit(msg=modify_manifest.__name__, cwd=path)
@contextlib.contextmanager
def modify_config(path='.', commit=True):
"""Modify the config yielded by this context to write to
.pre-commit-config.yaml
"""
config_path = os.path.join(path, C.CONFIG_FILE)
with open(config_path) as f:
config = yaml_load(f.read())
yield config
with open(config_path, 'w', encoding='UTF-8') as config_file:
config_file.write(yaml_dump(config))
if commit:
git_commit(msg=modify_config.__name__, cwd=path)
def sample_local_config():
return {
'repo': 'local',
'hooks': [{
'id': 'do_not_commit',
'name': 'Block if "DO NOT COMMIT" is found',
'entry': 'DO NOT COMMIT',
'language': 'pygrep',
}],
}
def sample_meta_config():
return {'repo': 'meta', 'hooks': [{'id': 'check-useless-excludes'}]}
def make_config_from_repo(repo_path, rev=None, hooks=None, check=True):
manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
config = {
'repo': f'file://{repo_path}',
'rev': rev or git.head_rev(repo_path),
'hooks': hooks or [{'id': hook['id']} for hook in manifest],
}
if check:
wrapped = validate({'repos': [config]}, CONFIG_SCHEMA)
wrapped = apply_defaults(wrapped, CONFIG_SCHEMA)
config, = wrapped['repos']
return config
else:
return config
def read_config(directory, config_file=C.CONFIG_FILE):
config_path = os.path.join(directory, config_file)
with open(config_path) as f:
config = yaml_load(f.read())
return config
def write_config(directory, config, config_file=C.CONFIG_FILE):
if type(config) is not list and 'repos' not in config:
assert isinstance(config, dict), config
config = {'repos': [config]}
with open(os.path.join(directory, config_file), 'w') as outfile:
outfile.write(yaml_dump(config))
def add_config_to_repo(git_path, config, config_file=C.CONFIG_FILE):
write_config(git_path, config, config_file=config_file)
cmd_output('git', 'add', config_file, cwd=git_path)
git_commit(msg=add_config_to_repo.__name__, cwd=git_path)
return git_path
def remove_config_from_repo(git_path, config_file=C.CONFIG_FILE):
cmd_output('git', 'rm', config_file, cwd=git_path)
git_commit(msg=remove_config_from_repo.__name__, cwd=git_path)
return git_path
def make_consuming_repo(tempdir_factory, repo_source):
path = make_repo(tempdir_factory, repo_source)
config = make_config_from_repo(path)
git_path = git_dir(tempdir_factory)
return add_config_to_repo(git_path, config)

28
testing/gen-languages-all Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env python3
import sys
LANGUAGES = [
'conda', 'docker', 'docker_image', 'fail', 'golang', 'node', 'perl',
'pygrep', 'python', 'python_venv', 'ruby', 'rust', 'script', 'swift',
'system',
]
FIELDS = [
'ENVIRONMENT_DIR', 'get_default_version', 'healthy', 'install_environment',
'run_hook',
]
def main() -> int:
print(f' # BEGIN GENERATED ({sys.argv[0]})')
for lang in LANGUAGES:
parts = [f' {lang!r}: Language(name={lang!r}']
for k in FIELDS:
parts.append(f', {k}={lang}.{k}')
parts.append('), # noqa: E501')
print(''.join(parts))
print(' # END GENERATED')
return 0
if __name__ == '__main__':
exit(main())

27
testing/get-swift.sh Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# This is a script used in CI to install swift
set -euxo pipefail
. /etc/lsb-release
if [ "$DISTRIB_CODENAME" = "bionic" ]; then
SWIFT_URL='https://swift.org/builds/swift-5.1.3-release/ubuntu1804/swift-5.1.3-RELEASE/swift-5.1.3-RELEASE-ubuntu18.04.tar.gz'
SWIFT_HASH='ac82ccd773fe3d586fc340814e31e120da1ff695c6a712f6634e9cc720769610'
else
echo "unknown dist: ${DISTRIB_CODENAME}" 1>&2
exit 1
fi
check() {
echo "$SWIFT_HASH $TGZ" | sha256sum --check
}
TGZ="$HOME/.swift/swift.tar.gz"
mkdir -p "$(dirname "$TGZ")"
if ! check >& /dev/null; then
rm -f "$TGZ"
curl --location --silent --output "$TGZ" "$SWIFT_URL"
check
fi
mkdir -p /tmp/swift
tar -xf "$TGZ" --strip 1 --directory /tmp/swift

View file

@ -0,0 +1,5 @@
- id: hook
name: hook
entry: ./hook.sh
language: script
files: \.py$

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Intentionally write mixed encoding to the output. This should not crash
# pre-commit and should write bytes to the output.
# '☃'.encode() + '²'.encode('latin1')
echo -e '\xe2\x98\x83\xb2'
# exit 1 to trigger printing
exit 1

View file

@ -0,0 +1,6 @@
- id: arg-per-line
name: Args per line hook
entry: bin/hook.sh
language: script
files: ''
args: [hello, world]

View file

@ -0,0 +1,5 @@
#!/usr/bin/env bash
for i in "$@"; do
echo "arg: $i"
done

View file

@ -0,0 +1,10 @@
- id: sys-exec
name: sys-exec
entry: python -c 'import os; import sys; print(sys.executable.split(os.path.sep)[-2]) if os.name == "nt" else print(sys.executable.split(os.path.sep)[-3])'
language: conda
files: \.py$
- id: additional-deps
name: additional-deps
entry: python
language: conda
files: \.py$

View file

@ -0,0 +1,6 @@
channels:
- conda-forge
- defaults
dependencies:
- python
- pip

View file

@ -0,0 +1,17 @@
- id: docker-hook
name: Docker test hook
entry: echo
language: docker
files: \.txt$
- id: docker-hook-arg
name: Docker test hook
entry: echo -n
language: docker
files: \.txt$
- id: docker-hook-failing
name: Docker test hook with nonzero exit code
entry: bork
language: docker
files: \.txt$

View file

@ -0,0 +1,3 @@
FROM cogniteev/echo
CMD ["echo", "This is overwritten by the .pre-commit-hooks.yaml 'entry'"]

View file

@ -0,0 +1,8 @@
- id: echo-entrypoint
name: echo (via --entrypoint)
language: docker_image
entry: --entrypoint echo cogniteev/echo
- id: echo-cmd
name: echo (via cmd)
language: docker_image
entry: cogniteev/echo echo

View file

@ -0,0 +1,6 @@
- id: python-files
name: Python files
entry: bin/hook.sh
language: script
types: [python]
exclude_types: [python3]

View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo $@
exit 1

View file

@ -0,0 +1,5 @@
- id: failing_hook
name: Failing hook
entry: bin/hook.sh
language: script
files: .

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
echo 'Fail'
echo $@
exit 1

View file

@ -0,0 +1,5 @@
- id: golang-hook
name: golang example hook
entry: golang-hello-world
language: golang
files: ''

View file

@ -0,0 +1,17 @@
package main
import (
"fmt"
"github.com/BurntSushi/toml"
)
type Config struct {
What string
}
func main() {
var conf Config
toml.Decode("What = 'world'\n", &conf)
fmt.Printf("hello %v\n", conf.What)
}

BIN
testing/resources/img1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

BIN
testing/resources/img2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

BIN
testing/resources/img3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

View file

@ -0,0 +1,6 @@
- id: logfile test hook
name: Logfile test hook
entry: bin/hook.sh
language: script
files: .
log_file: test.log

View file

@ -0,0 +1,5 @@
#!/usr/bin/env bash
echo "This is STDOUT output"
echo "This is STDERR output" 1>&2
exit 1

View file

@ -0,0 +1,15 @@
- id: bash_hook
name: Bash hook
entry: bin/hook.sh
language: script
files: 'foo.py'
- id: bash_hook2
name: Bash hook
entry: bin/hook2.sh
language: script
files: ''
- id: bash_hook3
name: Bash hook
entry: bin/hook3.sh
language: script
files: 'bar.py'

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
for f in $@; do
# Non UTF-8 bytes
echo -e '\x01\x97' > "$f"
echo "Modified: $f!"
done

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
echo $@

View file

@ -0,0 +1,6 @@
#!/usr/bin/env bash
for f in $@; do
# Non UTF-8 bytes
echo -e '\x01\x97' > "$f"
done

View file

@ -0,0 +1,5 @@
- id: foo
name: Foo
entry: foo
language: node
files: \.js$

View file

@ -0,0 +1,3 @@
#!/usr/bin/env node
console.log('Hello World');

View file

@ -0,0 +1,5 @@
{
"name": "foo",
"version": "0.0.1",
"bin": {"foo": "./bin/main.js"}
}

View file

@ -0,0 +1,6 @@
- id: versioned-node-hook
name: Versioned node hook
entry: versioned-node-hook
language: node
language_version: 9.3.0
files: \.js$

View file

@ -0,0 +1,4 @@
#!/usr/bin/env node
console.log(process.version);
console.log('Hello World');

View file

@ -0,0 +1,5 @@
{
"name": "versioned-node-hook",
"version": "0.0.1",
"bin": {"versioned-node-hook": "./bin/main.js"}
}

View file

@ -0,0 +1,5 @@
- id: not-found-exe
name: Not found exe
entry: i-dont-exist-lol
language: system
files: ''

View file

@ -0,0 +1,7 @@
/MYMETA.json
/MYMETA.yml
/Makefile
/PreCommitHello-*.tar.*
/PreCommitHello-*/
/blib/
/pm_to_blib

View file

@ -0,0 +1,5 @@
- id: perl-hook
name: perl example hook
entry: pre-commit-perl-hello
language: perl
files: ''

View file

@ -0,0 +1,4 @@
MANIFEST
Makefile.PL
bin/pre-commit-perl-hello
lib/PreCommitHello.pm

View file

@ -0,0 +1,10 @@
use strict;
use warnings;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => "PreCommitHello",
VERSION_FROM => "lib/PreCommitHello.pm",
EXE_FILES => [qw(bin/pre-commit-perl-hello)],
);

View file

@ -0,0 +1,7 @@
#!/usr/bin/env perl
use strict;
use warnings;
use PreCommitHello;
PreCommitHello::hello();

View file

@ -0,0 +1,12 @@
package PreCommitHello;
use strict;
use warnings;
our $VERSION = "0.1.0";
sub hello {
print "Hello from perl-commit Perl!\n";
}
1;

View file

@ -0,0 +1,5 @@
- id: prints_cwd
name: Prints Cwd
entry: pwd
language: system
files: \.sh$

View file

@ -0,0 +1,6 @@
- id: python3-hook
name: Python 3 Hook
entry: python3-hook
language: python
language_version: python3
files: \.py$

View file

@ -0,0 +1,8 @@
import sys
def main():
print(sys.version_info[0])
print(repr(sys.argv[1:]))
print('Hello World')
return 0

View file

@ -0,0 +1,8 @@
from setuptools import setup
setup(
name='python3_hook',
version='0.0.0',
py_modules=['py3_hook'],
entry_points={'console_scripts': ['python3-hook = py3_hook:main']},
)

View file

@ -0,0 +1,5 @@
- id: foo
name: Foo
entry: foo
language: python
files: \.py$

View file

@ -0,0 +1,7 @@
import sys
def main():
print(repr(sys.argv[1:]))
print('Hello World')
return 0

View file

@ -0,0 +1,8 @@
from setuptools import setup
setup(
name='foo',
version='0.0.0',
py_modules=['foo'],
entry_points={'console_scripts': ['foo = foo:main']},
)

View file

@ -0,0 +1,5 @@
- id: foo
name: Foo
entry: foo
language: python_venv
files: \.py$

View file

@ -0,0 +1,7 @@
import sys
def main():
print(repr(sys.argv[1:]))
print('Hello World')
return 0

View file

@ -0,0 +1,8 @@
from setuptools import setup
setup(
name='foo',
version='0.0.0',
py_modules=['foo'],
entry_points={'console_scripts': ['foo = foo:main']},
)

View file

@ -0,0 +1 @@
*.gem

View file

@ -0,0 +1,5 @@
- id: ruby_hook
name: Ruby Hook
entry: ruby_hook
language: ruby
files: \.rb$

View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
puts 'Hello world from a ruby hook'

View file

View file

@ -0,0 +1,9 @@
Gem::Specification.new do |s|
s.name = 'ruby_hook'
s.version = '0.1.0'
s.authors = ['Anthony Sottile']
s.summary = 'A ruby hook!'
s.description = 'A ruby hook!'
s.files = ['bin/ruby_hook']
s.executables = ['ruby_hook']
end

View file

@ -0,0 +1 @@
*.gem

View file

@ -0,0 +1,6 @@
- id: ruby_hook
name: Ruby Hook
entry: ruby_hook
language: ruby
language_version: 2.5.1
files: \.rb$

View file

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
puts RUBY_VERSION
puts 'Hello world from a ruby hook'

View file

@ -0,0 +1,9 @@
Gem::Specification.new do |s|
s.name = 'ruby_hook'
s.version = '0.1.0'
s.authors = ['Anthony Sottile']
s.summary = 'A ruby hook!'
s.description = 'A ruby hook!'
s.files = ['bin/ruby_hook']
s.executables = ['ruby_hook']
end

View file

@ -0,0 +1,5 @@
- id: rust-hook
name: rust example hook
entry: rust-hello-world
language: rust
files: ''

View file

@ -0,0 +1,3 @@
[[package]]
name = "rust-hello-world"
version = "0.1.0"

View file

@ -0,0 +1,3 @@
[package]
name = "rust-hello-world"
version = "0.1.0"

View file

@ -0,0 +1,3 @@
fn main() {
println!("hello world");
}

View file

@ -0,0 +1,5 @@
- id: bash_hook
name: Bash hook
entry: bin/hook.sh
language: script
files: ''

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
echo $@
echo 'Hello World'

View file

@ -0,0 +1,8 @@
- id: stdout-stderr
name: stdout-stderr
language: script
entry: ./stdout-stderr-entry
- id: tty-check
name: tty-check
language: script
entry: ./tty-check-entry

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
echo 0
echo 1 1>&2
echo 2
echo 3 1>&2
echo 4
echo 5 1>&2

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
t() {
if [ -t "$1" ]; then
echo "$2: True"
else
echo "$2: False"
fi
}
t 0 stdin
t 1 stdout
t 2 stderr

View file

@ -0,0 +1,4 @@
.DS_Store
/.build
/Packages
/*.xcodeproj

View file

@ -0,0 +1,6 @@
- id: swift-hooks-repo
name: Swift hooks repo example
description: Runs the hello world app generated by swift package init --type executable (binary called swift_hooks_repo here)
entry: swift_hooks_repo
language: swift
files: \.(swift)$

View file

@ -0,0 +1,7 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "swift_hooks_repo",
targets: [.target(name: "swift_hooks_repo")]
)

View file

@ -0,0 +1 @@
print("Hello, world!")

View file

@ -0,0 +1,5 @@
- id: system-hook-with-spaces
name: System hook with spaces
entry: bash -c 'echo "Hello World"'
language: system
files: \.sh$

View file

@ -0,0 +1,5 @@
- id: python-files
name: Python files
entry: bin/hook.sh
language: script
types: [python]

View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo $@
exit 1

113
testing/util.py Normal file
View file

@ -0,0 +1,113 @@
import contextlib
import os.path
import subprocess
import pytest
from pre_commit import parse_shebang
from pre_commit.languages.docker import docker_is_running
from pre_commit.util import cmd_output
from testing.auto_namedtuple import auto_namedtuple
TESTING_DIR = os.path.abspath(os.path.dirname(__file__))
def get_resource_path(path):
return os.path.join(TESTING_DIR, 'resources', path)
def cmd_output_mocked_pre_commit_home(
*args, tempdir_factory, pre_commit_home=None, env=None, **kwargs,
):
if pre_commit_home is None:
pre_commit_home = tempdir_factory.get()
env = env if env is not None else os.environ
kwargs.setdefault('stderr', subprocess.STDOUT)
# Don't want to write to the home directory
env = dict(env, PRE_COMMIT_HOME=pre_commit_home)
ret, out, _ = cmd_output(*args, env=env, **kwargs)
return ret, out.replace('\r\n', '\n'), None
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",
)
skipif_cant_run_swift = pytest.mark.skipif(
parse_shebang.find_executable('swift') is None,
reason="swift isn't installed or can't be found",
)
xfailif_windows_no_ruby = pytest.mark.xfail(
os.name == 'nt',
reason='Ruby support not yet implemented on windows.',
)
xfailif_windows = pytest.mark.xfail(os.name == 'nt', reason='windows')
def supports_venv(): # pragma: no cover (platform specific)
try:
__import__('ensurepip')
__import__('venv')
return True
except ImportError:
return False
xfailif_no_venv = pytest.mark.xfail(
not supports_venv(), reason='Does not support venv module',
)
def run_opts(
all_files=False,
files=(),
color=False,
verbose=False,
hook=None,
from_ref='',
to_ref='',
remote_name='',
remote_url='',
hook_stage='commit',
show_diff_on_failure=False,
commit_msg_filename='',
checkout_type='',
):
# These are mutually exclusive
assert not (all_files and files)
return auto_namedtuple(
all_files=all_files,
files=files,
color=color,
verbose=verbose,
hook=hook,
from_ref=from_ref,
to_ref=to_ref,
remote_name=remote_name,
remote_url=remote_url,
hook_stage=hook_stage,
show_diff_on_failure=show_diff_on_failure,
commit_msg_filename=commit_msg_filename,
checkout_type=checkout_type,
)
@contextlib.contextmanager
def cwd(path):
original_cwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(original_cwd)
def git_commit(*args, fn=cmd_output, msg='commit!', **kwargs):
kwargs.setdefault('stderr', subprocess.STDOUT)
cmd = ('git', 'commit', '--allow-empty', '--no-gpg-sign', '-a') + args
if msg is not None: # allow skipping `-m` with `msg=None`
cmd += ('-m', msg)
ret, out, _ = fn(*cmd, **kwargs)
return ret, out.replace('\r\n', '\n')