Skip to content

Commit 10c5e4e

Browse files
committed
forbid-new-submodules: fix triggering failure when only a submodule is committed (without any other file); support --from-ref and --to-ref; fixes #609
1 parent 8c1183c commit 10c5e4e

9 files changed

+65
-25
lines changed

.pre-commit-hooks.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
language: python
155155
entry: forbid-new-submodules
156156
description: Prevent addition of new git submodules
157+
types: [directory]
157158
- id: mixed-line-ending
158159
name: Mixed line ending
159160
description: Replaces or checks mixed line ending

pre_commit_hooks/forbid_new_submodules.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
1+
import argparse
2+
import os
13
from typing import Optional
24
from typing import Sequence
35

46
from pre_commit_hooks.util import cmd_output
57

68

79
def main(argv: Optional[Sequence[str]] = None) -> int:
8-
# `argv` is ignored, pre-commit will send us a list of files that we
9-
# don't care about
10+
parser = argparse.ArgumentParser()
11+
parser.add_argument('filenames', nargs='*')
12+
args = parser.parse_args(argv)
13+
14+
if (
15+
'PRE_COMMIT_FROM_REF' in os.environ and
16+
'PRE_COMMIT_TO_REF' in os.environ
17+
):
18+
diff_arg = '...'.join((
19+
os.environ['PRE_COMMIT_FROM_REF'],
20+
os.environ['PRE_COMMIT_TO_REF'],
21+
))
22+
else:
23+
diff_arg = '--staged'
1024
added_diff = cmd_output(
11-
'git', 'diff', '--staged', '--diff-filter=A', '--raw',
25+
'git', 'diff', '--diff-filter=A', '--raw', diff_arg, '--',
26+
*args.filenames,
1227
)
1328
retv = 0
1429
for line in added_diff.splitlines():

testing/util.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import os.path
2+
import subprocess
23

34

45
TESTING_DIR = os.path.abspath(os.path.dirname(__file__))
56

67

78
def get_resource_path(path):
89
return os.path.join(TESTING_DIR, 'resources', path)
10+
11+
12+
def git_commit(*args, **kwargs):
13+
cmd = ('git', 'commit', '--no-gpg-sign', '--no-verify', '--no-edit', *args)
14+
subprocess.check_call(cmd, **kwargs)

tests/check_added_large_files_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pre_commit_hooks.check_added_large_files import find_large_added_files
66
from pre_commit_hooks.check_added_large_files import main
77
from pre_commit_hooks.util import cmd_output
8+
from testing.util import git_commit
89

910

1011
def test_nothing_added(temp_git_dir):
@@ -104,7 +105,7 @@ def test_moves_with_gitlfs(temp_git_dir, monkeypatch): # pragma: no cover
104105
# First add the file we're going to move
105106
temp_git_dir.join('a.bin').write('a' * 10000)
106107
cmd_output('git', 'add', '--', '.')
107-
cmd_output('git', 'commit', '--no-gpg-sign', '-am', 'foo')
108+
git_commit('-am', 'foo')
108109
# Now move it and make sure the hook still succeeds
109110
cmd_output('git', 'mv', 'a.bin', 'b.bin')
110111
assert main(('--maxkb', '9', 'b.bin')) == 0

tests/check_case_conflict_test.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pre_commit_hooks.check_case_conflict import main
77
from pre_commit_hooks.check_case_conflict import parents
88
from pre_commit_hooks.util import cmd_output
9+
from testing.util import git_commit
910

