git 2.36.0 regression: pre-commit hooks no longer have stdout/stderr as tty

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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:
                break

    return 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@xxxxxxxxxx>
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@xxxxxxxxxx>
    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx>
    Acked-by: Emily Shaffer <emilyshaffer@xxxxxxxxxx>
    Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx>

 commit.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)
bisect run success
```


Anthony




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux