view tests/fakedirstatewritetime.py @ 27739:d6d3cf5fda6f

hooks: add HG_NODE_LAST to txnclose and changegroup hook environments Sometimes a txnclose or changegroup hook wants to iterate through all the changesets in transaction: in that situation usually the revset `$HG_NODE:` is used to select the revisions. Unfortunately this revset sometimes may contain too many changesets because we don't have the write lock while the hook runs newer changes may be added to repository in the meantime. That's why there is a need for extra variable carrying the information about the last change in the transaction.
author Mateusz Kwapich <mitrandir@fb.com>
date Tue, 05 Jan 2016 17:37:59 -0800
parents b38adef652fe
children df448de7cf3b
line wrap: on
line source

# extension to emulate invoking 'dirstate.write()' at the time
# specified by '[fakedirstatewritetime] fakenow', only when
# 'dirstate.write()' is invoked via functions below:
#
#   - 'workingctx._checklookup()' (= 'repo.status()')
#   - 'committablectx.markcommitted()'

from __future__ import absolute_import

from mercurial import (
    context,
    dirstate,
    extensions,
    parsers,
    util,
)

def pack_dirstate(fakenow, orig, dmap, copymap, pl, now):
    # execute what original parsers.pack_dirstate should do actually
    # for consistency
    actualnow = int(now)
    for f, e in dmap.iteritems():
        if e[0] == 'n' and e[3] == actualnow:
            e = parsers.dirstatetuple(e[0], e[1], e[2], -1)
            dmap[f] = e

    return orig(dmap, copymap, pl, fakenow)

def fakewrite(ui, func):
    # fake "now" of 'pack_dirstate' only if it is invoked while 'func'

    fakenow = ui.config('fakedirstatewritetime', 'fakenow')
    if not fakenow:
        # Execute original one, if fakenow isn't configured. This is
        # useful to prevent subrepos from executing replaced one,
        # because replacing 'parsers.pack_dirstate' is also effective
        # in subrepos.
        return func()

    # parsing 'fakenow' in YYYYmmddHHMM format makes comparison between
    # 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy
    fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0]

    orig_pack_dirstate = parsers.pack_dirstate
    orig_dirstate_getfsnow = dirstate._getfsnow
    wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args)

    parsers.pack_dirstate = wrapper
    dirstate._getfsnow = lambda *args: fakenow
    try:
        return func()
    finally:
        parsers.pack_dirstate = orig_pack_dirstate
        dirstate._getfsnow = orig_dirstate_getfsnow

def _checklookup(orig, workingctx, files):
    ui = workingctx.repo().ui
    return fakewrite(ui, lambda : orig(workingctx, files))

def markcommitted(orig, committablectx, node):
    ui = committablectx.repo().ui
    return fakewrite(ui, lambda : orig(committablectx, node))

def extsetup(ui):
    extensions.wrapfunction(context.workingctx, '_checklookup',
                            _checklookup)
    extensions.wrapfunction(context.committablectx, 'markcommitted',
                            markcommitted)