mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Merge pull request #473 from pre-commit/golang_hooks
Add first class support for golang hooks
This commit is contained in:
commit
9eeb701e26
11 changed files with 151 additions and 7 deletions
|
|
@ -32,6 +32,11 @@ def get_git_dir(git_root):
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def get_remote_url(git_root):
|
||||||
|
ret = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root)[1]
|
||||||
|
return ret.strip()
|
||||||
|
|
||||||
|
|
||||||
def is_in_merge_conflict():
|
def is_in_merge_conflict():
|
||||||
git_dir = get_git_dir('.')
|
git_dir = get_git_dir('.')
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from pre_commit.languages import docker
|
from pre_commit.languages import docker
|
||||||
|
from pre_commit.languages import golang
|
||||||
from pre_commit.languages import node
|
from pre_commit.languages import node
|
||||||
from pre_commit.languages import pcre
|
from pre_commit.languages import pcre
|
||||||
from pre_commit.languages import python
|
from pre_commit.languages import python
|
||||||
|
|
@ -43,6 +44,7 @@ from pre_commit.languages import system
|
||||||
|
|
||||||
languages = {
|
languages = {
|
||||||
'docker': docker,
|
'docker': docker,
|
||||||
|
'golang': golang,
|
||||||
'node': node,
|
'node': node,
|
||||||
'pcre': pcre,
|
'pcre': pcre,
|
||||||
'python': python,
|
'python': python,
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,8 @@ def install_environment(
|
||||||
assert repo_cmd_runner.exists('Dockerfile'), (
|
assert repo_cmd_runner.exists('Dockerfile'), (
|
||||||
'No Dockerfile was found in the hook repository'
|
'No Dockerfile was found in the hook repository'
|
||||||
)
|
)
|
||||||
assert version == 'default', (
|
helpers.assert_version_default('docker', version)
|
||||||
'Pre-commit does not support language_version for docker '
|
helpers.assert_no_additional_deps('docker', additional_dependencies)
|
||||||
)
|
|
||||||
assert_docker_available()
|
assert_docker_available()
|
||||||
|
|
||||||
directory = repo_cmd_runner.path(
|
directory = repo_cmd_runner.path(
|
||||||
|
|
|
||||||
72
pre_commit/languages/golang.py
Normal file
72
pre_commit/languages/golang.py
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from pre_commit import git
|
||||||
|
from pre_commit.envcontext import envcontext
|
||||||
|
from pre_commit.envcontext import Var
|
||||||
|
from pre_commit.languages import helpers
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
|
from pre_commit.util import cmd_output
|
||||||
|
from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
|
ENVIRONMENT_DIR = 'golangenv'
|
||||||
|
|
||||||
|
|
||||||
|
def get_env_patch(venv): # pragma: windows no cover
|
||||||
|
return (
|
||||||
|
('PATH', (os.path.join(venv, 'bin'), os.pathsep, Var('PATH'))),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def in_env(repo_cmd_runner): # pragma: windows no cover
|
||||||
|
envdir = repo_cmd_runner.path(
|
||||||
|
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
||||||
|
)
|
||||||
|
with envcontext(get_env_patch(envdir)):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
def guess_go_dir(remote_url):
|
||||||
|
if remote_url.endswith('.git'):
|
||||||
|
remote_url = remote_url[:-1 * len('.git')]
|
||||||
|
remote_url = remote_url.replace(':', '/')
|
||||||
|
looks_like_url = '//' in remote_url or '@' in remote_url
|
||||||
|
if looks_like_url:
|
||||||
|
_, _, remote_url = remote_url.rpartition('//')
|
||||||
|
_, _, remote_url = remote_url.rpartition('@')
|
||||||
|
return remote_url
|
||||||
|
else:
|
||||||
|
return 'unknown_src_dir'
|
||||||
|
|
||||||
|
|
||||||
|
def install_environment(
|
||||||
|
repo_cmd_runner,
|
||||||
|
version='default',
|
||||||
|
additional_dependencies=(),
|
||||||
|
): # pragma: windows no cover
|
||||||
|
helpers.assert_version_default('golang', version)
|
||||||
|
helpers.assert_no_additional_deps('golang', additional_dependencies)
|
||||||
|
directory = repo_cmd_runner.path(
|
||||||
|
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
||||||
|
)
|
||||||
|
|
||||||
|
with clean_path_on_failure(directory):
|
||||||
|
remote = git.get_remote_url(repo_cmd_runner.path())
|
||||||
|
repo_src_dir = os.path.join(directory, 'src', guess_go_dir(remote))
|
||||||
|
|
||||||
|
# Clone into the goenv we'll create
|
||||||
|
helpers.run_setup_cmd(
|
||||||
|
repo_cmd_runner, ('git', 'clone', '.', repo_src_dir),
|
||||||
|
)
|
||||||
|
|
||||||
|
env = dict(os.environ, GOPATH=directory)
|
||||||
|
cmd_output('go', 'get', './...', cwd=repo_src_dir, env=env)
|
||||||
|
|
||||||
|
|
||||||
|
def run_hook(repo_cmd_runner, hook, file_args): # pragma: windows no cover
|
||||||
|
with in_env(repo_cmd_runner):
|
||||||
|
return xargs(helpers.to_cmd(hook), file_args)
|
||||||
|
|
@ -18,3 +18,18 @@ def environment_dir(ENVIRONMENT_DIR, language_version):
|
||||||
|
|
||||||
def to_cmd(hook):
|
def to_cmd(hook):
|
||||||
return tuple(shlex.split(hook['entry'])) + tuple(hook['args'])
|
return tuple(shlex.split(hook['entry'])) + tuple(hook['args'])
|
||||||
|
|
||||||
|
|
||||||
|
def assert_version_default(binary, version):
|
||||||
|
if version != 'default':
|
||||||
|
raise AssertionError(
|
||||||
|
'For now, pre-commit requires system-installed {}'.format(binary),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_no_additional_deps(lang, additional_deps):
|
||||||
|
if additional_deps:
|
||||||
|
raise AssertionError(
|
||||||
|
'For now, pre-commit does not support '
|
||||||
|
'additional_dependencies for {}'.format(lang),
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,8 @@ def install_environment(
|
||||||
version='default',
|
version='default',
|
||||||
additional_dependencies=(),
|
additional_dependencies=(),
|
||||||
): # pragma: windows no cover
|
): # pragma: windows no cover
|
||||||
assert version == 'default', (
|
helpers.assert_version_default('swift', version)
|
||||||
'Pre-commit does not support language_version for docker '
|
helpers.assert_no_additional_deps('swift', additional_dependencies)
|
||||||
)
|
|
||||||
directory = repo_cmd_runner.path(
|
directory = repo_cmd_runner.path(
|
||||||
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
- id: golang-hook
|
||||||
|
name: golang example hook
|
||||||
|
entry: golang-hello-world
|
||||||
|
language: golang
|
||||||
|
files: ''
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
22
tests/languages/golang_test.py
Normal file
22
tests/languages/golang_test.py
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pre_commit.languages.golang import guess_go_dir
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
('url', 'expected'),
|
||||||
|
(
|
||||||
|
('/im/a/path/on/disk', 'unknown_src_dir'),
|
||||||
|
('git@github.com:golang/lint', 'github.com/golang/lint'),
|
||||||
|
('git://github.com/golang/lint', 'github.com/golang/lint'),
|
||||||
|
('http://github.com/golang/lint', 'github.com/golang/lint'),
|
||||||
|
('https://github.com/golang/lint', 'github.com/golang/lint'),
|
||||||
|
('ssh://git@github.com/golang/lint', 'github.com/golang/lint'),
|
||||||
|
('git@github.com:golang/lint.git', 'github.com/golang/lint'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_guess_go_dir(url, expected):
|
||||||
|
assert guess_go_dir(url) == expected
|
||||||
|
|
@ -257,6 +257,14 @@ def test_swift_hook(tempdir_factory, store):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.integration
|
||||||
|
def test_golang_hook(tempdir_factory, store):
|
||||||
|
_test_hook_repo(
|
||||||
|
tempdir_factory, store, 'golang_hooks_repo',
|
||||||
|
'golang-hook', [], b'hello world\n',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
def test_missing_executable(tempdir_factory, store):
|
def test_missing_executable(tempdir_factory, store):
|
||||||
_test_hook_repo(
|
_test_hook_repo(
|
||||||
|
|
|
||||||
2
tox.ini
2
tox.ini
|
|
@ -5,7 +5,7 @@ envlist = py27,py34,py35,pypy
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = -rrequirements-dev.txt
|
deps = -rrequirements-dev.txt
|
||||||
passenv = HOME HOMEPATH PROGRAMDATA TERM
|
passenv = GOROOT HOME HOMEPATH PROGRAMDATA TERM
|
||||||
setenv =
|
setenv =
|
||||||
VIRTUALENV_NO_DOWNLOAD = 1
|
VIRTUALENV_NO_DOWNLOAD = 1
|
||||||
GIT_AUTHOR_NAME = "test"
|
GIT_AUTHOR_NAME = "test"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue