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