From 7bc24625457bfaf54320523db49b44c2da4ead1e Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Tue, 3 Mar 2026 09:43:33 +0100
Subject: [PATCH v4 1/7] pgindent: Use git ls-files to discover files

When running pgindent on the whole source tree, it would often also
indent build artifacts. This changes the pgindent directory search logic
to become git-aware, and only indent files that are actually tracked by
git.

Any files that are explicitly part of the pgindent its arguments, are
always indented though, even if they are not tracked by git. This can be
useful to force indentation of an untracked file and/or for editor
integration.
---
 src/tools/pgindent/pgindent | 54 ++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent
index b2ec5e2914b..f5bc4b3642a 100755
--- a/src/tools/pgindent/pgindent
+++ b/src/tools/pgindent/pgindent
@@ -13,7 +13,6 @@ use strict;
 use warnings FATAL => 'all';
 
 use Cwd qw(abs_path getcwd);
-use File::Find;
 use File::Spec;
 use File::Temp;
 use IO::Handle;
@@ -338,6 +337,49 @@ sub diff
 	return $diff;
 }
 
+sub discover_files
+{
+	my @paths = @_;
+	my @discovered;
+
+	# Separate individual files from directories
+	my @dirs;
+	foreach my $path (@paths)
+	{
+		if (-f $path)
+		{
+			push(@discovered, $path);
+		}
+		elsif (-d $path)
+		{
+			push(@dirs, $path);
+		}
+		else
+		{
+			warn "Could not find $path";
+		}
+	}
+
+	# Use git ls-files for directories to avoid searching build trees etc.
+	if (@dirs)
+	{
+		# Use -z to handle files with newlines in their names, and split on \0
+		# afterward.
+		open(my $git_ls, '-|', 'git', 'ls-files', '-z', '--', @dirs)
+		  || die "could not open git ls-files: $!";
+		binmode($git_ls);
+		# Slurp all output into a single string by temporarily unsetting
+		# the line separator.
+		my $git_output = do { local $/; <$git_ls> };
+		close($git_ls);
+		die "git ls-files error" if $?;
+		my @git_files = split(/\0/, $git_output);
+		push(@discovered, grep { /\.[ch]$/ } @git_files);
+	}
+
+	return @discovered;
+}
+
 sub usage
 {
 	my $message = shift;
@@ -373,16 +415,8 @@ $filtered_typedefs_fh = load_typedefs();
 
 check_indent();
 
-my $wanted = sub {
-	my ($dev, $ino, $mode, $nlink, $uid, $gid);
-	(($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))
-	  && -f _
-	  && /^.*\.[ch]\z/s
-	  && push(@files, $File::Find::name);
-};
-
 # any non-option arguments are files or directories to be processed
-File::Find::find({ wanted => $wanted }, @ARGV) if @ARGV;
+push(@files, discover_files(@ARGV)) if @ARGV;
 
 # commit file locations are relative to the source root
 chdir "$sourcedir/../../.." if @commits && $sourcedir;

base-commit: effaa464afd355e8927bf430cfe6a0ddd2ee5695
-- 
2.53.0

