[clang] Add option to format a whole file using git-clang-format (PR #204336)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 24 01:22:32 PDT 2026
https://github.com/eoineoineoin updated https://github.com/llvm/llvm-project/pull/204336
>From 6e3b1a76f578b4e4dfe09b813d921fbe47b01b21 Mon Sep 17 00:00:00 2001
From: Eoin Mcloughlin <helloworld at eoinrul.es>
Date: Wed, 17 Jun 2026 11:48:32 +0100
Subject: [PATCH 1/2] Add --whole-file option to git-clang-format
---
clang/tools/clang-format/git-clang-format | 25 +++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format
index d79b57e7f6e10..f630cd4f8f28c 100755
--- a/clang/tools/clang-format/git-clang-format
+++ b/clang/tools/clang-format/git-clang-format
@@ -190,6 +190,11 @@ def main():
action="store_true",
help="format lines in the stage instead of the working dir",
)
+ p.add_argument(
+ "--whole-file",
+ action="store_true",
+ help="format whole file instead of only modified lines",
+ )
p.add_argument(
"--style",
default=config.get("clangformat.style", None),
@@ -256,7 +261,7 @@ def main():
opts.binary = os.path.abspath(opts.binary)
changed_lines = compute_diff_and_extract_lines(
- commits, files, opts.staged, opts.diff_from_common_commit
+ commits, files, opts.staged, opts.whole_file, opts.diff_from_common_commit
)
if opts.verbose >= 1:
ignored_files = set(changed_lines)
@@ -410,10 +415,10 @@ def get_object_type(value):
return convert_string(stdout.strip())
-def compute_diff_and_extract_lines(commits, files, staged, diff_common_commit):
+def compute_diff_and_extract_lines(commits, files, staged, whole_file, diff_common_commit):
"""Calls compute_diff() followed by extract_lines()."""
diff_process = compute_diff(commits, files, staged, diff_common_commit)
- changed_lines = extract_lines(diff_process.stdout)
+ changed_lines = extract_lines(diff_process.stdout, whole_file)
diff_process.stdout.close()
diff_process.wait()
if diff_process.returncode != 0:
@@ -446,7 +451,7 @@ def compute_diff(commits, files, staged, diff_common_commit):
return p
-def extract_lines(patch_file):
+def extract_lines(patch_file, whole_file):
"""Extract the changed lines in `patch_file`.
The return value is a dictionary mapping filename to a list of (start_line,
@@ -456,11 +461,23 @@ def extract_lines(patch_file):
zero lines of context. The return value is a dict mapping filename to a
list of line `Range`s."""
matches = {}
+
+ if whole_file:
+ # Find the repository root, in case this is run in a subdirectory
+ cmd = ['git', 'rev-parse', '--show-toplevel']
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ repo_root = convert_string(p.stdout.read()).strip()
+
for line in patch_file:
line = convert_string(line)
match = re.search(r"^\+\+\+\ [^/]+/(.*)", line)
if match:
filename = match.group(1).rstrip("\r\n\t")
+ if whole_file and filename not in matches:
+ full_path = os.path.join(repo_root, filename)
+ num_lines = sum(1 for _ in open(full_path))
+ matches.setdefault(filename, []).append(Range(1, num_lines))
+ continue
match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line)
if match:
start_line = int(match.group(1))
>From ae17aaac4a4ebc9b665947d2c254a3b074eb4752 Mon Sep 17 00:00:00 2001
From: Eoin Mcloughlin <helloworld at eoinrul.es>
Date: Wed, 24 Jun 2026 09:15:20 +0100
Subject: [PATCH 2/2] Avoid any filtering or file start/end calculation
---
clang/tools/clang-format/git-clang-format | 38 ++++++++++-------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format
index f630cd4f8f28c..cc2bf0607dc84 100755
--- a/clang/tools/clang-format/git-clang-format
+++ b/clang/tools/clang-format/git-clang-format
@@ -415,7 +415,9 @@ def get_object_type(value):
return convert_string(stdout.strip())
-def compute_diff_and_extract_lines(commits, files, staged, whole_file, diff_common_commit):
+def compute_diff_and_extract_lines(
+ commits, files, staged, whole_file, diff_common_commit
+):
"""Calls compute_diff() followed by extract_lines()."""
diff_process = compute_diff(commits, files, staged, diff_common_commit)
changed_lines = extract_lines(diff_process.stdout, whole_file)
@@ -461,34 +463,28 @@ def extract_lines(patch_file, whole_file):
zero lines of context. The return value is a dict mapping filename to a
list of line `Range`s."""
matches = {}
-
- if whole_file:
- # Find the repository root, in case this is run in a subdirectory
- cmd = ['git', 'rev-parse', '--show-toplevel']
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
- repo_root = convert_string(p.stdout.read()).strip()
-
for line in patch_file:
line = convert_string(line)
match = re.search(r"^\+\+\+\ [^/]+/(.*)", line)
if match:
filename = match.group(1).rstrip("\r\n\t")
if whole_file and filename not in matches:
- full_path = os.path.join(repo_root, filename)
- num_lines = sum(1 for _ in open(full_path))
- matches.setdefault(filename, []).append(Range(1, num_lines))
+ # Initialize the key for filename but ensure ranges is an empty
+ # list. This will prevent any filtering in clang_format_to_blob().
+ matches[filename] = []
continue
- match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line)
- if match:
- start_line = int(match.group(1))
- line_count = 1
- if match.group(3):
- line_count = int(match.group(3))
- if line_count == 0:
+ if not whole_file:
+ match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line)
+ if match:
+ start_line = int(match.group(1))
line_count = 1
- if start_line == 0:
- continue
- matches.setdefault(filename, []).append(Range(start_line, line_count))
+ if match.group(3):
+ line_count = int(match.group(3))
+ if line_count == 0:
+ line_count = 1
+ if start_line == 0:
+ continue
+ matches.setdefault(filename, []).append(Range(start_line, line_count))
return matches
More information about the cfe-commits
mailing list