Skip to content

Commit 44e5f08

Browse files
committed
instead of escaping, use subprocess without Shell set to true to avoid file nastiness (NO_JIRA)
1 parent 4a9c30f commit 44e5f08

File tree

1 file changed

+39
-46
lines changed

1 file changed

+39
-46
lines changed

main/githooks.py

+39-46
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,8 @@
5656
# File types that need a terminating newline
5757
TERMINATING_NEWLINE_EXTS = ['.c', '.cpp', '.h', '.inl']
5858

59-
_esc_re = re.compile(r'\s|[]()[]')
60-
def _esc_char(match):
61-
''' Lambda function to add in back-slashes to escape special chars as compiled in esc_re above
62-
which makes filenames work with subprocess commands
63-
'''
64-
return '\\' + match.group(0)
65-
66-
def _escape_filename(filename):
67-
''' Return an escaped filename - for example fi(1)le.txt would be changed to fi\\(1\\)le.txt
68-
'''
69-
return _esc_re.sub(_esc_char, filename)
70-
71-
72-
def _get_output(command, cwd='.'):
73-
return subprocess.check_output(command, shell=True, cwd=cwd).decode(errors='replace')
59+
def _get_output(command_list, cwd='.'):
60+
return subprocess.check_output(command_list, cwd=cwd).decode(errors='replace')
7461

7562

7663
def _is_github_event():
@@ -103,7 +90,7 @@ def get_user():
10390
if _is_github_event():
10491
return os.environ['GITHUB_ACTOR']
10592
else:
106-
output = _get_output('git var GIT_AUTHOR_IDENT')
93+
output = _get_output(['git', 'var', 'GIT_AUTHOR_IDENT'])
10794
match = re.match(r'^(.+) <', output)
10895
return match.group(1)
10996

@@ -116,7 +103,7 @@ def get_branch():
116103
else:
117104
return os.environ['GITHUB_REF'].split('/')[-1]
118105
else:
119-
return _get_output('git branch').split()[-1]
106+
return _get_output(['git', 'branch']).split()[-1]
120107

121108

122109
def get_file_content_as_binary(filename):
@@ -133,7 +120,7 @@ def get_file_content_as_binary(filename):
133120
_skip(filename, 'File is not UTF-8 encoded')
134121
data = None
135122
else:
136-
data = _get_output(f'git show :{_escape_filename(filename)}')
123+
data = _get_output(['git','show', f':{filename}'])
137124
return data
138125

139126

@@ -146,7 +133,7 @@ def get_text_file_content(filename):
146133
if _is_github_event() or 'pytest' in sys.modules:
147134
data = Path(filename).read_text()
148135
else:
149-
data = _get_output(f'git show :{_escape_filename(filename)}')
136+
data = _get_output('git', 'show', f':{filename}')
150137
return data
151138

152139

