view mercurial/scmposix.py @ 51572:13c004b54cbe stable

wireprotoserver: ensure that output stream gets flushed on exception Previously flush was happening due to Python finalizer being run on `BufferedWriter`. With upgrade to Python 3.11 this started randomly failing. My guess is that the finalizer on the raw `FileIO` object may be running before the finalizer of `BufferedWriter` has a chance to run. At any rate, since we're not relying on finalizers in the happy case we should also not rely on them in case of exception.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 04 Apr 2024 14:15:32 +0100
parents 9d3721552b6c
children a4b3b8dee0a8
line wrap: on
line source

import array
import errno
import fcntl
import os
import sys
import typing

from typing import (
    List,
    Tuple,
)

from . import (
    encoding,
    pycompat,
    util,
)

if typing.TYPE_CHECKING:
    from . import ui as uimod

# BSD 'more' escapes ANSI color sequences by default. This can be disabled by
# $MORE variable, but there's no compatible option with Linux 'more'. Given
# OS X is widely used and most modern Unix systems would have 'less', setting
# 'less' as the default seems reasonable.
fallbackpager = b'less'


def _rcfiles(path: bytes) -> List[bytes]:
    rcs = [os.path.join(path, b'hgrc')]
    rcdir = os.path.join(path, b'hgrc.d')
    try:
        rcs.extend(
            [
                os.path.join(rcdir, f)
                for f, kind in sorted(util.listdir(rcdir))
                if f.endswith(b".rc")
            ]
        )
    except OSError:
        pass
    return rcs


def systemrcpath() -> List[bytes]:
    path = []
    if pycompat.sysplatform == b'plan9':
        root = b'lib/mercurial'
    else:
        root = b'etc/mercurial'
    # old mod_python does not set sys.argv
    if len(getattr(sys, 'argv', [])) > 0:
        p = os.path.dirname(os.path.dirname(pycompat.sysargv[0]))
        if p != b'/':
            path.extend(_rcfiles(os.path.join(p, root)))
    path.extend(_rcfiles(b'/' + root))
    return path


def userrcpath() -> List[bytes]:
    if pycompat.sysplatform == b'plan9':
        return [encoding.environ[b'home'] + b'/lib/hgrc']
    elif pycompat.isdarwin:
        return [os.path.expanduser(b'~/.hgrc')]
    else:
        confighome = encoding.environ.get(b'XDG_CONFIG_HOME')
        if confighome is None or not os.path.isabs(confighome):
            confighome = os.path.expanduser(b'~/.config')

        return [
            os.path.expanduser(b'~/.hgrc'),
            os.path.join(confighome, b'hg', b'hgrc'),
        ]


def termsize(ui: "uimod.ui") -> Tuple[int, int]:
    try:
        import termios

        TIOCGWINSZ = termios.TIOCGWINSZ  # unavailable on IRIX (issue3449)
    except (AttributeError, ImportError):
        return 80, 24

    for dev in (ui.ferr, ui.fout, ui.fin):
        try:
            try:
                fd = dev.fileno()
            except AttributeError:
                continue
            if not os.isatty(fd):
                continue
            arri = fcntl.ioctl(fd, TIOCGWINSZ, b'\0' * 8)
            height, width = array.array('h', arri)[:2]
            if width > 0 and height > 0:
                return width, height
        except ValueError:
            pass
        except IOError as e:
            if e.errno == errno.EINVAL:
                pass
            else:
                raise
    return 80, 24