##// END OF EJS Templates
changelog: add class to represent parsed changelog revisions...
changelog: add class to represent parsed changelog revisions Currently, changelog entries are parsed into their respective components at read time. Many operations are only interested in a subset of fields of a changelog entry. The parsing and storing of all the fields adds avoidable overhead. This patch introduces the "changelogrevision" class. It takes changelog raw text and exposes the parsed results as attributes. The code for parsing changelog entries has been moved into its construction function. changelog.read() has been modified to use the new class internally while maintaining its existing API. Future patches will make revision parsing lazy. We implement the construction function of the new class with __new__ instead of __init__ so we can use a named tuple to represent the empty revision. This saves overhead and complexity of coercing later versions of this class to represent an empty instance. While we are here, we add a method on changelog to obtain an instance of the new type. The overhead of constructing the new class regresses performance of revsets accessing this data: author(mpm) 0.896565 0.929984 desc(bug) 0.887169 0.935642 105% date(2015) 0.878797 0.908094 extra(rebase_source) 0.865446 0.922624 106% author(mpm) or author(greg) 1.801832 1.902112 105% author(mpm) or desc(bug) 1.812438 1.860977 date(2015) or branch(default) 0.968276 1.005824 author(mpm) or desc(bug) or date(2015) or extra(rebase_source) 3.656193 3.743381 Once lazy parsing is implemented, these revsets will all be faster than before. There is no performance change on revsets that do not access this data. There /could/ be a performance regression on operations that perform several changelog reads. However, I can't think of anything outside of revsets and `hg log` (basically the same as a revset) that would be impacted.

File last commit:

r23964:f1c127df stable
r28487:98d98a64 default
Show More
diffhelpers.c
199 lines | 4.7 KiB | text/x-c | CLexer
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 /*
* diffhelpers.c - helper routines for mpatch
*
* Copyright 2007 Chris Mason <chris.mason@oracle.com>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License v2, incorporated herein by reference.
*/
#include <Python.h>
#include <stdlib.h>
#include <string.h>
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 #include "util.h"
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 static char diffhelpers_doc[] = "Efficient diff parsing";
static PyObject *diffhelpers_Error;
/* fixup the last lines of a and b when the patch has no newline at eof */
static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
{
Adrian Buehlmann
diffhelpers: use Py_ssize_t in _fix_newline()...
r16693 Py_ssize_t hunksz = PyList_Size(hunk);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 char *l = PyBytes_AsString(s);
Adrian Buehlmann
diffhelpers: use Py_ssize_t in _fix_newline()...
r16693 Py_ssize_t alen = PyList_Size(a);
Py_ssize_t blen = PyList_Size(b);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 char c = l[0];
Patrick Mezard
diffhelpers: fix variable declaration for MSVC (not C99)
r10146 PyObject *hline;
Adrian Buehlmann
diffhelpers: use Py_ssize_t in _fix_newline()...
r16693 Py_ssize_t sz = PyBytes_GET_SIZE(s);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897
Patrick Mezard
diffhelpers: fix variable declaration for MSVC (not C99)
r10146 if (sz > 1 && l[sz-2] == '\r')
/* tolerate CRLF in last line */
sz -= 1;
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363
hline = PyBytes_FromStringAndSize(l, sz-1);
Augie Fackler
diffhelpers: verify hline was created before using it...
r23959 if (!hline) {
Augie Fackler
diffhelpers: fix botched return statement from c8e7fa41bfc5...
r23964 return;
Augie Fackler
diffhelpers: verify hline was created before using it...
r23959 }
Patrick Mezard
diffhelpers: fix variable declaration for MSVC (not C99)
r10146
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 if (c == ' ' || c == '+') {
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyList_SetItem(b, blen-1, rline);
}
if (c == ' ' || c == '-') {
Py_INCREF(hline);
PyList_SetItem(a, alen-1, hline);
}
PyList_SetItem(hunk, hunksz-1, hline);
}
/* python callable form of _fix_newline */
static PyObject *
fix_newline(PyObject *self, PyObject *args)
{
PyObject *hunk, *a, *b;
if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
return NULL;
_fix_newline(hunk, a, b);
return Py_BuildValue("l", 0);
}
Adrian Buehlmann
diffhelpers: use Py_ssize_t in addlines()...
r16694 #if (PY_VERSION_HEX < 0x02050000)
static const char *addlines_format = "OOiiOO";
#else
static const char *addlines_format = "OOnnOO";
#endif
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 /*
* read lines from fp into the hunk. The hunk is parsed into two arrays
* a and b. a gets the old state of the text, b gets the new state
* The control char from the hunk is saved when inserting into a, but not b
* (for performance while deleting files)
*/
static PyObject *
addlines(PyObject *self, PyObject *args)
{
PyObject *fp, *hunk, *a, *b, *x;
Adrian Buehlmann
diffhelpers: use Py_ssize_t in addlines()...
r16694 Py_ssize_t i;
Py_ssize_t lena, lenb;
Py_ssize_t num;
Py_ssize_t todoa, todob;
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 char *s, c;
PyObject *l;
Adrian Buehlmann
diffhelpers: use Py_ssize_t in addlines()...
r16694 if (!PyArg_ParseTuple(args, addlines_format,
&fp, &hunk, &lena, &lenb, &a, &b))
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 return NULL;
Matt Mackall
many, many trivial check-code fixups
r10282 while (1) {
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 todoa = lena - PyList_Size(a);
todob = lenb - PyList_Size(b);
num = todoa > todob ? todoa : todob;
if (num == 0)
break;
Matt Mackall
many, many trivial check-code fixups
r10282 for (i = 0; i < num; i++) {
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 x = PyFile_GetLine(fp, 0);
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 s = PyBytes_AsString(x);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 c = *s;
if (strcmp(s, "\\ No newline at end of file\n") == 0) {
_fix_newline(hunk, a, b);
continue;
}
Hollis Blanchard
Handle patches with misformatted empty lines...
r5483 if (c == '\n') {
/* Some patches may be missing the control char
* on empty lines. Supply a leading space. */
Py_DECREF(x);
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 x = PyBytes_FromString(" \n");
Hollis Blanchard
Handle patches with misformatted empty lines...
r5483 }
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyList_Append(hunk, x);
if (c == '+') {
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 l = PyBytes_FromString(s + 1);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyList_Append(b, l);
Py_DECREF(l);
} else if (c == '-') {
PyList_Append(a, x);
} else {
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 l = PyBytes_FromString(s + 1);
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyList_Append(b, l);
Py_DECREF(l);
PyList_Append(a, x);
}
Py_DECREF(x);
}
}
return Py_BuildValue("l", 0);
}
/*
* compare the lines in a with the lines in b. a is assumed to have
* a control char at the start of each line, this char is ignored in the
* compare
*/
static PyObject *
testhunk(PyObject *self, PyObject *args)
{
PyObject *a, *b;
long bstart;
Adrian Buehlmann
diffhelpers: use Py_ssize_t in testhunk()...
r16695 Py_ssize_t alen, blen;
Py_ssize_t i;
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 char *sa, *sb;
if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
return NULL;
alen = PyList_Size(a);
blen = PyList_Size(b);
Matt Mackall
diffhelpers: harden testhunk
r16651 if (alen > blen - bstart || bstart < 0) {
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 return Py_BuildValue("l", -1);
}
Matt Mackall
many, many trivial check-code fixups
r10282 for (i = 0; i < alen; i++) {
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
Matt Mackall
many, many trivial check-code fixups
r10282 if (strcmp(sa + 1, sb) != 0)
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 return Py_BuildValue("l", -1);
}
return Py_BuildValue("l", 0);
}
static PyMethodDef methods[] = {
{"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
{"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
{"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
{NULL, NULL}
};
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 #ifdef IS_PY3K
static struct PyModuleDef diffhelpers_module = {
PyModuleDef_HEAD_INIT,
"diffhelpers",
diffhelpers_doc,
-1,
methods
};
PyMODINIT_FUNC PyInit_diffhelpers(void)
{
PyObject *m;
m = PyModule_Create(&diffhelpers_module);
if (m == NULL)
return NULL;
diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
NULL, NULL);
Py_INCREF(diffhelpers_Error);
PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
return m;
}
#else
Bryan O'Sullivan
Add Chris Mason's mpatch library....
r4897 PyMODINIT_FUNC
initdiffhelpers(void)
{
Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
NULL, NULL);
}
Renato Cunha
diffhelpers.c: Added support for py3k....
r11363 #endif