@@ -159,7 +146,7 @@ def get_sha():
159146
GITHUB_SHA cannot be used because in a pull request it gives the sha of the
160147
fake merge commit.
161148
'''
162-
return _get_output(f'git rev-parse {get_branch()}')
149+
return _get_output(['git','rev-parse', f'{get_branch()}'])
163150

164151

165152
def get_event():
@@ -173,12 +160,12 @@ def get_event():
173160
def get_branch_files():
174161
'''Get all files in branch'''
175162
branch = get_branch()
176-
return _get_output(f'git ls-tree -r {branch} --name-only').splitlines()
163+
return _get_output(['git','ls-tree', '-r', f'{branch}','--name-only']).splitlines()
177164

178165

179166
def add_file_to_index(filename):
180167
'''Add file to current commit'''
181-
return _get_output(f'git add {_escape_filename(filename)}')
168+
return _get_output(['git','add',f'{filename}'])
182169

183170

184171
def get_commit_files():
@@ -190,12 +177,15 @@ def get_commit_files():
190177
191178
'''
192179
if _is_github_event():
180+
commands = ['git','diff','--ignore-submodules','--name-status']
193181
if _is_pull_request():
194-
output = _get_output(f'git diff --ignore-submodules --name-status remotes/origin/{os.environ["GITHUB_BASE_REF"]}..remotes/origin/{os.environ["GITHUB_HEAD_REF"]} --')
182+
commands += [f'remotes/origin/{os.environ["GITHUB_BASE_REF"]}..remotes/origin/{os.environ["GITHUB_HEAD_REF"]}','--']
195183
else:
196-
output = _get_output('git diff --ignore-submodules --name-status HEAD~.. --')
184+
commands += ['HEAD~..', '--']
197185
else:
198-
output = _get_output('git diff-index --ignore-submodules HEAD --cached')
186+
commands = ['git', 'diff-index', '--ignore-submodules', 'HEAD', '--cached']
187+
188+
output = _get_output(commands)
199189
result = defaultdict(list)
200190
for line in output.splitlines():
201191
parts = line.split()
@@ -254,15 +244,14 @@ def get_changed_lines(modified_file):
254244
:returns: A list of line number (integers and ranges) of changed lines
255245
'''
256246
if _is_github_event():
247+
commands = ['git','diff','--unified=0']
257248
if _is_pull_request():
258-
output = _get_output(
259-
f'git diff --unified=0 remotes/origin/{os.environ["GITHUB_BASE_REF"]}..remotes/origin/{os.environ["GITHUB_HEAD_REF"]} -- {_escape_filename(modified_file)}')
249+
commands += [f'remotes/origin/{os.environ["GITHUB_BASE_REF"]}..remotes/origin/{os.environ["GITHUB_HEAD_REF"]}', '--',f'{modified_file}']
260250
else:
261-
output = _get_output(
262-
f'git diff --unified=0 HEAD~ {_escape_filename(modified_file)}')
251+
commands += ['HEAD~', f'{modified_file}']
263252
else:
264-
output = _get_output(
265-
f'git diff-index HEAD --unified=0 {_escape_filename(modified_file)}')
253+
commands = [f'git', 'diff-index', 'HEAD', '--unified=0', f'{modified_file}']
254+
output = _get_output(commands)
266255

267256
lines = []
268257
for line in output.splitlines():
@@ -295,7 +284,7 @@ def _test(input, output):
295284
def get_config_setting(setting):
296285
'''Get the value of a config setting'''
297286
try:
298-
return _get_output(f'git config --get {setting}').strip()
287+
return _get_output(['git', 'config', '--get', f'{setting}']).strip()
299288
except subprocess.CalledProcessError:
300289
return None
301290

@@ -472,20 +461,24 @@ class TestTrimTrailingWhitespace(unittest.TestCase):
472461
def test_trim_trailing_whitespace(self):
473462
content = 'first line\nsecond line \nthird line '
474463
trimmed_content = 'first line\nsecond line\nthird line'
475-
with NamedTemporaryFile() as tmp:
476-
Path(tmp.name).write_text(content)
477-
478-
# Trailing whitespace found
479-
retval = trim_trailing_whitespace_in_file(tmp.name, True, True)
480-
self.assertEqual(retval, 1)
481-
self.assertEqual(Path(tmp.name).read_text(), content)
482-
483-
# Now remove the trailing whitespace
484-
trim_trailing_whitespace_in_file(tmp.name, True, False, False)
485-
# Trailing whitespace no longer found
486-
self.assertEqual(Path(tmp.name).read_text(), trimmed_content)
487-
retval = trim_trailing_whitespace_in_file(tmp.name, True, True)
488-
self.assertEqual(retval, 0)
464+
name = NamedTemporaryFile().name
465+
Path(name).write_text(content)
466+
# Trailing whitespace found
467+
retval = trim_trailing_whitespace_in_file(name, True, True)
468+
self.assertEqual(retval, 1)
469+
self.assertEqual(Path(name).read_text(), content)
470+
471+
# Now remove the trailing whitespace
472+
trim_trailing_whitespace_in_file(name, True, False, False)
473+
# Trailing whitespace no longer found
474+
self.assertEqual(Path(name).read_text(), trimmed_content)
475+
retval = trim_trailing_whitespace_in_file(name, True, True)
476+
self.assertEqual(retval, 0)
477+
478+
try:
479+
Path(name).unlink(name)
480+
except Exception as e:
481+
pass
489482

490483
def test_decodeerror(self):
491484
# A text file that is not utf-8 encoded - report and skip

0 commit comments

Comments
 (0)