Hi,
src/tools/git-external-diff is a Bash script, but its usage text is enclosed
in the Perl POD markers =comment and =cut. Bash therefore tries to execute
the prose and the embedded git config/git diff examples on each invocation.
The attached patch changes only those two delimiters to a quoted no-op
here-document. This preserves the text literally, without executing it or
performing shell expansions, and leaves the actual diff code unchanged.
The patch was prepared against master at
3cde90ecc5f85e7c6cb9fba29d473b2f6dd40ee1.
Validation:
- bash -n and git diff --check pass.
- The attached standalone test passes all three cases with the patch;
all three fail against the unmodified master file. It records Git calls
rather than allowing the documentation examples to change configuration
or invoke another diff. It covers unchanged content, context diffs with
spaced paths, and custom DIFF_OPTS=-u.
- A separate integration check using real Git in an isolated temporary
repository produces the expected context diff and leaves configuration
unchanged.
Run the standalone test with an explicit path to the file under test:
python3 test_git_external_diff.py /path/to/postgres/src/tools/git-external-diff
This was originally proposed to IvorySQL; its maintainers asked that this
inherited tool change be sent upstream first:
https://github.com/IvorySQL/IvorySQL/pull/2510
AI assistance was used to prepare the patch, tests, and this message.
The reported validation results are from actual local runs.
Regards,
zmuxuny
From d0b00911847fdade71132dd0b573c5778ad479be Mon Sep 17 00:00:00 2001
From: zmuxuny <[email protected]>
Date: Tue, 20 Oct 2026 21:13:43 -0700
Subject: [PATCH] Make git-external-diff usage text a shell comment
The usage text is enclosed by Perl POD markers, but this is a Bash script. As a
result the text and its embedded Git commands are executed on every invocation.
Use a quoted no-op here-document to keep the documentation literal and leave
the diff behavior unchanged.
---
src/tools/git-external-diff | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/tools/git-external-diff b/src/tools/git-external-diff
index 39ddd01b..71db2ccc 100644
--- a/src/tools/git-external-diff
+++ b/src/tools/git-external-diff
@@ -7,7 +7,7 @@
# path old-file old-hash old-mode new-file new-hash new-mode
# 'path' is the git-tree-relative path of the file being diff'ed
-=comment
+: <<'DOCUMENTATION'
This info is copied from the old wiki page on Working with git:
@@ -40,7 +40,7 @@ Alternatively, configure a git alias in ~/.gitconfig or
.git/config:
[alias]
cdiff = !GIT_EXTERNAL_DIFF=git-context-diff git diff
-=cut
+DOCUMENTATION
old_hash="$3"
new_hash=$(git hash-object "$5")
--
2.52.0
#!/usr/bin/env python3
"""Run the Bash external-diff wrapper without executing Git configuration.
Run: python3 test_git_external_diff.py
/path/to/postgres/src/tools/git-external-diff
"""
import hashlib
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
if len(sys.argv) < 2:
raise SystemExit('Pass the path to the script under test as the first
argument')
SCRIPT = Path(sys.argv.pop(1)).resolve()
GIT = r'''#!/usr/bin/env python3
import hashlib
import json
import os
from pathlib import Path
import sys
args = sys.argv[1:]
with open(os.environ['GIT_LOG'], 'a', encoding='utf-8') as log:
log.write(json.dumps(args) + '\n')
if args[0] == 'hash-object':
data = Path(args[1]).read_bytes()
print(hashlib.sha1(b'blob ' + str(len(data)).encode() + b'\0' +
data).hexdigest())
else:
# Record but never run the config/diff examples embedded in the old script.
sys.exit(1)
'''
def blob_hash(data):
return hashlib.sha1(b'blob ' + str(len(data)).encode() + b'\0' +
data).hexdigest()
class ExternalDiff(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
bindir = self.root / 'bin'
bindir.mkdir()
git = bindir / 'git'
git.write_text(GIT, encoding='utf-8')
git.chmod(0o755)
self.log = self.root / 'git.jsonl'
self.env = dict(os.environ, PATH=str(bindir) + os.pathsep +
os.environ['PATH'],
GIT_LOG=str(self.log), DIFF_OPTS='')
self.old = self.root / 'old file'
self.new = self.root / 'new file'
def run_diff(self, old, new):
self.old.write_bytes(old)
self.new.write_bytes(new)
result = subprocess.run(
['bash', str(SCRIPT), 'source file.c', str(self.old),
blob_hash(old),
'100644', str(self.new), blob_hash(new), '100644'],
cwd=self.root, env=self.env, capture_output=True, text=True,
check=False)
calls = [json.loads(line) for line in self.log.read_text().splitlines()]
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(calls, [['hash-object', str(self.new)]])
self.assertEqual(result.stderr, '')
return result.stdout
def test_changed_content_produces_context_diff(self):
output = self.run_diff(b'old line\n', b'new line\n')
self.assertIn('diff --git a/source file.c b/source file.c\n', output)
self.assertIn('*** a/source file.c\n--- b/source file.c\n', output)
self.assertIn('! old line\n', output)
self.assertIn('! new line\n', output)
def test_unchanged_content_is_silent(self):
self.assertEqual(self.run_diff(b'same line\n', b'same line\n'), '')
def test_custom_diff_options_remain_supported(self):
self.env['DIFF_OPTS'] = '-u'
output = self.run_diff(b'old line\n', b'new line\n')
self.assertIn('--- a/source file.c\n+++ b/source file.c\n', output)
self.assertIn('-old line\n+new line\n', output)
if __name__ == '__main__':
unittest.main()
#!/usr/bin/env python3
"""Check the fixed wrapper using real Git in a disposable isolated repository.
Usage: python3 test_git_integration.py /path/to/fixed/git-external-diff
Do not run this test on the original buggy wrapper; use the recording-Git
unit test for the baseline to prevent recursive documentation examples.
"""
import os
from pathlib import Path
import subprocess
import sys
import tempfile
script = Path(sys.argv[1]).resolve()
with tempfile.TemporaryDirectory(prefix='pg-diff-integration-') as tmp:
root = Path(tmp)
env = {**os.environ, 'HOME': tmp, 'GIT_CONFIG_NOSYSTEM': '1',
'GIT_CONFIG_GLOBAL': str(root / 'global-config')}
def git(*args):
return subprocess.run(['git', *args], cwd=root, env=env, check=True,
text=True, capture_output=True, timeout=10).stdout
git('init', '--quiet')
source = root / 'source file.c'
source.write_text('old line\n')
git('add', 'source file.c')
git('-c', 'user.name=Test', '-c', '[email protected]',
'commit', '--quiet', '-m', 'fixture')
config_before = (root / '.git/config').read_bytes()
source.write_text('new line\n')
output = git('-c', f'diff.external=/bin/bash {script}', 'diff')
assert '*** a/source file.c\n--- b/source file.c\n' in output
assert '! old line' in output and '! new line' in output
assert (root / '.git/config').read_bytes() == config_before
assert not (root / 'global-config').exists()
print('Real Git integration: PASS (spaced filename, context diff, no config
changes)')