tests/hgweberror.py
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Wed, 14 Oct 2015 02:40:04 +0900
changeset 26630 3111b45a2bbf
parent 23409 dc4d2cd3aa3e
child 27299 74e6de99ce7f
permissions -rw-r--r--
parsers: make pack_dirstate take now in integer for consistency On recent OS, 'stat.st_mtime' has a double precision floating point value to represent nano seconds, but it is not wide enough for actual file timestamp: nowadays, only 52 - 32 = 20 bit width is available for decimal places in sec. Therefore, casting it to 'int' may cause unexpected result. See also changeset 13272104bb07 fixing issue4836 for detail. For example, changed file A may be treated as "clean" unexpectedly in steps below. "rounded now" is the value gotten by rounding via 'int(st.st_mtime)' or so. ---------------------+--------------------+------------------------ "now" | | timestamp of A (time_t) float rounded time_t| action | FS dirstate ------ ------- ------+--------------------+-------- --------------- N+.nnn N N | | --- --- | update file A | N | dirstate.normal(A) | N N+.999 N+1 N | | | dirstate.write() | N (*1) | : | | change file A | N | : | N+1.00 N+1 N+1 | | | "hg status" (*2) | N N ------ ------- ------+--------------------+-------- --------------- Timestamp N of A in dirstate isn't dropped at (*1), because "rounded now" is N+1 at that time, even if 'st_mtime' in 'time_t' is still N. Then, file A is unexpectedly treated as "clean" at (*2) in this case. For consistent handling of 'stat.st_mtime', this patch makes 'pack_dirstate()' take 'now' argument not in floating point but in integer. This patch makes 'PyArg_ParseTuple()' in 'pack_dirstate()' use format 'i' (= checking type mismatch or overflow), even though it is ensured that 'now' is in the range of 32bit signed integer by masking with '_rangemask' (= 0x7fffffff) on caller side. It should be cheaper enough than packing itself, and useful to detect that legacy code invokes 'pack_dirstate()' with 'now' in floating point value.

# A dummy extension that installs an hgweb command that throws an Exception.

from mercurial.hgweb import webcommands

def raiseerror(web, req, tmpl):
    '''Dummy web command that raises an uncaught Exception.'''

    # Simulate an error after partial response.
    if 'partialresponse' in req.form:
        req.respond(200, 'text/plain')
        req.write('partial content\n')

    raise AttributeError('I am an uncaught error!')

def extsetup(ui):
    setattr(webcommands, 'raiseerror', raiseerror)
    webcommands.__all__.append('raiseerror')