mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-04-18 11:31:46 +04:00
commit
195c406b78
23 changed files with 297 additions and 98 deletions
34
.travis.yml
34
.travis.yml
|
|
@ -1,34 +0,0 @@
|
||||||
language: python
|
|
||||||
dist: xenial
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- env: TOXENV=py27
|
|
||||||
- env: TOXENV=py27 LATEST_GIT=1
|
|
||||||
- env: TOXENV=py36
|
|
||||||
python: 3.6
|
|
||||||
- env: TOXENV=pypy
|
|
||||||
python: pypy2.7-5.10.0
|
|
||||||
- env: TOXENV=py37
|
|
||||||
python: 3.7
|
|
||||||
install: pip install coveralls tox
|
|
||||||
script: tox
|
|
||||||
before_install:
|
|
||||||
- git --version
|
|
||||||
- |
|
|
||||||
if [ "$LATEST_GIT" = "1" ]; then
|
|
||||||
testing/latest-git.sh
|
|
||||||
export PATH="/tmp/git/bin:$PATH"
|
|
||||||
fi
|
|
||||||
- git --version
|
|
||||||
- 'testing/get-swift.sh && export PATH="/tmp/swift/usr/bin:$PATH"'
|
|
||||||
- 'curl -sSf https://sh.rustup.rs | bash -s -- -y'
|
|
||||||
- export PATH="$HOME/.cargo/bin:$PATH"
|
|
||||||
after_success: coveralls
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache/pip
|
|
||||||
- $HOME/.cache/pre-commit
|
|
||||||
- $HOME/.rustup
|
|
||||||
- $HOME/.swift
|
|
||||||
48
CHANGELOG.md
48
CHANGELOG.md
|
|
@ -1,3 +1,51 @@
|
||||||
|
1.15.2
|
||||||
|
======
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix cloning non-branch tag while in the fallback slow-clone strategy.
|
||||||
|
- #997 issue by @jpinner.
|
||||||
|
- #998 PR by @asottile.
|
||||||
|
|
||||||
|
1.15.1
|
||||||
|
======
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix command length calculation on posix when `SC_ARG_MAX` is not defined.
|
||||||
|
- #691 issue by @ushuz.
|
||||||
|
- #987 PR by @asottile.
|
||||||
|
|
||||||
|
1.15.0
|
||||||
|
======
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- No longer require being in a `git` repo to run `pre-commit` `clean` / `gc` /
|
||||||
|
`sample-config`.
|
||||||
|
- #959 PR by @asottile.
|
||||||
|
- Improve command line length limit detection.
|
||||||
|
- #691 issue by @antonbabenko.
|
||||||
|
- #966 PR by @asottile.
|
||||||
|
- Use shallow cloning when possible.
|
||||||
|
- #958 PR by @DanielChabrowski.
|
||||||
|
- Add `minimum_pre_commit_version` top level key to require a new-enough
|
||||||
|
version of `pre-commit`.
|
||||||
|
- #977 PR by @asottile.
|
||||||
|
- Add helpful CI-friendly message when running
|
||||||
|
`pre-commit run --all-files --show-diff-on-failure`.
|
||||||
|
- #982 PR by @bnorquist.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix `try-repo` for staged untracked changes.
|
||||||
|
- #973 PR by @DanielChabrowski.
|
||||||
|
- Fix rpm build by explicitly using `#!/usr/bin/env python3` in hook template.
|
||||||
|
- #985 issue by @tim77.
|
||||||
|
- #986 PR by @tim77.
|
||||||
|
- Guard against infinite recursion when executing legacy hook script.
|
||||||
|
- #981 PR by @tristan0x.
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
- Add test for `git.no_git_env()`
|
||||||
|
- #972 PR by @javabrett.
|
||||||
|
|
||||||
1.14.4
|
1.14.4
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
[](https://travis-ci.org/pre-commit/pre-commit)
|
[](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=21&branchName=master)
|
||||||
[](https://coveralls.io/github/pre-commit/pre-commit?branch=master)
|
[](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=21&branchName=master)
|
||||||
[](https://ci.appveyor.com/project/asottile/pre-commit/branch/master)
|
|
||||||
|
|
||||||
## pre-commit
|
## pre-commit
|
||||||
|
|
||||||
|
|
|
||||||
29
appveyor.yml
29
appveyor.yml
|
|
@ -1,29 +0,0 @@
|
||||||
environment:
|
|
||||||
global:
|
|
||||||
COVERAGE_IGNORE_WINDOWS: '# pragma: windows no cover'
|
|
||||||
TOX_TESTENV_PASSENV: COVERAGE_IGNORE_WINDOWS
|
|
||||||
matrix:
|
|
||||||
- TOXENV: py27
|
|
||||||
- TOXENV: py37
|
|
||||||
|
|
||||||
install:
|
|
||||||
- "SET PATH=C:\\Python37;C:\\Python37\\Scripts;%PATH%"
|
|
||||||
- pip install tox virtualenv --upgrade
|
|
||||||
- "mkdir -p C:\\Temp"
|
|
||||||
- "SET TMPDIR=C:\\Temp"
|
|
||||||
- "curl -sSf https://sh.rustup.rs | bash -s -- -y"
|
|
||||||
- "SET PATH=%USERPROFILE%\\.cargo\\bin;%PATH%"
|
|
||||||
|
|
||||||
# Not a C# project
|
|
||||||
build: false
|
|
||||||
|
|
||||||
before_test:
|
|
||||||
# Shut up CRLF messages
|
|
||||||
- git config --global core.autocrlf false
|
|
||||||
- git config --global core.safecrlf false
|
|
||||||
|
|
||||||
test_script: tox
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- '%LOCALAPPDATA%\pip\cache'
|
|
||||||
- '%USERPROFILE%\.cache\pre-commit'
|
|
||||||
50
azure-pipelines.yml
Normal file
50
azure-pipelines.yml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
trigger:
|
||||||
|
branches:
|
||||||
|
include: [master, test-me-*]
|
||||||
|
tags:
|
||||||
|
include: ['*']
|
||||||
|
|
||||||
|
resources:
|
||||||
|
repositories:
|
||||||
|
- repository: asottile
|
||||||
|
type: github
|
||||||
|
endpoint: github
|
||||||
|
name: asottile/azure-pipeline-templates
|
||||||
|
ref: refs/tags/v0.0.13
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- template: job--pre-commit.yml@asottile
|
||||||
|
- template: job--python-tox.yml@asottile
|
||||||
|
parameters:
|
||||||
|
toxenvs: [py27, py37]
|
||||||
|
os: windows
|
||||||
|
additional_variables:
|
||||||
|
COVERAGE_IGNORE_WINDOWS: '# pragma: windows no cover'
|
||||||
|
TOX_TESTENV_PASSENV: COVERAGE_IGNORE_WINDOWS
|
||||||
|
TEMP: C:\Temp # remove when dropping python2
|
||||||
|
pre_test:
|
||||||
|
- template: step--rust-install.yml
|
||||||
|
- template: job--python-tox.yml@asottile
|
||||||
|
parameters:
|
||||||
|
toxenvs: [py37]
|
||||||
|
os: linux
|
||||||
|
name_postfix: _latest_git
|
||||||
|
pre_test:
|
||||||
|
- task: UseRubyVersion@0
|
||||||
|
- template: step--git-install.yml
|
||||||
|
- template: step--rust-install.yml
|
||||||
|
- bash: |
|
||||||
|
testing/get-swift.sh
|
||||||
|
echo '##vso[task.prependpath]/tmp/swift/usr/bin'
|
||||||
|
displayName: install swift
|
||||||
|
- template: job--python-tox.yml@asottile
|
||||||
|
parameters:
|
||||||
|
toxenvs: [pypy, pypy3, py27, py36, py37]
|
||||||
|
os: linux
|
||||||
|
pre_test:
|
||||||
|
- task: UseRubyVersion@0
|
||||||
|
- template: step--rust-install.yml
|
||||||
|
- bash: |
|
||||||
|
testing/get-swift.sh
|
||||||
|
echo '##vso[task.prependpath]/tmp/swift/usr/bin'
|
||||||
|
displayName: install swift
|
||||||
|
|
@ -5,6 +5,7 @@ import io
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pre_commit import git
|
from pre_commit import git
|
||||||
|
|
@ -84,7 +85,7 @@ def install(
|
||||||
|
|
||||||
# If we have an existing hook, move it to pre-commit.legacy
|
# If we have an existing hook, move it to pre-commit.legacy
|
||||||
if os.path.lexists(hook_path) and not is_our_script(hook_path):
|
if os.path.lexists(hook_path) and not is_our_script(hook_path):
|
||||||
os.rename(hook_path, legacy_path)
|
shutil.move(hook_path, legacy_path)
|
||||||
|
|
||||||
# If we specify overwrite, we simply delete the legacy file
|
# If we specify overwrite, we simply delete the legacy file
|
||||||
if overwrite and os.path.exists(legacy_path):
|
if overwrite and os.path.exists(legacy_path):
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ def _compute_cols(hooks, verbose):
|
||||||
def _all_filenames(args):
|
def _all_filenames(args):
|
||||||
if args.origin and args.source:
|
if args.origin and args.source:
|
||||||
return git.get_changed_files(args.origin, args.source)
|
return git.get_changed_files(args.origin, args.source)
|
||||||
elif args.hook_stage == 'commit-msg':
|
elif args.hook_stage in {'prepare-commit-msg', 'commit-msg'}:
|
||||||
return (args.commit_msg_filename,)
|
return (args.commit_msg_filename,)
|
||||||
elif args.files:
|
elif args.files:
|
||||||
return args.files
|
return args.files
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,6 @@ LOCAL_REPO_VERSION = '1'
|
||||||
VERSION = importlib_metadata.version('pre_commit')
|
VERSION = importlib_metadata.version('pre_commit')
|
||||||
|
|
||||||
# `manual` is not invoked by any installed git hook. See #719
|
# `manual` is not invoked by any installed git hook. See #719
|
||||||
STAGES = ('commit', 'commit-msg', 'manual', 'push')
|
STAGES = ('commit', 'prepare-commit-msg', 'commit-msg', 'manual', 'push')
|
||||||
|
|
||||||
DEFAULT = 'default'
|
DEFAULT = 'default'
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ def _envdir(prefix, version):
|
||||||
return prefix.path(directory)
|
return prefix.path(directory)
|
||||||
|
|
||||||
|
|
||||||
def get_env_patch(venv):
|
def get_env_patch(venv): # pragma: windows no cover
|
||||||
if sys.platform == 'cygwin': # pragma: no cover
|
if sys.platform == 'cygwin': # pragma: no cover
|
||||||
_, win_venv, _ = cmd_output('cygpath', '-w', venv)
|
_, win_venv, _ = cmd_output('cygpath', '-w', venv)
|
||||||
install_prefix = r'{}\bin'.format(win_venv.strip())
|
install_prefix = r'{}\bin'.format(win_venv.strip())
|
||||||
|
|
@ -41,12 +41,14 @@ def get_env_patch(venv):
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def in_env(prefix, language_version):
|
def in_env(prefix, language_version): # pragma: windows no cover
|
||||||
with envcontext(get_env_patch(_envdir(prefix, language_version))):
|
with envcontext(get_env_patch(_envdir(prefix, language_version))):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
def install_environment(prefix, version, additional_dependencies):
|
def install_environment(
|
||||||
|
prefix, version, additional_dependencies,
|
||||||
|
): # pragma: windows no cover
|
||||||
additional_dependencies = tuple(additional_dependencies)
|
additional_dependencies = tuple(additional_dependencies)
|
||||||
assert prefix.exists('package.json')
|
assert prefix.exists('package.json')
|
||||||
envdir = _envdir(prefix, version)
|
envdir = _envdir(prefix, version)
|
||||||
|
|
@ -72,6 +74,6 @@ def install_environment(prefix, version, additional_dependencies):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_hook(hook, file_args):
|
def run_hook(hook, file_args): # pragma: windows no cover
|
||||||
with in_env(hook.prefix, hook.language_version):
|
with in_env(hook.prefix, hook.language_version):
|
||||||
return helpers.run_xargs(hook, helpers.to_cmd(hook), file_args)
|
return helpers.run_xargs(hook, helpers.to_cmd(hook), file_args)
|
||||||
|
|
|
||||||
|
|
@ -109,15 +109,15 @@ def norm_version(version):
|
||||||
if _sys_executable_matches(version):
|
if _sys_executable_matches(version):
|
||||||
return sys.executable
|
return sys.executable
|
||||||
|
|
||||||
|
version_exec = _find_by_py_launcher(version)
|
||||||
|
if version_exec:
|
||||||
|
return version_exec
|
||||||
|
|
||||||
# Try looking up by name
|
# Try looking up by name
|
||||||
version_exec = find_executable(version)
|
version_exec = find_executable(version)
|
||||||
if version_exec and version_exec != version:
|
if version_exec and version_exec != version:
|
||||||
return version_exec
|
return version_exec
|
||||||
|
|
||||||
version_exec = _find_by_py_launcher(version)
|
|
||||||
if version_exec:
|
|
||||||
return version_exec
|
|
||||||
|
|
||||||
# If it is in the form pythonx.x search in the default
|
# If it is in the form pythonx.x search in the default
|
||||||
# place on windows
|
# place on windows
|
||||||
if version.startswith('python'):
|
if version.startswith('python'):
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,9 @@ def _add_config_option(parser):
|
||||||
|
|
||||||
def _add_hook_type_option(parser):
|
def _add_hook_type_option(parser):
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-t', '--hook-type', choices=('pre-commit', 'pre-push', 'commit-msg'),
|
'-t', '--hook-type', choices=(
|
||||||
|
'pre-commit', 'pre-push', 'prepare-commit-msg', 'commit-msg',
|
||||||
|
),
|
||||||
default='pre-commit',
|
default='pre-commit',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ def _pre_push(stdin):
|
||||||
|
|
||||||
def _opts(stdin):
|
def _opts(stdin):
|
||||||
fns = {
|
fns = {
|
||||||
|
'prepare-commit-msg': lambda _: ('--commit-msg-filename', sys.argv[1]),
|
||||||
'commit-msg': lambda _: ('--commit-msg-filename', sys.argv[1]),
|
'commit-msg': lambda _: ('--commit-msg-filename', sys.argv[1]),
|
||||||
'pre-commit': lambda _: (),
|
'pre-commit': lambda _: (),
|
||||||
'pre-push': _pre_push,
|
'pre-push': _pre_push,
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ class Store(object):
|
||||||
def _complete_clone(self, ref, git_cmd):
|
def _complete_clone(self, ref, git_cmd):
|
||||||
"""Perform a complete clone of a repository and its submodules """
|
"""Perform a complete clone of a repository and its submodules """
|
||||||
|
|
||||||
git_cmd('fetch', 'origin')
|
git_cmd('fetch', 'origin', '--tags')
|
||||||
git_cmd('checkout', ref)
|
git_cmd('checkout', ref)
|
||||||
git_cmd('submodule', 'update', '--init', '--recursive')
|
git_cmd('submodule', 'update', '--init', '--recursive')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ def _environ_size(_env=None):
|
||||||
def _get_platform_max_length(): # pragma: no cover (platform specific)
|
def _get_platform_max_length(): # pragma: no cover (platform specific)
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
maximum = os.sysconf(str('SC_ARG_MAX')) - 2048 - _environ_size()
|
maximum = os.sysconf(str('SC_ARG_MAX')) - 2048 - _environ_size()
|
||||||
maximum = min(maximum, 2 ** 17)
|
maximum = max(min(maximum, 2 ** 17), 2 ** 12)
|
||||||
return maximum
|
return maximum
|
||||||
elif os.name == 'nt':
|
elif os.name == 'nt':
|
||||||
return 2 ** 15 - 2048 # UNICODE_STRING max - headroom
|
return 2 ** 15 - 2048 # UNICODE_STRING max - headroom
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
name = pre_commit
|
name = pre_commit
|
||||||
version = 1.14.4
|
version = 1.15.2
|
||||||
description = A framework for managing and maintaining multi-language pre-commit hooks.
|
description = A framework for managing and maintaining multi-language pre-commit hooks.
|
||||||
long_description = file: README.md
|
long_description = file: README.md
|
||||||
long_description_content_type = text/markdown
|
long_description_content_type = text/markdown
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ def cmd_output_mocked_pre_commit_home(*args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
skipif_cant_run_docker = pytest.mark.skipif(
|
skipif_cant_run_docker = pytest.mark.skipif(
|
||||||
docker_is_running() is False,
|
os.name == 'nt' or not docker_is_running(),
|
||||||
reason='Docker isn\'t running or can\'t be accessed',
|
reason="Docker isn't running or can't be accessed",
|
||||||
)
|
)
|
||||||
|
|
||||||
skipif_cant_run_swift = pytest.mark.skipif(
|
skipif_cant_run_swift = pytest.mark.skipif(
|
||||||
|
|
@ -67,8 +67,8 @@ xfailif_broken_deep_listdir = pytest.mark.xfail(
|
||||||
|
|
||||||
|
|
||||||
def platform_supports_pcre():
|
def platform_supports_pcre():
|
||||||
output = cmd_output(GREP, '-P', "name='pre", 'setup.py', retcode=None)
|
output = cmd_output(GREP, '-P', "Don't", 'CHANGELOG.md', retcode=None)
|
||||||
return output[0] == 0 and "name='pre_commit'," in output[1]
|
return output[0] == 0 and "Don't use readlink -f" in output[1]
|
||||||
|
|
||||||
|
|
||||||
xfailif_no_pcre_support = pytest.mark.xfail(
|
xfailif_no_pcre_support = pytest.mark.xfail(
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,16 @@ def test_install_existing_hooks_no_overwrite(tempdir_factory, store):
|
||||||
assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
|
assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
|
||||||
|
|
||||||
|
|
||||||
|
def test_legacy_overwriting_legacy_hook(tempdir_factory, store):
|
||||||
|
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
||||||
|
with cwd(path):
|
||||||
|
_write_legacy_hook(path)
|
||||||
|
assert install(C.CONFIG_FILE, store) == 0
|
||||||
|
_write_legacy_hook(path)
|
||||||
|
# this previously crashed on windows. See #1010
|
||||||
|
assert install(C.CONFIG_FILE, store) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_install_existing_hook_no_overwrite_idempotent(tempdir_factory, store):
|
def test_install_existing_hook_no_overwrite_idempotent(tempdir_factory, store):
|
||||||
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
||||||
with cwd(path):
|
with cwd(path):
|
||||||
|
|
@ -655,7 +665,65 @@ def test_commit_msg_legacy(commit_msg_repo, tempdir_factory, store):
|
||||||
assert second_line.startswith('Must have "Signed off by:"...')
|
assert second_line.startswith('Must have "Signed off by:"...')
|
||||||
|
|
||||||
|
|
||||||
def test_install_disallow_mising_config(tempdir_factory, store):
|
def test_prepare_commit_msg_integration_failing(
|
||||||
|
failing_prepare_commit_msg_repo, tempdir_factory, store,
|
||||||
|
):
|
||||||
|
install(C.CONFIG_FILE, store, hook_type='prepare-commit-msg')
|
||||||
|
retc, out = _get_commit_output(tempdir_factory)
|
||||||
|
assert retc == 1
|
||||||
|
assert out.startswith('Add "Signed off by:"...')
|
||||||
|
assert out.strip().endswith('...Failed')
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_commit_msg_integration_passing(
|
||||||
|
prepare_commit_msg_repo, tempdir_factory, store,
|
||||||
|
):
|
||||||
|
install(C.CONFIG_FILE, store, hook_type='prepare-commit-msg')
|
||||||
|
msg = 'Hi'
|
||||||
|
retc, out = _get_commit_output(tempdir_factory, msg=msg)
|
||||||
|
assert retc == 0
|
||||||
|
first_line = out.splitlines()[0]
|
||||||
|
assert first_line.startswith('Add "Signed off by:"...')
|
||||||
|
assert first_line.endswith('...Passed')
|
||||||
|
commit_msg_path = os.path.join(
|
||||||
|
prepare_commit_msg_repo, '.git/COMMIT_EDITMSG',
|
||||||
|
)
|
||||||
|
with io.open(commit_msg_path) as f:
|
||||||
|
assert 'Signed off by: ' in f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_commit_msg_legacy(
|
||||||
|
prepare_commit_msg_repo, tempdir_factory, store,
|
||||||
|
):
|
||||||
|
hook_path = os.path.join(
|
||||||
|
prepare_commit_msg_repo, '.git/hooks/prepare-commit-msg',
|
||||||
|
)
|
||||||
|
mkdirp(os.path.dirname(hook_path))
|
||||||
|
with io.open(hook_path, 'w') as hook_file:
|
||||||
|
hook_file.write(
|
||||||
|
'#!/usr/bin/env bash\n'
|
||||||
|
'set -eu\n'
|
||||||
|
'test -e "$1"\n'
|
||||||
|
'echo legacy\n',
|
||||||
|
)
|
||||||
|
make_executable(hook_path)
|
||||||
|
|
||||||
|
install(C.CONFIG_FILE, store, hook_type='prepare-commit-msg')
|
||||||
|
|
||||||
|
msg = 'Hi'
|
||||||
|
retc, out = _get_commit_output(tempdir_factory, msg=msg)
|
||||||
|
assert retc == 0
|
||||||
|
first_line, second_line = out.splitlines()[:2]
|
||||||
|
assert first_line == 'legacy'
|
||||||
|
assert second_line.startswith('Add "Signed off by:"...')
|
||||||
|
commit_msg_path = os.path.join(
|
||||||
|
prepare_commit_msg_repo, '.git/COMMIT_EDITMSG',
|
||||||
|
)
|
||||||
|
with io.open(commit_msg_path) as f:
|
||||||
|
assert 'Signed off by: ' in f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def test_install_disallow_missing_config(tempdir_factory, store):
|
||||||
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
||||||
with cwd(path):
|
with cwd(path):
|
||||||
remove_config_from_repo(path)
|
remove_config_from_repo(path)
|
||||||
|
|
@ -668,7 +736,7 @@ def test_install_disallow_mising_config(tempdir_factory, store):
|
||||||
assert ret == 1
|
assert ret == 1
|
||||||
|
|
||||||
|
|
||||||
def test_install_allow_mising_config(tempdir_factory, store):
|
def test_install_allow_missing_config(tempdir_factory, store):
|
||||||
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
|
||||||
with cwd(path):
|
with cwd(path):
|
||||||
remove_config_from_repo(path)
|
remove_config_from_repo(path)
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,12 @@ def test_stages(cap_out, store, repo_with_passing_hook):
|
||||||
'language': 'pygrep',
|
'language': 'pygrep',
|
||||||
'stages': [stage],
|
'stages': [stage],
|
||||||
}
|
}
|
||||||
for i, stage in enumerate(('commit', 'push', 'manual'), 1)
|
for i, stage in enumerate(
|
||||||
|
(
|
||||||
|
'commit', 'push', 'manual', 'prepare-commit-msg',
|
||||||
|
'commit-msg',
|
||||||
|
), 1,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
add_config_to_repo(repo_with_passing_hook, config)
|
add_config_to_repo(repo_with_passing_hook, config)
|
||||||
|
|
@ -575,6 +580,8 @@ def test_stages(cap_out, store, repo_with_passing_hook):
|
||||||
assert _run_for_stage('commit').startswith(b'hook 1...')
|
assert _run_for_stage('commit').startswith(b'hook 1...')
|
||||||
assert _run_for_stage('push').startswith(b'hook 2...')
|
assert _run_for_stage('push').startswith(b'hook 2...')
|
||||||
assert _run_for_stage('manual').startswith(b'hook 3...')
|
assert _run_for_stage('manual').startswith(b'hook 3...')
|
||||||
|
assert _run_for_stage('prepare-commit-msg').startswith(b'hook 4...')
|
||||||
|
assert _run_for_stage('commit-msg').startswith(b'hook 5...')
|
||||||
|
|
||||||
|
|
||||||
def test_commit_msg_hook(cap_out, store, commit_msg_repo):
|
def test_commit_msg_hook(cap_out, store, commit_msg_repo):
|
||||||
|
|
@ -593,6 +600,25 @@ def test_commit_msg_hook(cap_out, store, commit_msg_repo):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_commit_msg_hook(cap_out, store, prepare_commit_msg_repo):
|
||||||
|
filename = '.git/COMMIT_EDITMSG'
|
||||||
|
with io.open(filename, 'w') as f:
|
||||||
|
f.write('This is the commit message')
|
||||||
|
|
||||||
|
_test_run(
|
||||||
|
cap_out,
|
||||||
|
store,
|
||||||
|
prepare_commit_msg_repo,
|
||||||
|
{'hook_stage': 'prepare-commit-msg', 'commit_msg_filename': filename},
|
||||||
|
expected_outputs=[b'Add "Signed off by:"', b'Passed'],
|
||||||
|
expected_ret=0,
|
||||||
|
stage=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
with io.open(filename) as f:
|
||||||
|
assert 'Signed off by: ' in f.read()
|
||||||
|
|
||||||
|
|
||||||
def test_local_hook_passes(cap_out, store, repo_with_passing_hook):
|
def test_local_hook_passes(cap_out, store, repo_with_passing_hook):
|
||||||
config = {
|
config = {
|
||||||
'repo': 'local',
|
'repo': 'local',
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from pre_commit import output
|
||||||
from pre_commit.logging_handler import logging_handler
|
from pre_commit.logging_handler import logging_handler
|
||||||
from pre_commit.store import Store
|
from pre_commit.store import Store
|
||||||
from pre_commit.util import cmd_output
|
from pre_commit.util import cmd_output
|
||||||
|
from pre_commit.util import make_executable
|
||||||
from testing.fixtures import git_dir
|
from testing.fixtures import git_dir
|
||||||
from testing.fixtures import make_consuming_repo
|
from testing.fixtures import make_consuming_repo
|
||||||
from testing.fixtures import write_config
|
from testing.fixtures import write_config
|
||||||
|
|
@ -134,6 +135,54 @@ def commit_msg_repo(tempdir_factory):
|
||||||
yield path
|
yield path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def prepare_commit_msg_repo(tempdir_factory):
|
||||||
|
path = git_dir(tempdir_factory)
|
||||||
|
script_name = 'add_sign_off.sh'
|
||||||
|
config = {
|
||||||
|
'repo': 'local',
|
||||||
|
'hooks': [{
|
||||||
|
'id': 'add-signoff',
|
||||||
|
'name': 'Add "Signed off by:"',
|
||||||
|
'entry': './{}'.format(script_name),
|
||||||
|
'language': 'script',
|
||||||
|
'stages': ['prepare-commit-msg'],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
write_config(path, config)
|
||||||
|
with cwd(path):
|
||||||
|
with io.open(script_name, 'w') as script_file:
|
||||||
|
script_file.write(
|
||||||
|
'#!/usr/bin/env bash\n'
|
||||||
|
'set -eu\n'
|
||||||
|
'echo "\nSigned off by: " >> "$1"\n',
|
||||||
|
)
|
||||||
|
make_executable(script_name)
|
||||||
|
cmd_output('git', 'add', '.')
|
||||||
|
git_commit(msg=prepare_commit_msg_repo.__name__)
|
||||||
|
yield path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def failing_prepare_commit_msg_repo(tempdir_factory):
|
||||||
|
path = git_dir(tempdir_factory)
|
||||||
|
config = {
|
||||||
|
'repo': 'local',
|
||||||
|
'hooks': [{
|
||||||
|
'id': 'add-signoff',
|
||||||
|
'name': 'Add "Signed off by:"',
|
||||||
|
'entry': 'bash -c "exit 1"',
|
||||||
|
'language': 'system',
|
||||||
|
'stages': ['prepare-commit-msg'],
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
write_config(path, config)
|
||||||
|
with cwd(path):
|
||||||
|
cmd_output('git', 'add', '.')
|
||||||
|
git_commit(msg=failing_prepare_commit_msg_repo.__name__)
|
||||||
|
yield path
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True, scope='session')
|
@pytest.fixture(autouse=True, scope='session')
|
||||||
def dont_write_to_home_directory():
|
def dont_write_to_home_directory():
|
||||||
"""pre_commit.store.Store will by default write to the home directory
|
"""pre_commit.store.Store will by default write to the home directory
|
||||||
|
|
|
||||||
|
|
@ -824,7 +824,9 @@ def test_manifest_hooks(tempdir_factory, store):
|
||||||
name='Bash hook',
|
name='Bash hook',
|
||||||
pass_filenames=True,
|
pass_filenames=True,
|
||||||
require_serial=False,
|
require_serial=False,
|
||||||
stages=('commit', 'commit-msg', 'manual', 'push'),
|
stages=(
|
||||||
|
'commit', 'prepare-commit-msg', 'commit-msg', 'manual', 'push',
|
||||||
|
),
|
||||||
types=['file'],
|
types=['file'],
|
||||||
verbose=False,
|
verbose=False,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ from pre_commit import git
|
||||||
from pre_commit.store import _get_default_directory
|
from pre_commit.store import _get_default_directory
|
||||||
from pre_commit.store import Store
|
from pre_commit.store import Store
|
||||||
from pre_commit.util import CalledProcessError
|
from pre_commit.util import CalledProcessError
|
||||||
|
from pre_commit.util import cmd_output
|
||||||
from testing.fixtures import git_dir
|
from testing.fixtures import git_dir
|
||||||
from testing.util import cwd
|
from testing.util import cwd
|
||||||
from testing.util import git_commit
|
from testing.util import git_commit
|
||||||
|
|
@ -147,6 +148,20 @@ def test_clone_shallow_failure_fallback_to_complete(
|
||||||
assert store.select_all_repos() == [(path, rev, ret)]
|
assert store.select_all_repos() == [(path, rev, ret)]
|
||||||
|
|
||||||
|
|
||||||
|
def test_clone_tag_not_on_mainline(store, tempdir_factory):
|
||||||
|
path = git_dir(tempdir_factory)
|
||||||
|
with cwd(path):
|
||||||
|
git_commit()
|
||||||
|
cmd_output('git', 'checkout', 'master', '-b', 'branch')
|
||||||
|
git_commit()
|
||||||
|
cmd_output('git', 'tag', 'v1')
|
||||||
|
cmd_output('git', 'checkout', 'master')
|
||||||
|
cmd_output('git', 'branch', '-D', 'branch')
|
||||||
|
|
||||||
|
# previously crashed on unreachable refs
|
||||||
|
store.clone(path, 'v1')
|
||||||
|
|
||||||
|
|
||||||
def test_create_when_directory_exists_but_not_db(store):
|
def test_create_when_directory_exists_but_not_db(store):
|
||||||
# In versions <= 0.3.5, there was no sqlite db causing a need for
|
# In versions <= 0.3.5, there was no sqlite db causing a need for
|
||||||
# backward compatibility
|
# backward compatibility
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ def test_argument_too_long():
|
||||||
def test_xargs_smoke():
|
def test_xargs_smoke():
|
||||||
ret, out, err = xargs.xargs(('echo',), ('hello', 'world'))
|
ret, out, err = xargs.xargs(('echo',), ('hello', 'world'))
|
||||||
assert ret == 0
|
assert ret == 0
|
||||||
assert out == b'hello world\n'
|
assert out.replace(b'\r\n', b'\n') == b'hello world\n'
|
||||||
assert err == b''
|
assert err == b''
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
15
tox.ini
15
tox.ini
|
|
@ -1,20 +1,19 @@
|
||||||
[tox]
|
[tox]
|
||||||
project = pre_commit
|
envlist = py27,py36,py37,pypy,pypy3,pre-commit
|
||||||
# These should match the travis env list
|
|
||||||
envlist = py27,py36,py37,pypy
|
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = -rrequirements-dev.txt
|
deps = -rrequirements-dev.txt
|
||||||
passenv = GOROOT HOME HOMEPATH PROGRAMDATA TERM
|
passenv = HOME LOCALAPPDATA
|
||||||
commands =
|
commands =
|
||||||
coverage erase
|
coverage erase
|
||||||
coverage run -m pytest {posargs:tests}
|
coverage run -m pytest {posargs:tests}
|
||||||
coverage report --fail-under 100
|
coverage report --fail-under 100
|
||||||
pre-commit run --all-files
|
pre-commit install
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:pre-commit]
|
||||||
envdir = venv-{[tox]project}
|
skip_install = true
|
||||||
commands =
|
deps = pre-commit
|
||||||
|
commands = pre-commit run --all-files --show-diff-on-failure
|
||||||
|
|
||||||
[pep8]
|
[pep8]
|
||||||
ignore = E265,E501,W504
|
ignore = E265,E501,W504
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue