Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a932315

Browse files
committed
Implement 'negate' to simplify pcre
1 parent b7d3954 commit a932315

5 files changed

Lines changed: 50 additions & 38 deletions

File tree

pre_commit/languages/pcre.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from sys import platform
44

5-
from pre_commit.util import shell_escape
65
from pre_commit.xargs import xargs
76

87

@@ -19,21 +18,12 @@ def install_environment(
1918

2019

2120
def run_hook(repo_cmd_runner, hook, file_args):
22-
grep_command = '{0} -H -n -P'.format(
21+
# For PCRE the entry is the regular expression to match
22+
cmd = (
2323
'ggrep' if platform == 'darwin' else 'grep',
24-
)
24+
'-H', '-n', '-P',
25+
) + tuple(hook['args']) + (hook['entry'],)
2526

26-
# For PCRE the entry is the regular expression to match
27-
return xargs(
28-
(
29-
'sh', '-c',
30-
# Grep usually returns 0 for matches, and nonzero for non-matches
31-
# so we flip it here.
32-
'! {0} {1} {2} $@'.format(
33-
grep_command, ' '.join(hook['args']),
34-
shell_escape(hook['entry']),
35-
),
36-
'--',
37-
),
38-
file_args,
39-
)
27+
# Grep usually returns 0 for matches, and nonzero for non-matches so we
28+
# negate it here.
29+
return xargs(cmd, file_args, negate=True)

pre_commit/util.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@ def noop_context():
6767
yield
6868

6969

70-
def shell_escape(arg):
71-
return "'" + arg.replace("'", "'\"'\"'".strip()) + "'"
72-
73-
7470
def no_git_env():
7571
# Too many bugs dealing with environment variables and GIT:
7672
# https://github.com/pre-commit/pre-commit/issues/300

pre_commit/xargs.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,31 @@ def partition(cmd, varargs, _max_length=MAX_LENGTH):
4242
return tuple(ret)
4343

4444

45-
def xargs(cmd, varargs):
46-
"""A simplified implementation of xargs."""
45+
def xargs(cmd, varargs, **kwargs):
46+
"""A simplified implementation of xargs.
47+
48+
negate: Make nonzero successful and zero a failure
49+
"""
50+
negate = kwargs.pop('negate', False)
4751
retcode = 0
4852
stdout = b''
4953
stderr = b''
5054

51-
for run_cmd in partition(cmd, varargs):
55+
for run_cmd in partition(cmd, varargs, **kwargs):
5256
proc_retcode, proc_out, proc_err = cmd_output(
5357
*run_cmd, encoding=None, retcode=None
5458
)
55-
retcode |= proc_retcode
59+
# This is *slightly* too clever so I'll explain it.
60+
# First the xor boolean table:
61+
# T | F |
62+
# +-------+
63+
# T | F | T |
64+
# --+-------+
65+
# F | T | F |
66+
# --+-------+
67+
# When negate is True, it has the effect of flipping the return code
68+
# Otherwise, the retuncode is unchanged
69+
retcode |= bool(proc_retcode) ^ negate
5670
stdout += proc_out
5771
stderr += proc_err
5872

tests/util_test.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from pre_commit.util import clean_path_on_failure
1010
from pre_commit.util import cwd
1111
from pre_commit.util import memoize_by_cwd
12-
from pre_commit.util import shell_escape
1312
from pre_commit.util import tmpdir
1413

1514

@@ -79,18 +78,6 @@ class MySystemExit(SystemExit):
7978
assert not os.path.exists('foo')
8079

8180

82-
@pytest.mark.parametrize(
83-
('input_str', 'expected'),
84-
(
85-
('', "''"),
86-
('foo"bar', "'foo\"bar'"),
87-
("foo'bar", "'foo'\"'\"'bar'")
88-
),
89-
)
90-
def test_shell_escape(input_str, expected):
91-
assert shell_escape(input_str) == expected
92-
93-
9481
def test_tmpdir():
9582
with tmpdir() as tempdir:
9683
assert os.path.exists(tempdir)

tests/xargs_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,28 @@ def test_xargs_smoke():
4545
assert ret == 0
4646
assert out == b'hello world\n'
4747
assert err == b''
48+
49+
50+
exit_cmd = ('bash', '-c', 'exit $1', '--')
51+
# Abuse max_length to control the exit code
52+
max_length = len(' '.join(exit_cmd)) + 2
53+
54+
55+
def test_xargs_negate():
56+
ret, _, _ = xargs.xargs(
57+
exit_cmd, ('1',), negate=True, _max_length=max_length,
58+
)
59+
assert ret == 0
60+
61+
ret, _, _ = xargs.xargs(
62+
exit_cmd, ('1', '0'), negate=True, _max_length=max_length,
63+
)
64+
assert ret == 1
65+
66+
67+
def test_xargs_retcode_normal():
68+
ret, _, _ = xargs.xargs(exit_cmd, ('0',), _max_length=max_length)
69+
assert ret == 0
70+
71+
ret, _, _ = xargs.xargs(exit_cmd, ('0', '1'), _max_length=max_length)
72+
assert ret == 1

0 commit comments

Comments
 (0)