Skip to content

Commit aeaae53

Browse files
[clang-format] Add "three dot" diff option to git-clang-format (#74230)
This patch adds in the ability to do a "three dot" git-clang-format between two commits. This looks at the diff between the second commit and the common merge base rather than comparing at the point of the specified commits. This is needed to improve the reliability of the LLVM code formatting CI action which currently breaks in some cases where files have been modified in the upstream tree and when the person created their branch, leaving phantom formatting diffs that weren't touched by the PR author. Part of a fix for #73873
1 parent 689db42 commit aeaae53

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

clang/tools/clang-format/git-clang-format

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ def main():
132132
help='passed to clang-format'),
133133
p.add_argument('-v', '--verbose', action='count', default=0,
134134
help='print extra information')
135+
p.add_argument('--diff_from_common_commit', action='store_true',
136+
help=('diff from the last common commit for commits in '
137+
'separate branches rather than the exact point of the '
138+
'commits'))
135139
# We gather all the remaining positional arguments into 'args' since we need
136140
# to use some heuristics to determine whether or not <commit> was present.
137141
# However, to print pretty messages, we make use of metavar and help.
@@ -145,19 +149,23 @@ def main():
145149
del opts.quiet
146150

147151
commits, files = interpret_args(opts.args, dash_dash, opts.commit)
148-
if len(commits) > 1:
152+
if len(commits) > 2:
153+
die('at most two commits allowed; %d given' % len(commits))
154+
if len(commits) == 2:
149155
if opts.staged:
150156
die('--staged is not allowed when two commits are given')
151157
if not opts.diff:
152158
die('--diff is required when two commits are given')
153-
else:
154-
if len(commits) > 2:
155-
die('at most two commits allowed; %d given' % len(commits))
159+
elif opts.diff_from_common_commit:
160+
die('--diff_from_common_commit is only allowed when two commits are given')
156161

157162
if os.path.dirname(opts.binary):
158163
opts.binary = os.path.abspath(opts.binary)
159164

160-
changed_lines = compute_diff_and_extract_lines(commits, files, opts.staged)
165+
changed_lines = compute_diff_and_extract_lines(commits,
166+
files,
167+
opts.staged,
168+
opts.diff_from_common_commit)
161169
if opts.verbose >= 1:
162170
ignored_files = set(changed_lines)
163171
filter_by_extension(changed_lines, opts.extensions.lower().split(','))
@@ -305,9 +313,9 @@ def get_object_type(value):
305313
return convert_string(stdout.strip())
306314

307315

308-
def compute_diff_and_extract_lines(commits, files, staged):
316+
def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit):
309317
"""Calls compute_diff() followed by extract_lines()."""
310-
diff_process = compute_diff(commits, files, staged)
318+
diff_process = compute_diff(commits, files, staged, diff_common_commit)
311319
changed_lines = extract_lines(diff_process.stdout)
312320
diff_process.stdout.close()
313321
diff_process.wait()
@@ -317,7 +325,7 @@ def compute_diff_and_extract_lines(commits, files, staged):
317325
return changed_lines
318326

319327

320-
def compute_diff(commits, files, staged):
328+
def compute_diff(commits, files, staged, diff_common_commit):
321329
"""Return a subprocess object producing the diff from `commits`.
322330
323331
The return value's `stdin` file object will produce a patch with the
@@ -327,10 +335,13 @@ def compute_diff(commits, files, staged):
327335
Zero context lines are used in the patch."""
328336
git_tool = 'diff-index'
329337
extra_args = []
330-
if len(commits) > 1:
338+
if len(commits) == 2:
331339
git_tool = 'diff-tree'
340+
if diff_common_commit:
341+
commits = [f'{commits[0]}...{commits[1]}']
332342
elif staged:
333343
extra_args += ['--cached']
344+
334345
cmd = ['git', git_tool, '-p', '-U0'] + extra_args + commits + ['--']
335346
cmd.extend(files)
336347
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

0 commit comments

Comments
 (0)