##// END OF EJS Templates
diffhelpers: add version to help detect breaking binary changes
Jun Wu -
r32357:2f51f4c5 default
parent child Browse files
Show More
@@ -1,199 +1,204
1 1 /*
2 2 * diffhelpers.c - helper routines for mpatch
3 3 *
4 4 * Copyright 2007 Chris Mason <chris.mason@oracle.com>
5 5 *
6 6 * This software may be used and distributed according to the terms
7 7 * of the GNU General Public License v2, incorporated herein by reference.
8 8 */
9 9
10 10 #include <Python.h>
11 11 #include <stdlib.h>
12 12 #include <string.h>
13 13
14 14 #include "util.h"
15 15
16 16 static char diffhelpers_doc[] = "Efficient diff parsing";
17 17 static PyObject *diffhelpers_Error;
18 18
19 19
20 20 /* fixup the last lines of a and b when the patch has no newline at eof */
21 21 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
22 22 {
23 23 Py_ssize_t hunksz = PyList_Size(hunk);
24 24 PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
25 25 char *l = PyBytes_AsString(s);
26 26 Py_ssize_t alen = PyList_Size(a);
27 27 Py_ssize_t blen = PyList_Size(b);
28 28 char c = l[0];
29 29 PyObject *hline;
30 30 Py_ssize_t sz = PyBytes_GET_SIZE(s);
31 31
32 32 if (sz > 1 && l[sz-2] == '\r')
33 33 /* tolerate CRLF in last line */
34 34 sz -= 1;
35 35
36 36 hline = PyBytes_FromStringAndSize(l, sz-1);
37 37 if (!hline) {
38 38 return;
39 39 }
40 40
41 41 if (c == ' ' || c == '+') {
42 42 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
43 43 PyList_SetItem(b, blen-1, rline);
44 44 }
45 45 if (c == ' ' || c == '-') {
46 46 Py_INCREF(hline);
47 47 PyList_SetItem(a, alen-1, hline);
48 48 }
49 49 PyList_SetItem(hunk, hunksz-1, hline);
50 50 }
51 51
52 52 /* python callable form of _fix_newline */
53 53 static PyObject *
54 54 fix_newline(PyObject *self, PyObject *args)
55 55 {
56 56 PyObject *hunk, *a, *b;
57 57 if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
58 58 return NULL;
59 59 _fix_newline(hunk, a, b);
60 60 return Py_BuildValue("l", 0);
61 61 }
62 62
63 63 #if (PY_VERSION_HEX < 0x02050000)
64 64 static const char *addlines_format = "OOiiOO";
65 65 #else
66 66 static const char *addlines_format = "OOnnOO";
67 67 #endif
68 68
69 69 /*
70 70 * read lines from fp into the hunk. The hunk is parsed into two arrays
71 71 * a and b. a gets the old state of the text, b gets the new state
72 72 * The control char from the hunk is saved when inserting into a, but not b
73 73 * (for performance while deleting files)
74 74 */
75 75 static PyObject *
76 76 addlines(PyObject *self, PyObject *args)
77 77 {
78 78
79 79 PyObject *fp, *hunk, *a, *b, *x;
80 80 Py_ssize_t i;
81 81 Py_ssize_t lena, lenb;
82 82 Py_ssize_t num;
83 83 Py_ssize_t todoa, todob;
84 84 char *s, c;
85 85 PyObject *l;
86 86 if (!PyArg_ParseTuple(args, addlines_format,
87 87 &fp, &hunk, &lena, &lenb, &a, &b))
88 88 return NULL;
89 89
90 90 while (1) {
91 91 todoa = lena - PyList_Size(a);
92 92 todob = lenb - PyList_Size(b);
93 93 num = todoa > todob ? todoa : todob;
94 94 if (num == 0)
95 95 break;
96 96 for (i = 0; i < num; i++) {
97 97 x = PyFile_GetLine(fp, 0);
98 98 s = PyBytes_AsString(x);
99 99 c = *s;
100 100 if (strcmp(s, "\\ No newline at end of file\n") == 0) {
101 101 _fix_newline(hunk, a, b);
102 102 continue;
103 103 }
104 104 if (c == '\n') {
105 105 /* Some patches may be missing the control char
106 106 * on empty lines. Supply a leading space. */
107 107 Py_DECREF(x);
108 108 x = PyBytes_FromString(" \n");
109 109 }
110 110 PyList_Append(hunk, x);
111 111 if (c == '+') {
112 112 l = PyBytes_FromString(s + 1);
113 113 PyList_Append(b, l);
114 114 Py_DECREF(l);
115 115 } else if (c == '-') {
116 116 PyList_Append(a, x);
117 117 } else {
118 118 l = PyBytes_FromString(s + 1);
119 119 PyList_Append(b, l);
120 120 Py_DECREF(l);
121 121 PyList_Append(a, x);
122 122 }
123 123 Py_DECREF(x);
124 124 }
125 125 }
126 126 return Py_BuildValue("l", 0);
127 127 }
128 128
129 129 /*
130 130 * compare the lines in a with the lines in b. a is assumed to have
131 131 * a control char at the start of each line, this char is ignored in the
132 132 * compare
133 133 */
134 134 static PyObject *
135 135 testhunk(PyObject *self, PyObject *args)
136 136 {
137 137
138 138 PyObject *a, *b;
139 139 long bstart;
140 140 Py_ssize_t alen, blen;
141 141 Py_ssize_t i;
142 142 char *sa, *sb;
143 143
144 144 if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
145 145 return NULL;
146 146 alen = PyList_Size(a);
147 147 blen = PyList_Size(b);
148 148 if (alen > blen - bstart || bstart < 0) {
149 149 return Py_BuildValue("l", -1);
150 150 }
151 151 for (i = 0; i < alen; i++) {
152 152 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
153 153 sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
154 154 if (strcmp(sa + 1, sb) != 0)
155 155 return Py_BuildValue("l", -1);
156 156 }
157 157 return Py_BuildValue("l", 0);
158 158 }
159 159
160 160 static PyMethodDef methods[] = {
161 161 {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
162 162 {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
163 163 {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
164 164 {NULL, NULL}
165 165 };
166 166
167 static const int version = 1;
168
167 169 #ifdef IS_PY3K
168 170 static struct PyModuleDef diffhelpers_module = {
169 171 PyModuleDef_HEAD_INIT,
170 172 "diffhelpers",
171 173 diffhelpers_doc,
172 174 -1,
173 175 methods
174 176 };
175 177
176 178 PyMODINIT_FUNC PyInit_diffhelpers(void)
177 179 {
178 180 PyObject *m;
179 181
180 182 m = PyModule_Create(&diffhelpers_module);
181 183 if (m == NULL)
182 184 return NULL;
183 185
184 186 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
185 187 NULL, NULL);
186 188 Py_INCREF(diffhelpers_Error);
187 189 PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
190 PyModule_AddIntConstant(m, "version", version);
188 191
189 192 return m;
190 193 }
191 194 #else
192 195 PyMODINIT_FUNC
193 196 initdiffhelpers(void)
194 197 {
195 Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
198 PyObject *m;
199 m = Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
196 200 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
197 201 NULL, NULL);
202 PyModule_AddIntConstant(m, "version", version);
198 203 }
199 204 #endif
General Comments 0
You need to be logged in to leave comments. Login now