Skip to content

Commit d194a3a

Browse files
committed
Use range when working out changed lines
1 parent 9a019ff commit d194a3a

1 file changed

Lines changed: 54 additions & 13 deletions

File tree

main/githooks.py

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,28 +148,49 @@ def get_commit_files():
148148

149149

150150
def parse_diff_header(header_line):
151-
changed_lines = []
151+
'''Parse "git diff --unified=0" header lines to get changed line numbers
152+
153+
The line number is in relation to the file after the change.
154+
155+
:param header_line: A header in the git diff --unified=0 output
156+
:returns: a string that represents either a line number or a range
157+
'''
152158
match = parse_diff_header.pattern.match(header_line)
153159
start = int(match.group(1))
154160
if match.group(2):
155-
for num in range(int(match.group(3))):
156-
changed_lines.append(start + num)
161+
num = int(match.group(3))
162+
changed_lines = f'{start}-{start+num-1}'
157163
else:
158-
changed_lines.append(start)
164+
changed_lines = str(start)
159165
return changed_lines
160166
parse_diff_header.pattern = re.compile(r'^@@\s[^\s]+\s\+?(\d+)(,(\d+))?\s@@.*')
161167

162168

163169
class TestParseDiffHeaderPattern(unittest.TestCase):
164170
def test_various_strings(self):
165171
def _test(input, output):
166-
self.assertListEqual(output, parse_diff_header(input))
167-
_test('@@ -142 +178,3 @@', [178, 179, 180])
168-
_test('@@ -142 +178,7 @@', [178, 179, 180, 181, 182, 183, 184])
172+
self.assertEqual(output, parse_diff_header(input))
173+
_test('@@ -142 +178 @@', '178')
174+
_test('@@ -142 +178,3 @@', '178-180')
175+
_test('@@ -142 +178,7 @@', '178-184')
169176

170177

171178
def get_changed_lines(modified_file):
172-
'''New and modified lines in modified file in current commit'''
179+
'''New and modified lines in modified file in current commit
180+
181+
Depending on the context, the change is defined as (old -> new):
182+
183+
pull request: BASE -> HEAD (ie. main -> feature_branch)
184+
push: HEAD~ -> HEAD (ie. previous commit -> current commit)
185+
precommit: HEAD -> index (ie. current commit -> new commit)
186+
187+
The returned list contains line numbers of lines that have changed. The
188+
list can contain ranges. For example ['3','6-9','12'] means lines
189+
3,6,7,8,9,12.
190+
191+
:param modified_file: The file which has changed
192+
:returns: A list of line number (integers and ranges) of changed lines
193+
'''
173194
if _is_github_event():
174195
if _is_pull_request():
175196
output = _get_output(
@@ -185,10 +206,30 @@ def get_changed_lines(modified_file):
185206
for line in output.splitlines():
186207
if not line.startswith('@@'):
187208
continue
188-
lines.extend(parse_diff_header(line))
209+
lines.append(parse_diff_header(line))
189210
return lines
190211

191212

213+
def yield_changed_lines(changed_lines):
214+
'''Yield individual line numbers from list returned by get_changed_lines'''
215+
for line_num_range in changed_lines:
216+
if '-' in line_num_range:
217+
start, end = map(int, line_num_range.split('-'))
218+
else:
219+
start, end = int(line_num_range), int(line_num_range)
220+
for line_num in range(start, end+1):
221+
yield line_num
222+
223+
224+
class TestYieldChangedLines(unittest.TestCase):
225+
def test_various_lists(self):
226+
def _test(input, output):
227+
self.assertListEqual(output, list(yield_changed_lines(input)))
228+
_test(['12'], [12])
229+
_test(['12-15'], [12,13,14,15])
230+
_test(['12-15','44','55-57'], [12,13,14,15,44,55,56,57])
231+
232+
192233
def get_config_setting(setting):
193234
'''Get the value of a config setting'''
194235
try:
@@ -241,11 +282,11 @@ def check_do_not_merge_in_file(filename, new_file=False):
241282
lines = fileobj.read().decode().splitlines(True)
242283

243284
if new_file:
244-
line_nums = range(1, len(lines)+1)
285+
line_nums = [f'1-{len(lines)}']
245286
else:
246287
line_nums = get_changed_lines(filename)
247288

248-
for line_num in line_nums:
289+
for line_num in yield_changed_lines(line_nums):
249290
try:
250291
line = lines[line_num-1]
251292
except IndexError as exc:
@@ -314,14 +355,14 @@ def trim_trailing_whitespace_in_file(filename, new_file, in_place):
314355
return
315356

316357
if new_file:
317-
line_nums = range(1, len(lines)+1)
358+
line_nums = [f'1-{len(lines)}']
318359
else:
319360
line_nums = get_changed_lines(filename)
320361

321362
modified_file = False # if trimming white space in place
322363
modified_lines = [] # if flagging instead of trimming in place
323364

324-
for line_num in line_nums:
365+
for line_num in yield_changed_lines(line_nums):
325366
try:
326367
before = lines[line_num-1]
327368
except IndexError as exc:

0 commit comments

Comments
 (0)