mercurial/scmposix.py
author Jun Wu <quark@fb.com>
Mon, 14 Nov 2016 23:32:54 +0000
changeset 30405 10514a92860e
parent 30327 365812902904
child 30476 5b0baa9f3362
permissions -rw-r--r--
util: add iterfile to workaround a fileobj.__iter__ issue with EINTR The fileobj.__iter__ implementation in Python 2.7.12 (hg changeset 45d4cea97b04) is buggy: it cannot handle EINTR correctly. In Objects/fileobject.c: size_t Py_UniversalNewlineFread(....) { .... if (!f->f_univ_newline) return fread(buf, 1, n, stream); .... } According to the "fread" man page: If an error occurs, or the end of the file is reached, the return value is a short item count (or zero). Therefore it's possible for "fread" (and "Py_UniversalNewlineFread") to return a positive value while errno is set to EINTR and ferror(stream) changes from zero to non-zero. There are multiple "Py_UniversalNewlineFread": "file_read", "file_readinto", "file_readlines", "readahead". While the first 3 have code to handle the EINTR case, the last one "readahead" doesn't: static int readahead(PyFileObject *f, Py_ssize_t bufsize) { .... chunksize = Py_UniversalNewlineFread( f->f_buf, bufsize, f->f_fp, (PyObject *)f); .... if (chunksize == 0) { if (ferror(f->f_fp)) { PyErr_SetFromErrno(PyExc_IOError); .... } } .... } It means "readahead" could ignore EINTR, if "Py_UniversalNewlineFread" returns a non-zero value. And at the next time "readahead" got executed, if "Py_UniversalNewlineFread" returns 0, "readahead" would raise a Python error without a incorrect errno - could be 0 - thus "IOError: [Errno 0] Error". The only user of "readahead" is "readahead_get_line_skip". The only user of "readahead_get_line_skip" is "file_iternext", aka. "fileobj.__iter__", which should be avoided. There are multiple places where the pattern "for x in fp" is used. This patch adds a "iterfile" method in "util.py" so we can migrate our code from "for x in fp" to "fox x in util.iterfile(fp)".
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27483
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     1
from __future__ import absolute_import
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     2
30324
80708959161a scmutil: narrow ImportError handling in termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30323
diff changeset
     3
import array
30322
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
     4
import errno
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
     5
import fcntl
27483
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     6
import os
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     7
import sys
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     8
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
     9
from . import (
30290
c90a05124fae py3: make scmposix.userrcpath() return bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27483
diff changeset
    10
    encoding,
27483
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
    11
    osutil,
39087ee88835 scmposix: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 22583
diff changeset
    12
)
18690
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    13
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    14
def _rcfiles(path):
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    15
    rcs = [os.path.join(path, 'hgrc')]
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    16
    rcdir = os.path.join(path, 'hgrc.d')
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    17
    try:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    18
        rcs.extend([os.path.join(rcdir, f)
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    19
                    for f, kind in osutil.listdir(rcdir)
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    20
                    if f.endswith(".rc")])
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    21
    except OSError:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    22
        pass
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    23
    return rcs
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    24
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    25
def systemrcpath():
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    26
    path = []
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    27
    if sys.platform == 'plan9':
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    28
        root = 'lib/mercurial'
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    29
    else:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    30
        root = 'etc/mercurial'
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    31
    # old mod_python does not set sys.argv
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    32
    if len(getattr(sys, 'argv', [])) > 0:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    33
        p = os.path.dirname(os.path.dirname(sys.argv[0]))
22583
23c995ed466b config: don't read the same config file twice
Mads Kiilerich <madski@unity3d.com>
parents: 18690
diff changeset
    34
        if p != '/':
23c995ed466b config: don't read the same config file twice
Mads Kiilerich <madski@unity3d.com>
parents: 18690
diff changeset
    35
            path.extend(_rcfiles(os.path.join(p, root)))
18690
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    36
    path.extend(_rcfiles('/' + root))
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    37
    return path
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    38
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    39
def userrcpath():
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    40
    if sys.platform == 'plan9':
30290
c90a05124fae py3: make scmposix.userrcpath() return bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27483
diff changeset
    41
        return [encoding.environ['home'] + '/lib/hgrc']
18690
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    42
    else:
4c6f7f0dadab scmutil: split platform-specific bits into their own modules
Kevin Bullock <kbullock@ringworld.org>
parents:
diff changeset
    43
        return [os.path.expanduser('~/.hgrc')]
30322
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
    44
30327
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    45
def termsize(ui):
30322
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
    46
    try:
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
    47
        import termios
30324
80708959161a scmutil: narrow ImportError handling in termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30323
diff changeset
    48
        TIOCGWINSZ = termios.TIOCGWINSZ  # unavailable on IRIX (issue3449)
80708959161a scmutil: narrow ImportError handling in termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30323
diff changeset
    49
    except (AttributeError, ImportError):
30327
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    50
        return 80, 24
30325
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    51
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    52
    for dev in (ui.ferr, ui.fout, ui.fin):
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    53
        try:
30322
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
    54
            try:
30325
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    55
                fd = dev.fileno()
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    56
            except AttributeError:
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    57
                continue
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    58
            if not os.isatty(fd):
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    59
                continue
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    60
            arri = fcntl.ioctl(fd, TIOCGWINSZ, '\0' * 8)
30327
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    61
            height, width = array.array('h', arri)[:2]
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    62
            if width > 0 and height > 0:
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    63
                return width, height
30325
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    64
        except ValueError:
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    65
            pass
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    66
        except IOError as e:
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    67
            if e[0] == errno.EINVAL:
30322
4b1af1c867fa scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30290
diff changeset
    68
                pass
30325
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    69
            else:
1ad1c5017043 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org>
parents: 30324
diff changeset
    70
                raise
30327
365812902904 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org>
parents: 30325
diff changeset
    71
    return 80, 24