1011
skip_win32 = pytest.mark.skipif(
1112
sys.platform == 'win32',
@@ -85,7 +86,7 @@ def test_file_conflicts_with_committed_file(temp_git_dir):
8586
with temp_git_dir.as_cwd():
8687
temp_git_dir.join('f.py').write("print('hello world')")
8788
cmd_output('git', 'add', 'f.py')
88-
cmd_output('git', 'commit', '--no-gpg-sign', '-n', '-m', 'Add f.py')
89+
git_commit('-m', 'Add f.py')
8990

9091
temp_git_dir.join('F.py').write("print('hello world')")
9192
cmd_output('git', 'add', 'F.py')
@@ -98,7 +99,7 @@ def test_file_conflicts_with_committed_dir(temp_git_dir):
9899
with temp_git_dir.as_cwd():
99100
temp_git_dir.mkdir('dir').join('x').write('foo')
100101
cmd_output('git', 'add', '-A')
101-
cmd_output('git', 'commit', '--no-gpg-sign', '-n', '-m', 'Add f.py')
102+
git_commit('-m', 'Add f.py')
102103

103104
temp_git_dir.join('DIR').write('foo')
104105
cmd_output('git', 'add', '-A')

tests/check_merge_conflict_test.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pre_commit_hooks.check_merge_conflict import main
77
from pre_commit_hooks.util import cmd_output
88
from testing.util import get_resource_path
9+
from testing.util import git_commit
910

1011

1112
@pytest.fixture
@@ -20,19 +21,19 @@ def f1_is_a_conflict_file(tmpdir):
2021
with repo1.as_cwd():
2122
repo1_f1.ensure()
2223
cmd_output('git', 'add', '.')
23-
cmd_output('git', 'commit', '--no-gpg-sign', '-m', 'commit1')
24+
git_commit('-m', 'commit1')
2425

2526
cmd_output('git', 'clone', str(repo1), str(repo2))
2627

2728
# Commit in master
2829
with repo1.as_cwd():
2930
repo1_f1.write('parent\n')
30-
cmd_output('git', 'commit', '--no-gpg-sign', '-am', 'master commit2')
31+
git_commit('-am', 'master commit2')
3132

3233
# Commit in clone and pull
3334
with repo2.as_cwd():
3435
repo2_f1.write('child\n')
35-
cmd_output('git', 'commit', '--no-gpg-sign', '-am', 'clone commit2')
36+
git_commit('-am', 'clone commit2')
3637
cmd_output('git', 'pull', '--no-rebase', retcode=None)
3738
# We should end up in a merge conflict!
3839
f1 = repo2_f1.read()
@@ -75,20 +76,20 @@ def repository_pending_merge(tmpdir):
7576
with repo1.as_cwd():
7677
repo1_f1.ensure()
7778
cmd_output('git', 'add', '.')
78-
cmd_output('git', 'commit', '--no-gpg-sign', '-m', 'commit1')
79+
git_commit('-m', 'commit1')
7980

8081
cmd_output('git', 'clone', str(repo1), str(repo2))
8182

8283
# Commit in master
8384
with repo1.as_cwd():
8485
repo1_f1.write('parent\n')
85-
cmd_output('git', 'commit', '--no-gpg-sign', '-am', 'master commit2')
86+
git_commit('-am', 'master commit2')
8687

8788
# Commit in clone and pull without committing
8889
with repo2.as_cwd():
8990
repo2_f2.write('child\n')
9091
cmd_output('git', 'add', '.')
91-
cmd_output('git', 'commit', '--no-gpg-sign', '-m', 'clone commit2')
92+
git_commit('-m', 'clone commit2')
9293
cmd_output('git', 'pull', '--no-commit', '--no-rebase')
9394
# We should end up in a pending merge
9495
assert repo2_f1.read() == 'parent\n'

tests/destroyed_symlinks_test.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from pre_commit_hooks.destroyed_symlinks import find_destroyed_symlinks
77
from pre_commit_hooks.destroyed_symlinks import main
8+
from testing.util import git_commit
89

910
TEST_SYMLINK = 'test_symlink'
1011
TEST_SYMLINK_TARGET = '/doesnt/really/matters'
@@ -23,9 +24,7 @@ def repo_with_destroyed_symlink(tmpdir):
2324
with open(TEST_FILE, 'w') as f:
2425
print('some random content', file=f)
2526
subprocess.check_call(('git', 'add', '.'))
26-
subprocess.check_call(
27-
('git', 'commit', '--no-gpg-sign', '-m', 'initial'),
28-
)
27+
git_commit('-m', 'initial')
2928
assert b'120000 ' in subprocess.check_output(
3029
('git', 'cat-file', '-p', 'HEAD^{tree}'),
3130
)
Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1+
import os
12
import subprocess
3+
from unittest import mock
24

35
import pytest
46

57
from pre_commit_hooks.forbid_new_submodules import main
8+
from testing.util import git_commit
69

710

811
@pytest.fixture
912
def git_dir_with_git_dir(tmpdir):
1013
with tmpdir.as_cwd():
1114
subprocess.check_call(('git', 'init', '.'))
12-
subprocess.check_call((
13-
'git', 'commit', '-m', 'init', '--allow-empty', '--no-gpg-sign',
14-
))
15+
git_commit('--allow-empty', '-m', 'init')
1516
subprocess.check_call(('git', 'init', 'foo'))
16-
subprocess.check_call(
17-
('git', 'commit', '-m', 'init', '--allow-empty', '--no-gpg-sign'),
18-
cwd=str(tmpdir.join('foo')),
19-
)
17+
git_commit('--allow-empty', '-m', 'init', cwd=str(tmpdir.join('foo')))
2018
yield
2119

2220

@@ -31,12 +29,29 @@ def git_dir_with_git_dir(tmpdir):
3129
)
3230
def test_main_new_submodule(git_dir_with_git_dir, capsys, cmd):
3331
subprocess.check_call(cmd)
34-
assert main() == 1
32+
assert main(('random_non-related_file',)) == 0
33+
assert main(('foo',)) == 1
34+
out, _ = capsys.readouterr()
35+
assert out.startswith('foo: new submodule introduced\n')
36+
37+
38+
def test_main_new_submodule_committed(git_dir_with_git_dir, capsys):
39+
rev_parse_cmd = ('git', 'rev-parse', 'HEAD')
40+
from_ref = subprocess.check_output(rev_parse_cmd).decode().strip()
41+
subprocess.check_call(('git', 'submodule', 'add', './foo'))
42+
git_commit('-m', 'new submodule')
43+
to_ref = subprocess.check_output(rev_parse_cmd).decode().strip()
44+
with mock.patch.dict(
45+
os.environ,
46+
{'PRE_COMMIT_FROM_REF': from_ref, 'PRE_COMMIT_TO_REF': to_ref},
47+
):
48+
assert main(('random_non-related_file',)) == 0
49+
assert main(('foo',)) == 1
3550
out, _ = capsys.readouterr()
3651
assert out.startswith('foo: new submodule introduced\n')
3752

3853

3954
def test_main_no_new_submodule(git_dir_with_git_dir):
4055
open('test.py', 'a+').close()
4156
subprocess.check_call(('git', 'add', 'test.py'))
42-
assert main() == 0
57+
assert main(('test.py',)) == 0

tests/no_commit_to_branch_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pre_commit_hooks.no_commit_to_branch import is_on_branch
44
from pre_commit_hooks.no_commit_to_branch import main
55
from pre_commit_hooks.util import cmd_output
6+
from testing.util import git_commit
67

78

89
def test_other_branch(temp_git_dir):
@@ -62,7 +63,7 @@ def test_main_default_call(temp_git_dir):
6263

6364
def test_not_on_a_branch(temp_git_dir):
6465
with temp_git_dir.as_cwd():
65-
cmd_output('git', 'commit', '--no-gpg-sign', '--allow-empty', '-m1')
66+
git_commit('--allow-empty', '-m1')
6667
head = cmd_output('git', 'rev-parse', 'HEAD').strip()
6768
cmd_output('git', 'checkout', head)
6869
# we're not on a branch!

0 commit comments

Comments
 (0)