git 2.36.0 regression: pre-commit hooks no longer have stdout/stderr as tty
- From
Anthony Sottile <asottile@umich.edu>
- Date
- Apr 19, 2022, 18:59 UTC
- Message-ID
- <CA+dzEBn108QoMA28f0nC8K21XT+Afua0V2Qv8XkR8rAeqUCCZw@mail.gmail.com>
here's the shortest reproduction --
```console
$ cat ../testrepo/.git/hooks/pre-commit
#!/usr/bin/env bash
if [ -t 1 ]; then
echo GOOD
fi
```in previous git versions:
``` $ git commit -q --allow-empty -m foo GOOD $ ```
with git 2.36.0:
```` $ git commit -q --allow-empty -m foo $ ```
why I care: I maintain a git hooks framework which uses `isatty` to detect whether it's appropriate to color the output. many tools utilize the same check. in 2.36.0+ isatty is false for stdout and stderr causing coloring to be turned off.
I bisected this (it was a little complicated, needed to force a pty):
`../testrepo`: a git repo set up with the hook above
`../bisect.sh`:
```bash #!/usr/bin/env bash set -eux git clean -fxfd >& /dev/null make -j6 prefix="$PWD/prefix" NO_GETTEXT=1 NO_TCLTK=1 install >& /dev/null export PATH="$PWD/prefix/bin:$PATH" cd ../testrepo (../pty git commit -q --allow-empty -m foo || true) | grep GOOD ```
`../pty`:
```python #!/usr/bin/env python3 import errno import os import subprocess import sys
x: int = 'nope'
class Pty(object):
def __init__(self):
self.r = self.w = None def __enter__(self):
self.r, self.w = os.openpty()return self
def close_w(self):
if self.w is not None:
os.close(self.w)
self.w = None def close_r(self):
assert self.r is not None
os.close(self.r)
self.r = None def __exit__(self, exc_type, exc_value, traceback):
self.close_w()
self.close_r()def cmd_output_p(*cmd, **kwargs):
with open(os.devnull) as devnull, Pty() as pty:
kwargs = {'stdin': devnull, 'stdout': pty.w, 'stderr': pty.w}
proc = subprocess.Popen(cmd, **kwargs)
pty.close_w() buf = b''
while True:
try:
bts = os.read(pty.r, 4096)
except OSError as e:
if e.errno == errno.EIO:
bts = b''
else:
raise
else:
buf += bts
if not bts:
breakreturn proc.wait(), buf, None
if __name__ == '__main__':
_, buf, _ = cmd_output_p(*sys.argv[1:])
sys.stdout.buffer.write(buf)
```the first commit it points out:
``` f443246b9f29b815f0b98a07bb2d425628ae6522 is the first bad commit commit f443246b9f29b815f0b98a07bb2d425628ae6522 Author: Emily Shaffer <emilyshaffer@google.com> Date: Wed Dec 22 04:59:40 2021 +0100
commit: convert {pre-commit,prepare-commit-msg} hook to hook.h Move these hooks hook away from run-command.h to and over to the new
hook.h library. Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Acked-by: Emily Shaffer <emilyshaffer@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>commit.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) bisect run success ```
Anthony