mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-14 04:50:20 -06:00
Merge pull request #473 from pre-commit/golang_hooks
Add first class support for golang hooks
This commit is contained in:
@@ -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():
|
||||
git_dir = get_git_dir('.')
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from pre_commit.languages import docker
|
||||
from pre_commit.languages import golang
|
||||
from pre_commit.languages import node
|
||||
from pre_commit.languages import pcre
|
||||
from pre_commit.languages import python
|
||||
@@ -43,6 +44,7 @@ from pre_commit.languages import system
|
||||
|
||||
languages = {
|
||||
'docker': docker,
|
||||
'golang': golang,
|
||||
'node': node,
|
||||
'pcre': pcre,
|
||||
'python': python,
|
||||
|
||||
@@ -60,9 +60,8 @@ def install_environment(
|
||||
assert repo_cmd_runner.exists('Dockerfile'), (
|
||||
'No Dockerfile was found in the hook repository'
|
||||
)
|
||||
assert version == 'default', (
|
||||
'Pre-commit does not support language_version for docker '
|
||||
)
|
||||
helpers.assert_version_default('docker', version)
|
||||
helpers.assert_no_additional_deps('docker', additional_dependencies)
|
||||
assert_docker_available()
|
||||
|
||||
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):
|
||||
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',
|
||||
additional_dependencies=(),
|
||||
): # pragma: windows no cover
|
||||
assert version == 'default', (
|
||||
'Pre-commit does not support language_version for docker '
|
||||
)
|
||||
helpers.assert_version_default('swift', version)
|
||||
helpers.assert_no_additional_deps('swift', additional_dependencies)
|
||||
directory = repo_cmd_runner.path(
|
||||
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
|
||||
def test_missing_executable(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
|
||||
Reference in New Issue
Block a user