From c65e6330ec14ea1a05b027b29269dcd5331e336c Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Wed, 4 Mar 2026 09:04:15 +0100
Subject: [PATCH v4 7/7] pgcheck: Add easy way of getting perltidy

pgcheck needs a very specific perltidy version, but getting that
installed is quite a hassle. Especially for people who don't use perl on
a daily basis. This commit adds a small script to download the exact
perltidy version that we need and install it locally in the repo. It
also teaches pgcheck to use that locally installed perltidy if it is
available.
---
 src/tools/pgcheck/pgcheck       | 25 +++++++++++--
 src/tools/pgindent/.gitignore   |  1 +
 src/tools/pgindent/README       | 16 ++++-----
 src/tools/pgindent/get_perltidy | 62 +++++++++++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 10 deletions(-)
 create mode 100644 src/tools/pgindent/.gitignore
 create mode 100755 src/tools/pgindent/get_perltidy

diff --git a/src/tools/pgcheck/pgcheck b/src/tools/pgcheck/pgcheck
index d0586e9ae6c..f9fef61195a 100755
--- a/src/tools/pgcheck/pgcheck
+++ b/src/tools/pgcheck/pgcheck
@@ -175,8 +175,29 @@ if (!$indent && $sourcedir)
 }
 $indent ||= "pg_bsd_indent";
 
-# get perltidy location: command line wins, then environment, then PATH.
-my $perltidy = $perltidy_arg || $ENV{PERLTIDY} || "perltidy";
+# get perltidy location: command line wins, then environment, then try to
+# find a get_perltidy-installed copy in the source tree, then fall back to
+# PATH.
+my $perltidy = $perltidy_arg || $ENV{PERLTIDY};
+if (!$perltidy && $sourcedir)
+{
+	# Look for a get_perltidy-installed perltidy in the source tree.
+	my $candidate = "$sourcedir/perltidy/bin/perltidy";
+	if (-x $candidate)
+	{
+		$perltidy = $candidate;
+
+		# Local installs need PERL5LIB set so perltidy can find its
+		# modules.
+		my $libdir = "$sourcedir/perltidy/lib/perl5";
+		if (-d $libdir)
+		{
+			$ENV{PERL5LIB} =
+			  $ENV{PERL5LIB} ? "$libdir:$ENV{PERL5LIB}" : $libdir;
+		}
+	}
+}
+$perltidy ||= "perltidy";
 
 # get perlcritic location: command line wins, then environment, then PATH.
 my $perlcritic = $perlcritic_arg || $ENV{PERLCRITIC} || "perlcritic";
diff --git a/src/tools/pgindent/.gitignore b/src/tools/pgindent/.gitignore
new file mode 100644
index 00000000000..1497217113b
--- /dev/null
+++ b/src/tools/pgindent/.gitignore
@@ -0,0 +1 @@
+/perltidy/
diff --git a/src/tools/pgindent/README b/src/tools/pgindent/README
index b6cd4c6f6b7..ebc18d83e9c 100644
--- a/src/tools/pgindent/README
+++ b/src/tools/pgindent/README
@@ -17,14 +17,14 @@ PREREQUISITES:
 
 2) Install perltidy.  Please be sure it is version 20230309 (older and newer
    versions make different formatting choices, and we want consistency).
-   You can get the correct version from
-   https://cpan.metacpan.org/authors/id/S/SH/SHANCOCK/
-   To install, follow the usual install process for a Perl module
-   ("man perlmodinstall" explains it).  Or, if you have cpan installed,
-   this should work:
-   cpan SHANCOCK/Perl-Tidy-20230309.tar.gz
-   Or if you have cpanm installed, you can just use:
-   cpanm https://cpan.metacpan.org/authors/id/S/SH/SHANCOCK/Perl-Tidy-20230309.tar.gz
+
+   The easiest way is to use the get_perltidy script, which downloads,
+   verifies, and installs the correct version into the source tree:
+
+	src/tools/pgindent/get_perltidy
+
+   This installs perltidy into src/tools/pgindent/perltidy/, which
+   pgindent will find automatically.
 
 
 DOING THE INDENT RUN BEFORE A NORMAL COMMIT:
diff --git a/src/tools/pgindent/get_perltidy b/src/tools/pgindent/get_perltidy
new file mode 100755
index 00000000000..09ce4a195cb
--- /dev/null
+++ b/src/tools/pgindent/get_perltidy
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+# src/tools/pgindent/get_perltidy
+#
+# Downloads and installs perltidy 20230309 into src/tools/pgindent/perltidy/.
+
+set -e
+
+PERLTIDY_VERSION=20230309
+PERLTIDY_TARBALL="Perl-Tidy-${PERLTIDY_VERSION}.tar.gz"
+PERLTIDY_URL="https://cpan.metacpan.org/authors/id/S/SH/SHANCOCK/${PERLTIDY_TARBALL}"
+PERLTIDY_SHA256="e22949a208c618d671a18c5829b451abbe9da0da2cddd78fdbfcb036c7361c18"
+
+# Determine the directory this script lives in, i.e. src/tools/pgindent
+SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
+
+PERLTIDY_DIR="$SCRIPT_DIR/perltidy"
+PERLTIDY_BIN="$PERLTIDY_DIR/bin/perltidy"
+
+# Check if already installed with the correct version
+if [ -x "$PERLTIDY_BIN" ]; then
+	perltidy_lib="$PERLTIDY_DIR/lib/perl5"
+	installed_version=$(PERL5LIB="$perltidy_lib${PERL5LIB:+:$PERL5LIB}" "$PERLTIDY_BIN" -v 2>/dev/null || true)
+	if echo "$installed_version" | grep -q "$PERLTIDY_VERSION"; then
+		echo "perltidy $PERLTIDY_VERSION is already installed in $PERLTIDY_DIR"
+		exit 0
+	fi
+fi
+
+WORK_DIR=$(mktemp -d)
+trap 'rm -rf "$WORK_DIR"' EXIT
+
+# Download
+TARBALL="$WORK_DIR/$PERLTIDY_TARBALL"
+if command -v curl >/dev/null 2>&1; then
+	curl -sSL -o "$TARBALL" "$PERLTIDY_URL"
+elif command -v wget >/dev/null 2>&1; then
+	wget -q -O "$TARBALL" "$PERLTIDY_URL"
+else
+	echo "error: neither curl nor wget found" >&2
+	exit 1
+fi
+
+# Verify SHA256
+if command -v sha256sum >/dev/null 2>&1; then
+	echo "$PERLTIDY_SHA256  $TARBALL" | sha256sum -c - >/dev/null
+elif command -v shasum >/dev/null 2>&1; then
+	echo "$PERLTIDY_SHA256  $TARBALL" | shasum -a 256 -c - >/dev/null
+else
+	echo "error: neither sha256sum nor shasum found" >&2
+	exit 1
+fi
+
+# Extract, build, install
+cd "$WORK_DIR"
+tar xzf "$TARBALL"
+cd "Perl-Tidy-${PERLTIDY_VERSION}"
+perl Makefile.PL INSTALL_BASE="$PERLTIDY_DIR" >/dev/null
+make >/dev/null
+make install >/dev/null
+
+echo "perltidy $PERLTIDY_VERSION installed in $PERLTIDY_DIR"
-- 
2.53.0

