# HG changeset patch # User Augie Fackler # Date 2018-03-24 18:28:24 # Node ID b1f62cd39b5c350b3f939a5c77e96f28f3186960 # Parent 314f39e5fa8639b6a97cb427cde8a4cd03ef6986 fsmonitor: layer on another hack in bser.c for os.stat() compat (issue5811) It's unclear to me how these `bserobj_tuple` objects are used, other than as stat objects. This should fix fsmonitor in the wake of ffa3026d4196 and similar changes. I regret the hack here, but the code already has plenty of hg-specific hacks. :( It feels like we should be able to use int(result.st_mtime) globally, but that doesn't work. See issue4836 for a bug that was hard to track down relating to rounding behavior causing very subtle dirstate problems. Differential Revision: https://phab.mercurial-scm.org/D2939 diff --git a/hgext/fsmonitor/pywatchman/bser.c b/hgext/fsmonitor/pywatchman/bser.c --- a/hgext/fsmonitor/pywatchman/bser.c +++ b/hgext/fsmonitor/pywatchman/bser.c @@ -128,27 +128,38 @@ static PyObject* bserobj_getattrro(PyObj Py_ssize_t i, n; PyObject* name_bytes = NULL; PyObject* ret = NULL; - const char* namestr; + const char* namestr = NULL; if (PyIndex_Check(name)) { i = PyNumber_AsSsize_t(name, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { goto bail; } - ret = PySequence_GetItem(obj->values, i); - goto bail; - } - // We can be passed in Unicode objects here -- we don't support anything other - // than UTF-8 for keys. - if (PyUnicode_Check(name)) { - name_bytes = PyUnicode_AsUTF8String(name); - if (name_bytes == NULL) { + if (i == 8 && PySequence_Size(obj->values) < 9) { + // Hack alert: Python 3 removed support for os.stat().st_mtime + // being an integer.Instead, if you need an integer, you have to + // use os.stat()[stat.ST_MTIME] instead. stat.ST_MTIME is 8, and + // our stat tuples are shorter than that, so we can detect + // requests for index 8 on tuples shorter than that and return + // st_mtime instead. + namestr = "st_mtime"; + } else { + ret = PySequence_GetItem(obj->values, i); goto bail; } - namestr = PyBytes_AsString(name_bytes); } else { - namestr = PyBytes_AsString(name); + // We can be passed in Unicode objects here -- we don't support anything other + // than UTF-8 for keys. + if (PyUnicode_Check(name)) { + name_bytes = PyUnicode_AsUTF8String(name); + if (name_bytes == NULL) { + goto bail; + } + namestr = PyBytes_AsString(name_bytes); + } else { + namestr = PyBytes_AsString(name); + } } if (namestr == NULL) {