##// END OF EJS Templates
Some additional space/tab cleanups
Thomas Arendsen Hein -
r7190:aecea693 default
parent child Browse files
Show More
@@ -1,155 +1,155 b''
1 1 /*
2 2 base85 codec
3 3
4 4 Copyright 2006 Brendan Cully <brendan@kublai.com>
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8
9 9 Largely based on git's implementation
10 10 */
11 11
12 12 #include <Python.h>
13 13
14 14 static const char b85chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
15 15 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
16 16 static char b85dec[256];
17 17
18 18 static void
19 19 b85prep(void)
20 20 {
21 21 int i;
22 22
23 23 memset(b85dec, 0, sizeof(b85dec));
24 24 for (i = 0; i < sizeof(b85chars); i++)
25 25 b85dec[(int)(b85chars[i])] = i + 1;
26 26 }
27 27
28 28 static PyObject *
29 29 b85encode(PyObject *self, PyObject *args)
30 30 {
31 31 const unsigned char *text;
32 32 PyObject *out;
33 33 char *dst;
34 34 int len, olen, i;
35 35 unsigned int acc, val, ch;
36 int pad = 0;
36 int pad = 0;
37 37
38 38 if (!PyArg_ParseTuple(args, "s#|i", &text, &len, &pad))
39 39 return NULL;
40 40
41 if (pad)
42 olen = ((len + 3) / 4 * 5) - 3;
43 else {
44 olen = len % 4;
45 if (olen)
46 olen++;
47 olen += len / 4 * 5;
48 }
41 if (pad)
42 olen = ((len + 3) / 4 * 5) - 3;
43 else {
44 olen = len % 4;
45 if (olen)
46 olen++;
47 olen += len / 4 * 5;
48 }
49 49 if (!(out = PyString_FromStringAndSize(NULL, olen + 3)))
50 50 return NULL;
51 51
52 52 dst = PyString_AS_STRING(out);
53 53
54 54 while (len) {
55 55 acc = 0;
56 56 for (i = 24; i >= 0; i -= 8) {
57 57 ch = *text++;
58 58 acc |= ch << i;
59 59 if (--len == 0)
60 60 break;
61 61 }
62 62 for (i = 4; i >= 0; i--) {
63 63 val = acc % 85;
64 64 acc /= 85;
65 65 dst[i] = b85chars[val];
66 66 }
67 67 dst += 5;
68 68 }
69 69
70 if (!pad)
71 _PyString_Resize(&out, olen);
70 if (!pad)
71 _PyString_Resize(&out, olen);
72 72
73 73 return out;
74 74 }
75 75
76 76 static PyObject *
77 77 b85decode(PyObject *self, PyObject *args)
78 78 {
79 79 PyObject *out;
80 80 const char *text;
81 81 char *dst;
82 82 int len, i, j, olen, c, cap;
83 83 unsigned int acc;
84 84
85 85 if (!PyArg_ParseTuple(args, "s#", &text, &len))
86 86 return NULL;
87 87
88 88 olen = len / 5 * 4;
89 89 i = len % 5;
90 90 if (i)
91 91 olen += i - 1;
92 92 if (!(out = PyString_FromStringAndSize(NULL, olen)))
93 93 return NULL;
94 94
95 95 dst = PyString_AS_STRING(out);
96 96
97 97 i = 0;
98 98 while (i < len)
99 99 {
100 100 acc = 0;
101 101 cap = len - i - 1;
102 102 if (cap > 4)
103 103 cap = 4;
104 104 for (j = 0; j < cap; i++, j++)
105 105 {
106 106 c = b85dec[(int)*text++] - 1;
107 107 if (c < 0)
108 108 return PyErr_Format(PyExc_ValueError, "Bad base85 character at position %d", i);
109 109 acc = acc * 85 + c;
110 110 }
111 111 if (i++ < len)
112 112 {
113 113 c = b85dec[(int)*text++] - 1;
114 114 if (c < 0)
115 115 return PyErr_Format(PyExc_ValueError, "Bad base85 character at position %d", i);
116 116 /* overflow detection: 0xffffffff == "|NsC0",
117 117 * "|NsC" == 0x03030303 */
118 118 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
119 119 return PyErr_Format(PyExc_ValueError, "Bad base85 sequence at position %d", i);
120 120 acc += c;
121 121 }
122 122
123 123 cap = olen < 4 ? olen : 4;
124 124 olen -= cap;
125 125 for (j = 0; j < 4 - cap; j++)
126 126 acc *= 85;
127 127 if (cap && cap < 4)
128 128 acc += 0xffffff >> (cap - 1) * 8;
129 129 for (j = 0; j < cap; j++)
130 130 {
131 131 acc = (acc << 8) | (acc >> 24);
132 132 *dst++ = acc;
133 133 }
134 134 }
135 135
136 136 return out;
137 137 }
138 138
139 139 static char base85_doc[] = "Base85 Data Encoding";
140 140
141 141 static PyMethodDef methods[] = {
142 142 {"b85encode", b85encode, METH_VARARGS,
143 "Encode text in base85.\n\n"
144 "If the second parameter is true, pad the result to a multiple of "
145 "five characters.\n"},
143 "Encode text in base85.\n\n"
144 "If the second parameter is true, pad the result to a multiple of "
145 "five characters.\n"},
146 146 {"b85decode", b85decode, METH_VARARGS, "Decode base85 text.\n"},
147 147 {NULL, NULL}
148 148 };
149 149
150 150 PyMODINIT_FUNC initbase85(void)
151 151 {
152 152 Py_InitModule3("base85", methods, base85_doc);
153 153
154 154 b85prep();
155 155 }
@@ -1,409 +1,409 b''
1 1 /*
2 2 osutil.c - native operating system services
3 3
4 4 Copyright 2007 Matt Mackall and others
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 #define _ATFILE_SOURCE
11 11 #include <Python.h>
12 12 #ifdef _WIN32
13 13 #include <windows.h>
14 14 #else
15 15 #include <dirent.h>
16 16 #include <fcntl.h>
17 17 #include <string.h>
18 18 #include <sys/stat.h>
19 19 #include <sys/types.h>
20 20 #include <unistd.h>
21 21 #endif
22 22
23 23 #ifdef _WIN32
24 24 /*
25 25 stat struct compatible with hg expectations
26 26 Mercurial only uses st_mode, st_size and st_mtime
27 27 the rest is kept to minimize changes between implementations
28 28 */
29 29 struct hg_stat {
30 30 int st_dev;
31 31 int st_mode;
32 32 int st_nlink;
33 33 __int64 st_size;
34 34 int st_mtime;
35 35 int st_ctime;
36 36 };
37 37 struct listdir_stat {
38 38 PyObject_HEAD
39 39 struct hg_stat st;
40 40 };
41 41 #else
42 42 struct listdir_stat {
43 43 PyObject_HEAD
44 44 struct stat st;
45 45 };
46 46 #endif
47 47
48 48 #define listdir_slot(name) \
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
50 { \
51 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
52 }
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
50 { \
51 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
52 }
53 53
54 54 listdir_slot(st_dev)
55 55 listdir_slot(st_mode)
56 56 listdir_slot(st_nlink)
57 57 #ifdef _WIN32
58 58 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
59 59 {
60 60 return PyLong_FromLongLong(
61 61 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
62 62 }
63 63 #else
64 64 listdir_slot(st_size)
65 65 #endif
66 66 listdir_slot(st_mtime)
67 67 listdir_slot(st_ctime)
68 68
69 69 static struct PyGetSetDef listdir_stat_getsets[] = {
70 70 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
71 71 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
72 72 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
73 73 {"st_size", listdir_stat_st_size, 0, 0, 0},
74 74 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
75 75 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
76 76 {0, 0, 0, 0, 0}
77 77 };
78 78
79 79 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
80 80 {
81 81 return t->tp_alloc(t, 0);
82 82 }
83 83
84 84 static void listdir_stat_dealloc(PyObject *o)
85 85 {
86 86 o->ob_type->tp_free(o);
87 87 }
88 88
89 89 static PyTypeObject listdir_stat_type = {
90 90 PyObject_HEAD_INIT(NULL)
91 91 0, /*ob_size*/
92 92 "osutil.stat", /*tp_name*/
93 93 sizeof(struct listdir_stat), /*tp_basicsize*/
94 94 0, /*tp_itemsize*/
95 95 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
96 96 0, /*tp_print*/
97 97 0, /*tp_getattr*/
98 98 0, /*tp_setattr*/
99 99 0, /*tp_compare*/
100 100 0, /*tp_repr*/
101 101 0, /*tp_as_number*/
102 102 0, /*tp_as_sequence*/
103 103 0, /*tp_as_mapping*/
104 104 0, /*tp_hash */
105 105 0, /*tp_call*/
106 106 0, /*tp_str*/
107 107 0, /*tp_getattro*/
108 108 0, /*tp_setattro*/
109 109 0, /*tp_as_buffer*/
110 110 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
111 111 "stat objects", /* tp_doc */
112 112 0, /* tp_traverse */
113 113 0, /* tp_clear */
114 114 0, /* tp_richcompare */
115 115 0, /* tp_weaklistoffset */
116 116 0, /* tp_iter */
117 117 0, /* tp_iternext */
118 118 0, /* tp_methods */
119 119 0, /* tp_members */
120 120 listdir_stat_getsets, /* tp_getset */
121 121 0, /* tp_base */
122 122 0, /* tp_dict */
123 123 0, /* tp_descr_get */
124 124 0, /* tp_descr_set */
125 125 0, /* tp_dictoffset */
126 126 0, /* tp_init */
127 127 0, /* tp_alloc */
128 128 listdir_stat_new, /* tp_new */
129 129 };
130 130
131 131 #ifdef _WIN32
132 132
133 133 static int to_python_time(const FILETIME *tm)
134 134 {
135 135 /* number of seconds between epoch and January 1 1601 */
136 136 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
137 137 /* conversion factor from 100ns to 1s */
138 138 const __int64 a1 = 10000000;
139 139 /* explicit (int) cast to suspend compiler warnings */
140 140 return (int)((((__int64)tm->dwHighDateTime << 32)
141 141 + tm->dwLowDateTime) / a1 - a0);
142 142 }
143 143
144 144 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
145 145 {
146 146 PyObject *py_st;
147 147 struct hg_stat *stp;
148 148
149 149 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
150 150 ? _S_IFDIR : _S_IFREG;
151 151
152 152 if (!wantstat)
153 153 return Py_BuildValue("si", fd->cFileName, kind);
154 154
155 155 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
156 156 if (!py_st)
157 157 return NULL;
158 158
159 159 stp = &((struct listdir_stat *)py_st)->st;
160 160 /*
161 161 use kind as st_mode
162 162 rwx bits on Win32 are meaningless
163 163 and Hg does not use them anyway
164 164 */
165 165 stp->st_mode = kind;
166 166 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
167 167 stp->st_ctime = to_python_time(&fd->ftCreationTime);
168 168 if (kind == _S_IFREG)
169 169 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
170 170 + fd->nFileSizeLow;
171 171 return Py_BuildValue("siN", fd->cFileName,
172 172 kind, py_st);
173 173 }
174 174
175 175 static PyObject *_listdir(char *path, int plen, int wantstat, char *skip)
176 176 {
177 177 PyObject *rval = NULL; /* initialize - return value */
178 178 PyObject *list;
179 179 HANDLE fh;
180 180 WIN32_FIND_DATAA fd;
181 181 char *pattern;
182 182
183 183 /* build the path + \* pattern string */
184 184 pattern = malloc(plen+3); /* path + \* + \0 */
185 185 if (!pattern) {
186 186 PyErr_NoMemory();
187 187 goto error_nomem;
188 188 }
189 189 strcpy(pattern, path);
190 190
191 191 if (plen > 0) {
192 192 char c = path[plen-1];
193 193 if (c != ':' && c != '/' && c != '\\')
194 194 pattern[plen++] = '\\';
195 195 }
196 196 strcpy(pattern + plen, "*");
197 197
198 198 fh = FindFirstFileA(pattern, &fd);
199 199 if (fh == INVALID_HANDLE_VALUE) {
200 200 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
201 201 goto error_file;
202 202 }
203 203
204 204 list = PyList_New(0);
205 205 if (!list)
206 206 goto error_list;
207 207
208 208 do {
209 209 PyObject *item;
210 210
211 211 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
212 212 if (!strcmp(fd.cFileName, ".")
213 213 || !strcmp(fd.cFileName, ".."))
214 214 continue;
215 215
216 216 if (skip && !strcmp(fd.cFileName, skip)) {
217 217 rval = PyList_New(0);
218 218 goto error;
219 219 }
220 220 }
221 221
222 222 item = make_item(&fd, wantstat);
223 223 if (!item)
224 224 goto error;
225 225
226 226 if (PyList_Append(list, item)) {
227 227 Py_XDECREF(item);
228 228 goto error;
229 229 }
230 230
231 231 Py_XDECREF(item);
232 232 } while (FindNextFileA(fh, &fd));
233 233
234 234 if (GetLastError() != ERROR_NO_MORE_FILES) {
235 235 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
236 236 goto error;
237 237 }
238 238
239 239 rval = list;
240 240 Py_XINCREF(rval);
241 241 error:
242 242 Py_XDECREF(list);
243 243 error_list:
244 244 FindClose(fh);
245 245 error_file:
246 246 free(pattern);
247 247 error_nomem:
248 248 return rval;
249 249 }
250 250
251 251 #else
252 252
253 253 int entkind(struct dirent *ent)
254 254 {
255 255 #ifdef DT_REG
256 256 switch (ent->d_type) {
257 257 case DT_REG: return S_IFREG;
258 258 case DT_DIR: return S_IFDIR;
259 259 case DT_LNK: return S_IFLNK;
260 260 case DT_BLK: return S_IFBLK;
261 261 case DT_CHR: return S_IFCHR;
262 262 case DT_FIFO: return S_IFIFO;
263 263 case DT_SOCK: return S_IFSOCK;
264 264 }
265 265 #endif
266 266 return -1;
267 267 }
268 268
269 269 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
270 270 {
271 271 PyObject *list, *elem, *stat, *ret = NULL;
272 272 char fullpath[PATH_MAX + 10];
273 273 int kind, err;
274 274 struct stat st;
275 275 struct dirent *ent;
276 276 DIR *dir;
277 277 #ifdef AT_SYMLINK_NOFOLLOW
278 278 int dfd = -1;
279 279 #endif
280 280
281 281 if (pathlen >= PATH_MAX) {
282 282 PyErr_SetString(PyExc_ValueError, "path too long");
283 283 goto error_value;
284 284 }
285 285 strncpy(fullpath, path, PATH_MAX);
286 286 fullpath[pathlen] = '/';
287 287
288 288 #ifdef AT_SYMLINK_NOFOLLOW
289 289 dfd = open(path, O_RDONLY);
290 290 if (dfd == -1) {
291 291 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
292 292 goto error_value;
293 293 }
294 294 dir = fdopendir(dfd);
295 295 #else
296 296 dir = opendir(path);
297 297 #endif
298 298 if (!dir) {
299 299 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
300 300 goto error_dir;
301 301 }
302 302
303 303 list = PyList_New(0);
304 304 if (!list)
305 305 goto error_list;
306 306
307 307 while ((ent = readdir(dir))) {
308 308 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
309 309 continue;
310 310
311 311 kind = entkind(ent);
312 312 if (kind == -1 || keepstat) {
313 313 #ifdef AT_SYMLINK_NOFOLLOW
314 314 err = fstatat(dfd, ent->d_name, &st,
315 315 AT_SYMLINK_NOFOLLOW);
316 316 #else
317 317 strncpy(fullpath + pathlen + 1, ent->d_name,
318 318 PATH_MAX - pathlen);
319 319 fullpath[PATH_MAX] = 0;
320 320 err = lstat(fullpath, &st);
321 321 #endif
322 322 if (err == -1) {
323 323 strncpy(fullpath + pathlen + 1, ent->d_name,
324 324 PATH_MAX - pathlen);
325 325 fullpath[PATH_MAX] = 0;
326 326 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
327 327 fullpath);
328 328 goto error;
329 329 }
330 330 kind = st.st_mode & S_IFMT;
331 331 }
332 332
333 333 /* quit early? */
334 334 if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
335 335 ret = PyList_New(0);
336 336 goto error;
337 337 }
338 338
339 339 if (keepstat) {
340 340 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
341 341 if (!stat)
342 342 goto error;
343 343 memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
344 344 elem = Py_BuildValue("siN", ent->d_name, kind, stat);
345 345 } else
346 346 elem = Py_BuildValue("si", ent->d_name, kind);
347 347 if (!elem)
348 348 goto error;
349 349
350 350 PyList_Append(list, elem);
351 351 Py_DECREF(elem);
352 352 }
353 353
354 354 ret = list;
355 355 Py_INCREF(ret);
356 356
357 357 error:
358 358 Py_DECREF(list);
359 359 error_list:
360 360 closedir(dir);
361 361 error_dir:
362 362 #ifdef AT_SYMLINK_NOFOLLOW
363 363 close(dfd);
364 364 #endif
365 365 error_value:
366 366 return ret;
367 367 }
368 368
369 369 #endif /* ndef _WIN32 */
370 370
371 371 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
372 372 {
373 373 PyObject *statobj = NULL; /* initialize - optional arg */
374 374 PyObject *skipobj = NULL; /* initialize - optional arg */
375 375 char *path, *skip = NULL;
376 376 int wantstat, plen;
377 377
378 378 static char *kwlist[] = {"path", "stat", "skip", NULL};
379 379
380 380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|OO:listdir",
381 381 kwlist, &path, &plen, &statobj, &skipobj))
382 382 return NULL;
383 383
384 384 wantstat = statobj && PyObject_IsTrue(statobj);
385 385
386 386 if (skipobj && skipobj != Py_None) {
387 387 skip = PyString_AsString(skipobj);
388 388 if (!skip)
389 389 return NULL;
390 390 }
391 391
392 392 return _listdir(path, plen, wantstat, skip);
393 393 }
394 394
395 395 static char osutil_doc[] = "Native operating system services.";
396 396
397 397 static PyMethodDef methods[] = {
398 398 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
399 399 "list a directory\n"},
400 400 {NULL, NULL}
401 401 };
402 402
403 403 PyMODINIT_FUNC initosutil(void)
404 404 {
405 405 if (PyType_Ready(&listdir_stat_type) == -1)
406 406 return;
407 407
408 408 Py_InitModule3("osutil", methods, osutil_doc);
409 409 }
@@ -1,435 +1,435 b''
1 1 /*
2 2 parsers.c - efficient content parsing
3 3
4 4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 #include <Python.h>
11 11 #include <ctype.h>
12 12 #include <string.h>
13 13
14 14 static int hexdigit(char c)
15 15 {
16 16 if (c >= '0' && c <= '9')
17 17 return c - '0';
18 18 if (c >= 'a' && c <= 'f')
19 19 return c - 'a' + 10;
20 20 if (c >= 'A' && c <= 'F')
21 21 return c - 'A' + 10;
22 22
23 23 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
24 24 return 0;
25 25 }
26 26
27 27 /*
28 28 * Turn a hex-encoded string into binary.
29 29 */
30 30 static PyObject *unhexlify(const char *str, int len)
31 31 {
32 32 PyObject *ret;
33 33 const char *c;
34 34 char *d;
35 35
36 36 ret = PyString_FromStringAndSize(NULL, len / 2);
37 37 if (!ret)
38 38 return NULL;
39 39
40 40 d = PyString_AS_STRING(ret);
41 41 for (c = str; c < str + len;) {
42 42 int hi = hexdigit(*c++);
43 43 int lo = hexdigit(*c++);
44 44 *d++ = (hi << 4) | lo;
45 45 }
46 46
47 47 return ret;
48 48 }
49 49
50 50 /*
51 51 * This code assumes that a manifest is stitched together with newline
52 52 * ('\n') characters.
53 53 */
54 54 static PyObject *parse_manifest(PyObject *self, PyObject *args)
55 55 {
56 56 PyObject *mfdict, *fdict;
57 57 char *str, *cur, *start, *zero;
58 58 int len;
59 59
60 60 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
61 61 &PyDict_Type, &mfdict,
62 62 &PyDict_Type, &fdict,
63 63 &str, &len))
64 64 goto quit;
65 65
66 66 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
67 67 PyObject *file = NULL, *node = NULL;
68 68 PyObject *flags = NULL;
69 69 int nlen;
70 70
71 71 if (!*cur) {
72 72 zero = cur;
73 73 continue;
74 74 }
75 75 else if (*cur != '\n')
76 76 continue;
77 77
78 78 if (!zero) {
79 79 PyErr_SetString(PyExc_ValueError,
80 80 "manifest entry has no separator");
81 81 goto quit;
82 82 }
83 83
84 84 file = PyString_FromStringAndSize(start, zero - start);
85 85 if (!file)
86 86 goto bail;
87 87
88 88 nlen = cur - zero - 1;
89 89
90 90 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
91 91 if (!node)
92 92 goto bail;
93 93
94 94 if (nlen > 40) {
95 95 PyObject *flags;
96 96
97 97 flags = PyString_FromStringAndSize(zero + 41,
98 98 nlen - 40);
99 99 if (!flags)
100 100 goto bail;
101 101
102 102 if (PyDict_SetItem(fdict, file, flags) == -1)
103 103 goto bail;
104 104 }
105 105
106 106 if (PyDict_SetItem(mfdict, file, node) == -1)
107 107 goto bail;
108 108
109 109 start = cur + 1;
110 110 zero = NULL;
111 111
112 112 Py_XDECREF(flags);
113 113 Py_XDECREF(node);
114 114 Py_XDECREF(file);
115 115 continue;
116 116 bail:
117 117 Py_XDECREF(flags);
118 118 Py_XDECREF(node);
119 119 Py_XDECREF(file);
120 120 goto quit;
121 121 }
122 122
123 123 if (len > 0 && *(cur - 1) != '\n') {
124 124 PyErr_SetString(PyExc_ValueError,
125 125 "manifest contains trailing garbage");
126 126 goto quit;
127 127 }
128 128
129 129 Py_INCREF(Py_None);
130 130 return Py_None;
131 131 quit:
132 132 return NULL;
133 133 }
134 134
135 135 #ifdef _WIN32
136 136 # ifdef _MSC_VER
137 137 /* msvc 6.0 has problems */
138 138 # define inline __inline
139 139 typedef unsigned long uint32_t;
140 140 typedef unsigned __int64 uint64_t;
141 141 # else
142 142 # include <stdint.h>
143 143 # endif
144 144 static uint32_t ntohl(uint32_t x)
145 145 {
146 146 return ((x & 0x000000ffUL) << 24) |
147 ((x & 0x0000ff00UL) << 8) |
148 ((x & 0x00ff0000UL) >> 8) |
149 ((x & 0xff000000UL) >> 24);
147 ((x & 0x0000ff00UL) << 8) |
148 ((x & 0x00ff0000UL) >> 8) |
149 ((x & 0xff000000UL) >> 24);
150 150 }
151 151 #else
152 152 /* not windows */
153 153 # include <sys/types.h>
154 154 # if defined __BEOS__ && !defined __HAIKU__
155 155 # include <ByteOrder.h>
156 156 # else
157 157 # include <arpa/inet.h>
158 158 # endif
159 159 # include <inttypes.h>
160 160 #endif
161 161
162 162 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
163 163 {
164 164 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
165 165 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
166 166 char *str, *cur, *end, *cpos;
167 167 int state, mode, size, mtime;
168 168 unsigned int flen;
169 169 int len;
170 170 char decode[16]; /* for alignment */
171 171
172 172 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
173 173 &PyDict_Type, &dmap,
174 174 &PyDict_Type, &cmap,
175 175 &str, &len))
176 176 goto quit;
177 177
178 178 /* read parents */
179 179 if (len < 40)
180 180 goto quit;
181 181
182 182 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
183 183 if (!parents)
184 184 goto quit;
185 185
186 186 /* read filenames */
187 187 cur = str + 40;
188 188 end = str + len;
189 189
190 190 while (cur < end - 17) {
191 191 /* unpack header */
192 192 state = *cur;
193 193 memcpy(decode, cur + 1, 16);
194 194 mode = ntohl(*(uint32_t *)(decode));
195 195 size = ntohl(*(uint32_t *)(decode + 4));
196 196 mtime = ntohl(*(uint32_t *)(decode + 8));
197 197 flen = ntohl(*(uint32_t *)(decode + 12));
198 198 cur += 17;
199 199 if (flen > end - cur) {
200 200 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
201 201 goto quit;
202 202 }
203 203
204 204 entry = Py_BuildValue("ciii", state, mode, size, mtime);
205 205 if (!entry)
206 206 goto quit;
207 207 PyObject_GC_UnTrack(entry); /* don't waste time with this */
208 208
209 209 cpos = memchr(cur, 0, flen);
210 210 if (cpos) {
211 211 fname = PyString_FromStringAndSize(cur, cpos - cur);
212 212 cname = PyString_FromStringAndSize(cpos + 1,
213 213 flen - (cpos - cur) - 1);
214 214 if (!fname || !cname ||
215 215 PyDict_SetItem(cmap, fname, cname) == -1 ||
216 216 PyDict_SetItem(dmap, fname, entry) == -1)
217 217 goto quit;
218 218 Py_DECREF(cname);
219 219 } else {
220 220 fname = PyString_FromStringAndSize(cur, flen);
221 221 if (!fname ||
222 222 PyDict_SetItem(dmap, fname, entry) == -1)
223 223 goto quit;
224 224 }
225 225 cur += flen;
226 226 Py_DECREF(fname);
227 227 Py_DECREF(entry);
228 228 fname = cname = entry = NULL;
229 229 }
230 230
231 231 ret = parents;
232 232 Py_INCREF(ret);
233 233 quit:
234 234 Py_XDECREF(fname);
235 235 Py_XDECREF(cname);
236 236 Py_XDECREF(entry);
237 237 Py_XDECREF(parents);
238 238 return ret;
239 239 }
240 240
241 241 const char nullid[20];
242 242 const int nullrev = -1;
243 243
244 244 /* create an index tuple, insert into the nodemap */
245 245 static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags,
246 246 int comp_len, int uncomp_len, int base_rev,
247 247 int link_rev, int parent_1, int parent_2,
248 248 const char *c_node_id)
249 249 {
250 250 int err;
251 251 PyObject *entry, *node_id, *n_obj;
252 252
253 253 node_id = PyString_FromStringAndSize(c_node_id, 20);
254 254 n_obj = PyInt_FromLong(n);
255 255 if (!node_id || !n_obj)
256 256 err = -1;
257 257 else
258 258 err = PyDict_SetItem(nodemap, node_id, n_obj);
259 259
260 260 Py_XDECREF(n_obj);
261 261 if (err)
262 262 goto error_dealloc;
263 263
264 264 entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len,
265 265 uncomp_len, base_rev, link_rev,
266 266 parent_1, parent_2, node_id);
267 267 if (!entry)
268 268 goto error_dealloc;
269 269 PyObject_GC_UnTrack(entry); /* don't waste time with this */
270 270
271 271 return entry;
272 272
273 273 error_dealloc:
274 274 Py_XDECREF(node_id);
275 275 return NULL;
276 276 }
277 277
278 278 /* RevlogNG format (all in big endian, data may be inlined):
279 279 * 6 bytes: offset
280 280 * 2 bytes: flags
281 281 * 4 bytes: compressed length
282 282 * 4 bytes: uncompressed length
283 283 * 4 bytes: base revision
284 284 * 4 bytes: link revision
285 285 * 4 bytes: parent 1 revision
286 286 * 4 bytes: parent 2 revision
287 287 * 32 bytes: nodeid (only 20 bytes used)
288 288 */
289 289 static int _parse_index_ng (const char *data, int size, int inlined,
290 290 PyObject *index, PyObject *nodemap)
291 291 {
292 292 PyObject *entry;
293 293 int n = 0, err;
294 294 uint64_t offset_flags;
295 295 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
296 296 const char *c_node_id;
297 297 const char *end = data + size;
298 298 char decode[64]; /* to enforce alignment with inline data */
299 299
300 300 while (data < end) {
301 301 unsigned int step;
302
302
303 303 memcpy(decode, data, 64);
304 304 offset_flags = ntohl(*((uint32_t *) (decode + 4)));
305 305 if (n == 0) /* mask out version number for the first entry */
306 306 offset_flags &= 0xFFFF;
307 307 else {
308 308 uint32_t offset_high = ntohl(*((uint32_t *) decode));
309 309 offset_flags |= ((uint64_t) offset_high) << 32;
310 310 }
311 311
312 312 comp_len = ntohl(*((uint32_t *) (decode + 8)));
313 313 uncomp_len = ntohl(*((uint32_t *) (decode + 12)));
314 314 base_rev = ntohl(*((uint32_t *) (decode + 16)));
315 315 link_rev = ntohl(*((uint32_t *) (decode + 20)));
316 316 parent_1 = ntohl(*((uint32_t *) (decode + 24)));
317 317 parent_2 = ntohl(*((uint32_t *) (decode + 28)));
318 318 c_node_id = decode + 32;
319 319
320 320 entry = _build_idx_entry(nodemap, n, offset_flags,
321 321 comp_len, uncomp_len, base_rev,
322 322 link_rev, parent_1, parent_2,
323 323 c_node_id);
324 324 if (!entry)
325 325 return 0;
326 326
327 327 if (inlined) {
328 328 err = PyList_Append(index, entry);
329 329 Py_DECREF(entry);
330 330 if (err)
331 331 return 0;
332 332 } else
333 333 PyList_SET_ITEM(index, n, entry); /* steals reference */
334 334
335 335 n++;
336 336 step = 64 + (inlined ? comp_len : 0);
337 337 if (end - data < step)
338 338 break;
339 339 data += step;
340 340 }
341 341 if (data != end) {
342 342 if (!PyErr_Occurred())
343 343 PyErr_SetString(PyExc_ValueError, "corrupt index file");
344 344 return 0;
345 345 }
346 346
347 /* create the nullid/nullrev entry in the nodemap and the
347 /* create the nullid/nullrev entry in the nodemap and the
348 348 * magic nullid entry in the index at [-1] */
349 entry = _build_idx_entry(nodemap,
349 entry = _build_idx_entry(nodemap,
350 350 nullrev, 0, 0, 0, -1, -1, -1, -1, nullid);
351 351 if (!entry)
352 352 return 0;
353 353 if (inlined) {
354 354 err = PyList_Append(index, entry);
355 355 Py_DECREF(entry);
356 356 if (err)
357 357 return 0;
358 358 } else
359 359 PyList_SET_ITEM(index, n, entry); /* steals reference */
360 360
361 361 return 1;
362 362 }
363 363
364 364 /* This function parses a index file and returns a Python tuple of the
365 365 * following format: (index, nodemap, cache)
366 366 *
367 367 * index: a list of tuples containing the RevlogNG records
368 368 * nodemap: a dict mapping node ids to indices in the index list
369 369 * cache: if data is inlined, a tuple (index_file_content, 0) else None
370 370 */
371 371 static PyObject *parse_index(PyObject *self, PyObject *args)
372 372 {
373 373 const char *data;
374 374 int size, inlined;
375 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
375 PyObject *rval = NULL, *index = NULL, *nodemap = NULL, *cache = NULL;
376 376 PyObject *data_obj = NULL, *inlined_obj;
377 377
378 378 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
379 379 return NULL;
380 380 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
381 381
382 /* If no data is inlined, we know the size of the index list in
383 * advance: size divided by size of one one revlog record (64 bytes)
384 * plus one for the nullid */
382 /* If no data is inlined, we know the size of the index list in
383 * advance: size divided by size of one one revlog record (64 bytes)
384 * plus one for the nullid */
385 385 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
386 386 if (!index)
387 387 goto quit;
388 388
389 389 nodemap = PyDict_New();
390 390 if (!nodemap)
391 391 goto quit;
392 392
393 393 /* set up the cache return value */
394 394 if (inlined) {
395 395 /* Note that the reference to data_obj is only borrowed */
396 396 data_obj = PyTuple_GET_ITEM(args, 0);
397 397 cache = Py_BuildValue("iO", 0, data_obj);
398 398 if (!cache)
399 399 goto quit;
400 400 } else {
401 401 cache = Py_None;
402 402 Py_INCREF(Py_None);
403 403 }
404 404
405 405 /* actually populate the index and the nodemap with data */
406 406 if (!_parse_index_ng (data, size, inlined, index, nodemap))
407 407 goto quit;
408 408
409 409 rval = Py_BuildValue("NNN", index, nodemap, cache);
410 410 if (!rval)
411 411 goto quit;
412 412 return rval;
413 413
414 414 quit:
415 415 Py_XDECREF(index);
416 416 Py_XDECREF(nodemap);
417 417 Py_XDECREF(cache);
418 418 Py_XDECREF(rval);
419 419 return NULL;
420 420 }
421 421
422 422
423 423 static char parsers_doc[] = "Efficient content parsing.";
424 424
425 425 static PyMethodDef methods[] = {
426 426 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
427 427 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
428 428 {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"},
429 429 {NULL, NULL}
430 430 };
431 431
432 432 PyMODINIT_FUNC initparsers(void)
433 433 {
434 434 Py_InitModule3("parsers", methods, parsers_doc);
435 435 }
@@ -1,41 +1,41 b''
1 1 # strutil.py - string utilities for Mercurial
2 2 #
3 3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 def findall(haystack, needle, start=0, end=None):
9 9 if end is None:
10 10 end = len(haystack)
11 11 if end < 0:
12 12 end += len(haystack)
13 13 if start < 0:
14 14 start += len(haystack)
15 15 while start < end:
16 16 c = haystack.find(needle, start, end)
17 17 if c == -1:
18 18 break
19 19 yield c
20 20 start = c + 1
21 21
22 22 def rfindall(haystack, needle, start=0, end=None):
23 23 if end is None:
24 24 end = len(haystack)
25 25 if end < 0:
26 26 end += len(haystack)
27 27 if start < 0:
28 28 start += len(haystack)
29 29 while end >= 0:
30 30 c = haystack.rfind(needle, start, end)
31 31 if c == -1:
32 32 break
33 33 yield c
34 34 end = c - 1
35 35
36 36 def rsplit(s, sep=None, maxsplit=-1):
37 37 try:
38 38 return s.rsplit(sep, maxsplit)
39 39 except AttributeError:
40 return [chunk[::-1] for chunk in
41 s[::-1].split(sep, maxsplit)[::-1]]
40 return [chunk[::-1] for chunk in
41 s[::-1].split(sep, maxsplit)[::-1]]
General Comments 0
You need to be logged in to leave comments. Login now