vfs: use checkambigatclosing in checkambig=True but atomictemp=False case
In Mercurial source tree, opening a file in "a"/"a+" mode like below
doesn't specify atomictemp=True for vfs, and this avoids file stat
ambiguity check by atomictempfile.
- writing changes out in revlog layer uses "a+" mode
- truncation in repair.strip() uses "a" mode
- truncation in transaction._playback() uses "a" mode
If steps below occurs at "the same time in sec", all of mtime, ctime
and size are same between (1) and (3).
1. append data to revlog-style file (and close transaction)
2. discard appended data by truncation (strip or rollback)
3. append same size but different data to revlog-style file again
Therefore, cache validation doesn't work after (3) as expected.
This patch uses checkambigatclosing in checkambig=True but
atomictemp=False case, to check (and get rid of) file stat ambiguity
at closing.
This is a part of ExactCacheValidationPlan.
https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
from __future__ import absolute_import
import cffi
import os
ffi = cffi.FFI()
mpatch_c = os.path.join(os.path.join(os.path.dirname(__file__), 'mercurial',
'mpatch.c'))
ffi.set_source("_mpatch_cffi", open(mpatch_c).read(),
include_dirs=["mercurial"])
ffi.cdef("""
struct mpatch_frag {
int start, end, len;
const char *data;
};
struct mpatch_flist {
struct mpatch_frag *base, *head, *tail;
};
extern "Python" struct mpatch_flist* cffi_get_next_item(void*, ssize_t);
int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist** res);
ssize_t mpatch_calcsize(size_t len, struct mpatch_flist *l);
void mpatch_lfree(struct mpatch_flist *a);
static int mpatch_apply(char *buf, const char *orig, size_t len,
struct mpatch_flist *l);
struct mpatch_flist *mpatch_fold(void *bins,
struct mpatch_flist* (*get_next_item)(void*, ssize_t),
ssize_t start, ssize_t end);
""")
if __name__ == '__main__':
ffi.compile()