From c3c055b114ecb6ddbc84e4f338b78c411b0a7bdf Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 24 Sep 2026 11:50:00 +0200 Subject: [PATCH 2/3] pgindent: Add --exclude-dir option This is meant to exclude build directories from being processed by pgindent, which is both wasteful and likely to crash pgindent. --- src/tools/pgindent/pgindent | 57 ++++++++++++++++++++++++++++++--- src/tools/pgindent/pgindent.man | 9 ++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent index d25f547e289..cbfa50fadb0 100755 --- a/src/tools/pgindent/pgindent +++ b/src/tools/pgindent/pgindent @@ -43,7 +43,8 @@ my $indent_opts = my $devnull = File::Spec->devnull; -my ($typedefs_file, $typedef_str, @excludes, $indent, $diff, +my ($typedefs_file, $typedef_str, @excludes, + @exclude_dirs, $indent, $diff, $check, $help, @commits,); $help = 0; @@ -54,6 +55,7 @@ my %options = ( "typedefs=s" => \$typedefs_file, "list-of-typedefs=s" => \$typedef_str, "excludes=s" => \@excludes, + "exclude-dir=s" => \@exclude_dirs, "indent=s" => \$indent, "diff" => \$diff, "check" => \$check,); @@ -64,6 +66,12 @@ usage() if $help; usage("Cannot use --commit with command line file list") if (@commits && @ARGV); +# --exclude-dir arguments are relative to the directory pgindent was +# invoked in, so resolve them to absolute paths now, before we +# possibly chdir() elsewhere. abs_path returns undef for a directory +# that doesn't exist, so drop those. +@exclude_dirs = grep { defined } map { abs_path($_) } @exclude_dirs; + # command line option wins, then environment, then locations based on current # dir, then default location $typedefs_file ||= $ENV{PGTYPEDEFS}; @@ -209,6 +217,32 @@ sub process_exclude return; } +# Is the given file or directory inside one of the --exclude-dir +# directories? The argument is interpreted relative to the current +# directory. +sub in_excluded_dir +{ + my $path = shift; + + return 0 unless @exclude_dirs; + + # abs_path() returns undef if a directory along the path is + # missing, which can happen for a file named by --commit that has + # since been removed. Fall back to a purely textual absolute + # path, so that such a file is still recognized as excluded rather + # than warned about later. + my $abs = abs_path($path); + $abs = File::Spec->canonpath(File::Spec->rel2abs($path)) + unless defined $abs; + + foreach my $dir (@exclude_dirs) + { + return 1 if $abs eq $dir || index($abs, "$dir/") == 0; + } + + return 0; +} + sub read_source { my $source_filename = shift; @@ -418,10 +452,12 @@ Options: --typedefs=FILE file containing a list of typedefs --list-of-typedefs=STR string containing typedefs, space separated --excludes=PATH file containing list of filename patterns to ignore + --exclude-dir=DIR skip all files below the directory DIR --indent=PATH path to pg_bsd_indent program --diff show the changes that would be made --check exit with status 2 if any changes would be made -The --excludes and --commit options can be given more than once. +The --excludes, --exclude-dir, and --commit options can be given more +than once. EOF if ($help) { @@ -443,8 +479,17 @@ check_indent(); my $wanted = sub { my ($dev, $ino, $mode, $nlink, $uid, $gid); - (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) - && -f _ + return unless (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)); + + # Don't even descend into an excluded directory. Note that File::Find + # has chdir'd into the containing directory, so $_ is what we must test. + if (-d _ && in_excluded_dir($_)) + { + $File::Find::prune = 1; + return; + } + + -f _ && /^.*\.[ch]\z/s && push(@files, $File::Find::name); }; @@ -465,6 +510,10 @@ foreach my $commit (@commits) push(@files, @affected); } +# remove files below excluded directories from the file list (could be +# from command line or from --commit) +@files = grep { !in_excluded_dir($_) } @files if @exclude_dirs; + warn "No files to process" unless @files; # remove excluded files from the file list diff --git a/src/tools/pgindent/pgindent.man b/src/tools/pgindent/pgindent.man index caab5cde914..cac2d30cd41 100644 --- a/src/tools/pgindent/pgindent.man +++ b/src/tools/pgindent/pgindent.man @@ -31,6 +31,15 @@ find the file src/tools/pgindent/exclude_file_patterns. The --excludes option can be used more than once to specify multiple files containing exclusion patterns. +Whole directories can be skipped with the --exclude-dir option, which is +useful for build directories containing generated .c and .h files, for +example: + + pgindent . --exclude-dir=build --exclude-dir=build2 + +Relative directory names are interpreted relative to the directory pgindent +is invoked in. This option can also be used more than once. + There are also two non-destructive modes of pgindent. If given the --diff option pgindent will show the changes it would make, but doesn't actually make them. If given instead the --check option, pgindent will exit with a status of -- 2.55.0