Repository: pre-commit/pre-commit

Issue:
recursive submodule support for `language: golang`
I added this hook in `pre-commit-hooks.yaml` in `https://github.com/google/go-jsonnet`, and then when I try to use this hook as:
```
repos:
  - repo: https://github.com/google/go-jsonnet
    rev: 4a3144a417b7eb9b1f7e56741a9e72f3155de3fa
    hooks:
      - id: jsonnet-format
```
then I see following error.

```
Traceback (most recent call last):
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/error_handler.py", line 65, in error_handler
    yield
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/main.py", line 378, in main
    return run(args.config, store, args)
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/commands/run.py", line 403, in run
    install_hook_envs(hooks, store)
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/repository.py", line 224, in install_hook_envs
    _hook_install(hook)
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/repository.py", line 82, in _hook_install
    lang.install_environment(
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/languages/golang.py", line 81, in install_environment
    cmd_output_b('go', 'get', './...', cwd=repo_src_dir, env=env)
  File "/usr/local/Cellar/pre-commit/2.10.0/libexec/lib/python3.9/site-packages/pre_commit/util.py", line 154, in cmd_output_b
    raise CalledProcessError(returncode, cmd, retcode, stdout_b, stderr_b)
pre_commit.util.CalledProcessError: command: ('/usr/local/bin/go', 'get', './...')
return code: 2
expected return code: 0
stdout: (none)
stderr:
    go: downloading github.com/sergi/go-diff v1.1.0
    go: downloading github.com/fatih/color v1.9.0
    go: downloading github.com/mattn/go-colorable v0.1.4
    go: downloading github.com/mattn/go-isatty v0.0.11
    go: downloading golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
    # github.com/google/go-jsonnet/c-bindings
    libjsonnet.cpp:5:14: fatal error: 'libjsonnet.h' file not found

```
Any idea? Thanks.

_Originally posted by @gaurav517 in https://github.com/pre-commit/pre-commit/issues/1785#issuecomment-774486062_


Discussion:

Resolving patch:
diff --git a/pre_commit/languages/golang.py b/pre_commit/languages/golang.py
--- a/pre_commit/languages/golang.py
+++ b/pre_commit/languages/golang.py
@@ -69,7 +69,8 @@ def install_environment(
         repo_src_dir = os.path.join(directory, 'src', guess_go_dir(remote))
 
         # Clone into the goenv we'll create
-        helpers.run_setup_cmd(prefix, ('git', 'clone', '.', repo_src_dir))
+        cmd = ('git', 'clone', '--recursive', '.', repo_src_dir)
+        helpers.run_setup_cmd(prefix, cmd)
 
         if sys.platform == 'cygwin':  # pragma: no cover
             _, gopath, _ = cmd_output('cygpath', '-w', directory)


Test patch:
diff --git a/tests/repository_test.py b/tests/repository_test.py
--- a/tests/repository_test.py
+++ b/tests/repository_test.py
@@ -10,6 +10,7 @@
 import re_assert
 
 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.envcontext import envcontext
@@ -346,6 +347,59 @@ def test_golang_hook_still_works_when_gobin_is_set(tempdir_factory, store):
     assert os.listdir(gobin_dir) == []
 
 
+def test_golang_with_recursive_submodule(tmpdir, tempdir_factory, store):
+    sub_go = '''\
+package sub
+
+import "fmt"
+
+func Func() {
+    fmt.Println("hello hello world")
+}
+'''
+    sub = tmpdir.join('sub').ensure_dir()
+    sub.join('sub.go').write(sub_go)
+    cmd_output('git', '-C', str(sub), 'init', '.')
+    cmd_output('git', '-C', str(sub), 'add', '.')
+    git.commit(str(sub))
+
+    pre_commit_hooks = '''\
+-   id: example
+    name: example
+    entry: example
+    language: golang
+    verbose: true
+'''
+    go_mod = '''\
+module github.com/asottile/example
+
+go 1.14
+'''
+    main_go = '''\
+package main
+
+import "github.com/asottile/example/sub"
+
+func main() {
+    sub.Func()
+}
+'''
+    repo = tmpdir.join('repo').ensure_dir()
+    repo.join('.pre-commit-hooks.yaml').write(pre_commit_hooks)
+    repo.join('go.mod').write(go_mod)
+    repo.join('main.go').write(main_go)
+    cmd_output('git', '-C', str(repo), 'init', '.')
+    cmd_output('git', '-C', str(repo), 'add', '.')
+    cmd_output('git', '-C', str(repo), 'submodule', 'add', str(sub), 'sub')
+    git.commit(str(repo))
+
+    config = make_config_from_repo(str(repo))
+    hook = _get_hook(config, store, 'example')
+    ret, out = _hook_run(hook, (), color=False)
+    assert ret == 0
+    assert _norm_out(out) == b'hello hello world\n'
+
+
 def test_rust_hook(tempdir_factory, store):
     _test_hook_repo(
         tempdir_factory, store, 'rust_hooks_repo',