##// END OF EJS Templates
rust-dirstate: add rust-cpython bindings to the new parse/pack functions...
Raphaël Gomès -
r42489:e240bec2 default
parent child Browse files
Show More
@@ -0,0 +1,227 b''
1 // dirstate.rs
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
7
8 //! Bindings for the `hg::dirstate` module provided by the
9 //! `hg-core` package.
10 //!
11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
12
13 use cpython::{
14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyObject, PyResult,
15 PySequence, PyTuple, Python, ToPyObject,
16 };
17 use hg::{
18 pack_dirstate, parse_dirstate, CopyVecEntry, DirstateEntry,
19 DirstatePackError, DirstateParents, DirstateParseError, DirstateVec,
20 };
21 use std::collections::HashMap;
22 use std::ffi::CStr;
23 #[cfg(feature = "python27")]
24 extern crate python27_sys as python_sys;
25 #[cfg(feature = "python3")]
26 extern crate python3_sys as python_sys;
27 use self::python_sys::PyCapsule_Import;
28 use libc::{c_char, c_int};
29 use std::mem::transmute;
30
31 /// C code uses a custom `dirstate_tuple` type, checks in multiple instances
32 /// for this type, and raises a Python `Exception` if the check does not pass.
33 /// Because this type differs only in name from the regular Python tuple, it
34 /// would be a good idea in the near future to remove it entirely to allow
35 /// for a pure Python tuple of the same effective structure to be used,
36 /// rendering this type and the capsule below useless.
37 type MakeDirstateTupleFn = extern "C" fn(
38 state: c_char,
39 mode: c_int,
40 size: c_int,
41 mtime: c_int,
42 ) -> PyObject;
43
44 /// This is largely a copy/paste from cindex.rs, pending the merge of a
45 /// `py_capsule_fn!` macro in the rust-cpython project:
46 /// https://github.com/dgrunwald/rust-cpython/pull/169
47 fn decapsule_make_dirstate_tuple(py: Python) -> PyResult<MakeDirstateTupleFn> {
48 unsafe {
49 let caps_name = CStr::from_bytes_with_nul_unchecked(
50 b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0",
51 );
52 let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
53 if from_caps.is_null() {
54 return Err(PyErr::fetch(py));
55 }
56 Ok(transmute(from_caps))
57 }
58 }
59
60 fn parse_dirstate_wrapper(
61 py: Python,
62 dmap: PyDict,
63 copymap: PyDict,
64 st: PyBytes,
65 ) -> PyResult<PyTuple> {
66 match parse_dirstate(st.data(py)) {
67 Ok((parents, dirstate_vec, copies)) => {
68 for (filename, entry) in dirstate_vec {
69 dmap.set_item(
70 py,
71 PyBytes::new(py, &filename[..]),
72 decapsule_make_dirstate_tuple(py)?(
73 entry.state,
74 entry.mode,
75 entry.size,
76 entry.mtime,
77 ),
78 )?;
79 }
80 for CopyVecEntry { path, copy_path } in copies {
81 copymap.set_item(
82 py,
83 PyBytes::new(py, path),
84 PyBytes::new(py, copy_path),
85 )?;
86 }
87 Ok((PyBytes::new(py, parents.p1), PyBytes::new(py, parents.p2))
88 .to_py_object(py))
89 }
90 Err(e) => Err(PyErr::new::<exc::ValueError, _>(
91 py,
92 match e {
93 DirstateParseError::TooLittleData => {
94 "too little data for parents".to_string()
95 }
96 DirstateParseError::Overflow => {
97 "overflow in dirstate".to_string()
98 }
99 DirstateParseError::CorruptedEntry(e) => e,
100 },
101 )),
102 }
103 }
104
105 fn pack_dirstate_wrapper(
106 py: Python,
107 dmap: PyDict,
108 copymap: PyDict,
109 pl: PyTuple,
110 now: PyInt,
111 ) -> PyResult<PyBytes> {
112 let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?;
113 let p1: &[u8] = p1.data(py);
114 let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?;
115 let p2: &[u8] = p2.data(py);
116
117 let dirstate_vec: Result<DirstateVec, PyErr> = dmap
118 .items(py)
119 .iter()
120 .map(|(filename, stats)| {
121 let stats = stats.extract::<PySequence>(py)?;
122 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
123 let state = state.data(py)[0] as i8;
124 let mode = stats.get_item(py, 1)?.extract(py)?;
125 let size = stats.get_item(py, 2)?.extract(py)?;
126 let mtime = stats.get_item(py, 3)?.extract(py)?;
127 let filename = filename.extract::<PyBytes>(py)?;
128 let filename = filename.data(py);
129 Ok((
130 filename.to_owned(),
131 DirstateEntry {
132 state,
133 mode,
134 size,
135 mtime,
136 },
137 ))
138 })
139 .collect();
140
141 let copies: Result<HashMap<Vec<u8>, Vec<u8>>, PyErr> = copymap
142 .items(py)
143 .iter()
144 .map(|(key, value)| {
145 Ok((
146 key.extract::<PyBytes>(py)?.data(py).to_owned(),
147 value.extract::<PyBytes>(py)?.data(py).to_owned(),
148 ))
149 })
150 .collect();
151
152 match pack_dirstate(
153 &dirstate_vec?,
154 &copies?,
155 DirstateParents { p1, p2 },
156 now.value(py) as i32,
157 ) {
158 Ok((packed, new_dirstate_vec)) => {
159 for (
160 filename,
161 DirstateEntry {
162 state,
163 mode,
164 size,
165 mtime,
166 },
167 ) in new_dirstate_vec
168 {
169 dmap.set_item(
170 py,
171 PyBytes::new(py, &filename[..]),
172 decapsule_make_dirstate_tuple(py)?(
173 state, mode, size, mtime,
174 ),
175 )?;
176 }
177 Ok(PyBytes::new(py, &packed))
178 }
179 Err(error) => Err(PyErr::new::<exc::ValueError, _>(
180 py,
181 match error {
182 DirstatePackError::CorruptedParent => {
183 "expected a 20-byte hash".to_string()
184 }
185 DirstatePackError::CorruptedEntry(e) => e,
186 DirstatePackError::BadSize(expected, actual) => {
187 format!("bad dirstate size: {} != {}", actual, expected)
188 }
189 },
190 )),
191 }
192 }
193
194 /// Create the module, with `__package__` given from parent
195 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
196 let dotted_name = &format!("{}.dirstate", package);
197 let m = PyModule::new(py, dotted_name)?;
198 m.add(py, "__package__", package)?;
199 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
200 m.add(
201 py,
202 "parse_dirstate",
203 py_fn!(
204 py,
205 parse_dirstate_wrapper(dmap: PyDict, copymap: PyDict, st: PyBytes)
206 ),
207 )?;
208 m.add(
209 py,
210 "pack_dirstate",
211 py_fn!(
212 py,
213 pack_dirstate_wrapper(
214 dmap: PyDict,
215 copymap: PyDict,
216 pl: PyTuple,
217 now: PyInt
218 )
219 ),
220 )?;
221
222 let sys = PyModule::import(py, "sys")?;
223 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
224 sys_modules.set_item(py, dotted_name, &m)?;
225
226 Ok(m)
227 }
@@ -1,755 +1,762 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 #define PY_SSIZE_T_CLEAN
10 #define PY_SSIZE_T_CLEAN
11 #include <Python.h>
11 #include <Python.h>
12 #include <ctype.h>
12 #include <ctype.h>
13 #include <stddef.h>
13 #include <stddef.h>
14 #include <string.h>
14 #include <string.h>
15
15
16 #include "bitmanipulation.h"
16 #include "bitmanipulation.h"
17 #include "charencode.h"
17 #include "charencode.h"
18 #include "util.h"
18 #include "util.h"
19
19
20 #ifdef IS_PY3K
20 #ifdef IS_PY3K
21 /* The mapping of Python types is meant to be temporary to get Python
21 /* The mapping of Python types is meant to be temporary to get Python
22 * 3 to compile. We should remove this once Python 3 support is fully
22 * 3 to compile. We should remove this once Python 3 support is fully
23 * supported and proper types are used in the extensions themselves. */
23 * supported and proper types are used in the extensions themselves. */
24 #define PyInt_Check PyLong_Check
24 #define PyInt_Check PyLong_Check
25 #define PyInt_FromLong PyLong_FromLong
25 #define PyInt_FromLong PyLong_FromLong
26 #define PyInt_FromSsize_t PyLong_FromSsize_t
26 #define PyInt_FromSsize_t PyLong_FromSsize_t
27 #define PyInt_AsLong PyLong_AsLong
27 #define PyInt_AsLong PyLong_AsLong
28 #endif
28 #endif
29
29
30 static const char *const versionerrortext = "Python minor version mismatch";
30 static const char *const versionerrortext = "Python minor version mismatch";
31
31
32 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
32 static PyObject *dict_new_presized(PyObject *self, PyObject *args)
33 {
33 {
34 Py_ssize_t expected_size;
34 Py_ssize_t expected_size;
35
35
36 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size)) {
36 if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size)) {
37 return NULL;
37 return NULL;
38 }
38 }
39
39
40 return _dict_new_presized(expected_size);
40 return _dict_new_presized(expected_size);
41 }
41 }
42
42
43 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
43 static inline dirstateTupleObject *make_dirstate_tuple(char state, int mode,
44 int size, int mtime)
44 int size, int mtime)
45 {
45 {
46 dirstateTupleObject *t =
46 dirstateTupleObject *t =
47 PyObject_New(dirstateTupleObject, &dirstateTupleType);
47 PyObject_New(dirstateTupleObject, &dirstateTupleType);
48 if (!t) {
48 if (!t) {
49 return NULL;
49 return NULL;
50 }
50 }
51 t->state = state;
51 t->state = state;
52 t->mode = mode;
52 t->mode = mode;
53 t->size = size;
53 t->size = size;
54 t->mtime = mtime;
54 t->mtime = mtime;
55 return t;
55 return t;
56 }
56 }
57
57
58 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
58 static PyObject *dirstate_tuple_new(PyTypeObject *subtype, PyObject *args,
59 PyObject *kwds)
59 PyObject *kwds)
60 {
60 {
61 /* We do all the initialization here and not a tp_init function because
61 /* We do all the initialization here and not a tp_init function because
62 * dirstate_tuple is immutable. */
62 * dirstate_tuple is immutable. */
63 dirstateTupleObject *t;
63 dirstateTupleObject *t;
64 char state;
64 char state;
65 int size, mode, mtime;
65 int size, mode, mtime;
66 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime)) {
66 if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime)) {
67 return NULL;
67 return NULL;
68 }
68 }
69
69
70 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
70 t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1);
71 if (!t) {
71 if (!t) {
72 return NULL;
72 return NULL;
73 }
73 }
74 t->state = state;
74 t->state = state;
75 t->mode = mode;
75 t->mode = mode;
76 t->size = size;
76 t->size = size;
77 t->mtime = mtime;
77 t->mtime = mtime;
78
78
79 return (PyObject *)t;
79 return (PyObject *)t;
80 }
80 }
81
81
82 static void dirstate_tuple_dealloc(PyObject *o)
82 static void dirstate_tuple_dealloc(PyObject *o)
83 {
83 {
84 PyObject_Del(o);
84 PyObject_Del(o);
85 }
85 }
86
86
87 static Py_ssize_t dirstate_tuple_length(PyObject *o)
87 static Py_ssize_t dirstate_tuple_length(PyObject *o)
88 {
88 {
89 return 4;
89 return 4;
90 }
90 }
91
91
92 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
92 static PyObject *dirstate_tuple_item(PyObject *o, Py_ssize_t i)
93 {
93 {
94 dirstateTupleObject *t = (dirstateTupleObject *)o;
94 dirstateTupleObject *t = (dirstateTupleObject *)o;
95 switch (i) {
95 switch (i) {
96 case 0:
96 case 0:
97 return PyBytes_FromStringAndSize(&t->state, 1);
97 return PyBytes_FromStringAndSize(&t->state, 1);
98 case 1:
98 case 1:
99 return PyInt_FromLong(t->mode);
99 return PyInt_FromLong(t->mode);
100 case 2:
100 case 2:
101 return PyInt_FromLong(t->size);
101 return PyInt_FromLong(t->size);
102 case 3:
102 case 3:
103 return PyInt_FromLong(t->mtime);
103 return PyInt_FromLong(t->mtime);
104 default:
104 default:
105 PyErr_SetString(PyExc_IndexError, "index out of range");
105 PyErr_SetString(PyExc_IndexError, "index out of range");
106 return NULL;
106 return NULL;
107 }
107 }
108 }
108 }
109
109
110 static PySequenceMethods dirstate_tuple_sq = {
110 static PySequenceMethods dirstate_tuple_sq = {
111 dirstate_tuple_length, /* sq_length */
111 dirstate_tuple_length, /* sq_length */
112 0, /* sq_concat */
112 0, /* sq_concat */
113 0, /* sq_repeat */
113 0, /* sq_repeat */
114 dirstate_tuple_item, /* sq_item */
114 dirstate_tuple_item, /* sq_item */
115 0, /* sq_ass_item */
115 0, /* sq_ass_item */
116 0, /* sq_contains */
116 0, /* sq_contains */
117 0, /* sq_inplace_concat */
117 0, /* sq_inplace_concat */
118 0 /* sq_inplace_repeat */
118 0 /* sq_inplace_repeat */
119 };
119 };
120
120
121 PyTypeObject dirstateTupleType = {
121 PyTypeObject dirstateTupleType = {
122 PyVarObject_HEAD_INIT(NULL, 0) /* header */
122 PyVarObject_HEAD_INIT(NULL, 0) /* header */
123 "dirstate_tuple", /* tp_name */
123 "dirstate_tuple", /* tp_name */
124 sizeof(dirstateTupleObject), /* tp_basicsize */
124 sizeof(dirstateTupleObject), /* tp_basicsize */
125 0, /* tp_itemsize */
125 0, /* tp_itemsize */
126 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
126 (destructor)dirstate_tuple_dealloc, /* tp_dealloc */
127 0, /* tp_print */
127 0, /* tp_print */
128 0, /* tp_getattr */
128 0, /* tp_getattr */
129 0, /* tp_setattr */
129 0, /* tp_setattr */
130 0, /* tp_compare */
130 0, /* tp_compare */
131 0, /* tp_repr */
131 0, /* tp_repr */
132 0, /* tp_as_number */
132 0, /* tp_as_number */
133 &dirstate_tuple_sq, /* tp_as_sequence */
133 &dirstate_tuple_sq, /* tp_as_sequence */
134 0, /* tp_as_mapping */
134 0, /* tp_as_mapping */
135 0, /* tp_hash */
135 0, /* tp_hash */
136 0, /* tp_call */
136 0, /* tp_call */
137 0, /* tp_str */
137 0, /* tp_str */
138 0, /* tp_getattro */
138 0, /* tp_getattro */
139 0, /* tp_setattro */
139 0, /* tp_setattro */
140 0, /* tp_as_buffer */
140 0, /* tp_as_buffer */
141 Py_TPFLAGS_DEFAULT, /* tp_flags */
141 Py_TPFLAGS_DEFAULT, /* tp_flags */
142 "dirstate tuple", /* tp_doc */
142 "dirstate tuple", /* tp_doc */
143 0, /* tp_traverse */
143 0, /* tp_traverse */
144 0, /* tp_clear */
144 0, /* tp_clear */
145 0, /* tp_richcompare */
145 0, /* tp_richcompare */
146 0, /* tp_weaklistoffset */
146 0, /* tp_weaklistoffset */
147 0, /* tp_iter */
147 0, /* tp_iter */
148 0, /* tp_iternext */
148 0, /* tp_iternext */
149 0, /* tp_methods */
149 0, /* tp_methods */
150 0, /* tp_members */
150 0, /* tp_members */
151 0, /* tp_getset */
151 0, /* tp_getset */
152 0, /* tp_base */
152 0, /* tp_base */
153 0, /* tp_dict */
153 0, /* tp_dict */
154 0, /* tp_descr_get */
154 0, /* tp_descr_get */
155 0, /* tp_descr_set */
155 0, /* tp_descr_set */
156 0, /* tp_dictoffset */
156 0, /* tp_dictoffset */
157 0, /* tp_init */
157 0, /* tp_init */
158 0, /* tp_alloc */
158 0, /* tp_alloc */
159 dirstate_tuple_new, /* tp_new */
159 dirstate_tuple_new, /* tp_new */
160 };
160 };
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 state, *cur, *str, *cpos;
166 char state, *cur, *str, *cpos;
167 int mode, size, mtime;
167 int mode, size, mtime;
168 unsigned int flen, pos = 40;
168 unsigned int flen, pos = 40;
169 Py_ssize_t len = 40;
169 Py_ssize_t len = 40;
170 Py_ssize_t readlen;
170 Py_ssize_t readlen;
171
171
172 if (!PyArg_ParseTuple(
172 if (!PyArg_ParseTuple(
173 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
173 args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"),
174 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) {
174 &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) {
175 goto quit;
175 goto quit;
176 }
176 }
177
177
178 len = readlen;
178 len = readlen;
179
179
180 /* read parents */
180 /* read parents */
181 if (len < 40) {
181 if (len < 40) {
182 PyErr_SetString(PyExc_ValueError,
182 PyErr_SetString(PyExc_ValueError,
183 "too little data for parents");
183 "too little data for parents");
184 goto quit;
184 goto quit;
185 }
185 }
186
186
187 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, (Py_ssize_t)20,
187 parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, (Py_ssize_t)20,
188 str + 20, (Py_ssize_t)20);
188 str + 20, (Py_ssize_t)20);
189 if (!parents) {
189 if (!parents) {
190 goto quit;
190 goto quit;
191 }
191 }
192
192
193 /* read filenames */
193 /* read filenames */
194 while (pos >= 40 && pos < len) {
194 while (pos >= 40 && pos < len) {
195 if (pos + 17 > len) {
195 if (pos + 17 > len) {
196 PyErr_SetString(PyExc_ValueError,
196 PyErr_SetString(PyExc_ValueError,
197 "overflow in dirstate");
197 "overflow in dirstate");
198 goto quit;
198 goto quit;
199 }
199 }
200 cur = str + pos;
200 cur = str + pos;
201 /* unpack header */
201 /* unpack header */
202 state = *cur;
202 state = *cur;
203 mode = getbe32(cur + 1);
203 mode = getbe32(cur + 1);
204 size = getbe32(cur + 5);
204 size = getbe32(cur + 5);
205 mtime = getbe32(cur + 9);
205 mtime = getbe32(cur + 9);
206 flen = getbe32(cur + 13);
206 flen = getbe32(cur + 13);
207 pos += 17;
207 pos += 17;
208 cur += 17;
208 cur += 17;
209 if (flen > len - pos) {
209 if (flen > len - pos) {
210 PyErr_SetString(PyExc_ValueError,
210 PyErr_SetString(PyExc_ValueError,
211 "overflow in dirstate");
211 "overflow in dirstate");
212 goto quit;
212 goto quit;
213 }
213 }
214
214
215 entry =
215 entry =
216 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
216 (PyObject *)make_dirstate_tuple(state, mode, size, mtime);
217 cpos = memchr(cur, 0, flen);
217 cpos = memchr(cur, 0, flen);
218 if (cpos) {
218 if (cpos) {
219 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
219 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
220 cname = PyBytes_FromStringAndSize(
220 cname = PyBytes_FromStringAndSize(
221 cpos + 1, flen - (cpos - cur) - 1);
221 cpos + 1, flen - (cpos - cur) - 1);
222 if (!fname || !cname ||
222 if (!fname || !cname ||
223 PyDict_SetItem(cmap, fname, cname) == -1 ||
223 PyDict_SetItem(cmap, fname, cname) == -1 ||
224 PyDict_SetItem(dmap, fname, entry) == -1) {
224 PyDict_SetItem(dmap, fname, entry) == -1) {
225 goto quit;
225 goto quit;
226 }
226 }
227 Py_DECREF(cname);
227 Py_DECREF(cname);
228 } else {
228 } else {
229 fname = PyBytes_FromStringAndSize(cur, flen);
229 fname = PyBytes_FromStringAndSize(cur, flen);
230 if (!fname ||
230 if (!fname ||
231 PyDict_SetItem(dmap, fname, entry) == -1) {
231 PyDict_SetItem(dmap, fname, entry) == -1) {
232 goto quit;
232 goto quit;
233 }
233 }
234 }
234 }
235 Py_DECREF(fname);
235 Py_DECREF(fname);
236 Py_DECREF(entry);
236 Py_DECREF(entry);
237 fname = cname = entry = NULL;
237 fname = cname = entry = NULL;
238 pos += flen;
238 pos += flen;
239 }
239 }
240
240
241 ret = parents;
241 ret = parents;
242 Py_INCREF(ret);
242 Py_INCREF(ret);
243 quit:
243 quit:
244 Py_XDECREF(fname);
244 Py_XDECREF(fname);
245 Py_XDECREF(cname);
245 Py_XDECREF(cname);
246 Py_XDECREF(entry);
246 Py_XDECREF(entry);
247 Py_XDECREF(parents);
247 Py_XDECREF(parents);
248 return ret;
248 return ret;
249 }
249 }
250
250
251 /*
251 /*
252 * Build a set of non-normal and other parent entries from the dirstate dmap
252 * Build a set of non-normal and other parent entries from the dirstate dmap
253 */
253 */
254 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
254 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
255 {
255 {
256 PyObject *dmap, *fname, *v;
256 PyObject *dmap, *fname, *v;
257 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
257 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
258 Py_ssize_t pos;
258 Py_ssize_t pos;
259
259
260 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type,
260 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type,
261 &dmap)) {
261 &dmap)) {
262 goto bail;
262 goto bail;
263 }
263 }
264
264
265 nonnset = PySet_New(NULL);
265 nonnset = PySet_New(NULL);
266 if (nonnset == NULL) {
266 if (nonnset == NULL) {
267 goto bail;
267 goto bail;
268 }
268 }
269
269
270 otherpset = PySet_New(NULL);
270 otherpset = PySet_New(NULL);
271 if (otherpset == NULL) {
271 if (otherpset == NULL) {
272 goto bail;
272 goto bail;
273 }
273 }
274
274
275 pos = 0;
275 pos = 0;
276 while (PyDict_Next(dmap, &pos, &fname, &v)) {
276 while (PyDict_Next(dmap, &pos, &fname, &v)) {
277 dirstateTupleObject *t;
277 dirstateTupleObject *t;
278 if (!dirstate_tuple_check(v)) {
278 if (!dirstate_tuple_check(v)) {
279 PyErr_SetString(PyExc_TypeError,
279 PyErr_SetString(PyExc_TypeError,
280 "expected a dirstate tuple");
280 "expected a dirstate tuple");
281 goto bail;
281 goto bail;
282 }
282 }
283 t = (dirstateTupleObject *)v;
283 t = (dirstateTupleObject *)v;
284
284
285 if (t->state == 'n' && t->size == -2) {
285 if (t->state == 'n' && t->size == -2) {
286 if (PySet_Add(otherpset, fname) == -1) {
286 if (PySet_Add(otherpset, fname) == -1) {
287 goto bail;
287 goto bail;
288 }
288 }
289 }
289 }
290
290
291 if (t->state == 'n' && t->mtime != -1) {
291 if (t->state == 'n' && t->mtime != -1) {
292 continue;
292 continue;
293 }
293 }
294 if (PySet_Add(nonnset, fname) == -1) {
294 if (PySet_Add(nonnset, fname) == -1) {
295 goto bail;
295 goto bail;
296 }
296 }
297 }
297 }
298
298
299 result = Py_BuildValue("(OO)", nonnset, otherpset);
299 result = Py_BuildValue("(OO)", nonnset, otherpset);
300 if (result == NULL) {
300 if (result == NULL) {
301 goto bail;
301 goto bail;
302 }
302 }
303 Py_DECREF(nonnset);
303 Py_DECREF(nonnset);
304 Py_DECREF(otherpset);
304 Py_DECREF(otherpset);
305 return result;
305 return result;
306 bail:
306 bail:
307 Py_XDECREF(nonnset);
307 Py_XDECREF(nonnset);
308 Py_XDECREF(otherpset);
308 Py_XDECREF(otherpset);
309 Py_XDECREF(result);
309 Py_XDECREF(result);
310 return NULL;
310 return NULL;
311 }
311 }
312
312
313 /*
313 /*
314 * Efficiently pack a dirstate object into its on-disk format.
314 * Efficiently pack a dirstate object into its on-disk format.
315 */
315 */
316 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
316 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
317 {
317 {
318 PyObject *packobj = NULL;
318 PyObject *packobj = NULL;
319 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
319 PyObject *map, *copymap, *pl, *mtime_unset = NULL;
320 Py_ssize_t nbytes, pos, l;
320 Py_ssize_t nbytes, pos, l;
321 PyObject *k, *v = NULL, *pn;
321 PyObject *k, *v = NULL, *pn;
322 char *p, *s;
322 char *p, *s;
323 int now;
323 int now;
324
324
325 if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
325 if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map,
326 &PyDict_Type, &copymap, &PyTuple_Type, &pl,
326 &PyDict_Type, &copymap, &PyTuple_Type, &pl,
327 &now)) {
327 &now)) {
328 return NULL;
328 return NULL;
329 }
329 }
330
330
331 if (PyTuple_Size(pl) != 2) {
331 if (PyTuple_Size(pl) != 2) {
332 PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
332 PyErr_SetString(PyExc_TypeError, "expected 2-element tuple");
333 return NULL;
333 return NULL;
334 }
334 }
335
335
336 /* Figure out how much we need to allocate. */
336 /* Figure out how much we need to allocate. */
337 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
337 for (nbytes = 40, pos = 0; PyDict_Next(map, &pos, &k, &v);) {
338 PyObject *c;
338 PyObject *c;
339 if (!PyBytes_Check(k)) {
339 if (!PyBytes_Check(k)) {
340 PyErr_SetString(PyExc_TypeError, "expected string key");
340 PyErr_SetString(PyExc_TypeError, "expected string key");
341 goto bail;
341 goto bail;
342 }
342 }
343 nbytes += PyBytes_GET_SIZE(k) + 17;
343 nbytes += PyBytes_GET_SIZE(k) + 17;
344 c = PyDict_GetItem(copymap, k);
344 c = PyDict_GetItem(copymap, k);
345 if (c) {
345 if (c) {
346 if (!PyBytes_Check(c)) {
346 if (!PyBytes_Check(c)) {
347 PyErr_SetString(PyExc_TypeError,
347 PyErr_SetString(PyExc_TypeError,
348 "expected string key");
348 "expected string key");
349 goto bail;
349 goto bail;
350 }
350 }
351 nbytes += PyBytes_GET_SIZE(c) + 1;
351 nbytes += PyBytes_GET_SIZE(c) + 1;
352 }
352 }
353 }
353 }
354
354
355 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
355 packobj = PyBytes_FromStringAndSize(NULL, nbytes);
356 if (packobj == NULL) {
356 if (packobj == NULL) {
357 goto bail;
357 goto bail;
358 }
358 }
359
359
360 p = PyBytes_AS_STRING(packobj);
360 p = PyBytes_AS_STRING(packobj);
361
361
362 pn = PyTuple_GET_ITEM(pl, 0);
362 pn = PyTuple_GET_ITEM(pl, 0);
363 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
363 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
364 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
364 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
365 goto bail;
365 goto bail;
366 }
366 }
367 memcpy(p, s, l);
367 memcpy(p, s, l);
368 p += 20;
368 p += 20;
369 pn = PyTuple_GET_ITEM(pl, 1);
369 pn = PyTuple_GET_ITEM(pl, 1);
370 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
370 if (PyBytes_AsStringAndSize(pn, &s, &l) == -1 || l != 20) {
371 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
371 PyErr_SetString(PyExc_TypeError, "expected a 20-byte hash");
372 goto bail;
372 goto bail;
373 }
373 }
374 memcpy(p, s, l);
374 memcpy(p, s, l);
375 p += 20;
375 p += 20;
376
376
377 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
377 for (pos = 0; PyDict_Next(map, &pos, &k, &v);) {
378 dirstateTupleObject *tuple;
378 dirstateTupleObject *tuple;
379 char state;
379 char state;
380 int mode, size, mtime;
380 int mode, size, mtime;
381 Py_ssize_t len, l;
381 Py_ssize_t len, l;
382 PyObject *o;
382 PyObject *o;
383 char *t;
383 char *t;
384
384
385 if (!dirstate_tuple_check(v)) {
385 if (!dirstate_tuple_check(v)) {
386 PyErr_SetString(PyExc_TypeError,
386 PyErr_SetString(PyExc_TypeError,
387 "expected a dirstate tuple");
387 "expected a dirstate tuple");
388 goto bail;
388 goto bail;
389 }
389 }
390 tuple = (dirstateTupleObject *)v;
390 tuple = (dirstateTupleObject *)v;
391
391
392 state = tuple->state;
392 state = tuple->state;
393 mode = tuple->mode;
393 mode = tuple->mode;
394 size = tuple->size;
394 size = tuple->size;
395 mtime = tuple->mtime;
395 mtime = tuple->mtime;
396 if (state == 'n' && mtime == now) {
396 if (state == 'n' && mtime == now) {
397 /* See pure/parsers.py:pack_dirstate for why we do
397 /* See pure/parsers.py:pack_dirstate for why we do
398 * this. */
398 * this. */
399 mtime = -1;
399 mtime = -1;
400 mtime_unset = (PyObject *)make_dirstate_tuple(
400 mtime_unset = (PyObject *)make_dirstate_tuple(
401 state, mode, size, mtime);
401 state, mode, size, mtime);
402 if (!mtime_unset) {
402 if (!mtime_unset) {
403 goto bail;
403 goto bail;
404 }
404 }
405 if (PyDict_SetItem(map, k, mtime_unset) == -1) {
405 if (PyDict_SetItem(map, k, mtime_unset) == -1) {
406 goto bail;
406 goto bail;
407 }
407 }
408 Py_DECREF(mtime_unset);
408 Py_DECREF(mtime_unset);
409 mtime_unset = NULL;
409 mtime_unset = NULL;
410 }
410 }
411 *p++ = state;
411 *p++ = state;
412 putbe32((uint32_t)mode, p);
412 putbe32((uint32_t)mode, p);
413 putbe32((uint32_t)size, p + 4);
413 putbe32((uint32_t)size, p + 4);
414 putbe32((uint32_t)mtime, p + 8);
414 putbe32((uint32_t)mtime, p + 8);
415 t = p + 12;
415 t = p + 12;
416 p += 16;
416 p += 16;
417 len = PyBytes_GET_SIZE(k);
417 len = PyBytes_GET_SIZE(k);
418 memcpy(p, PyBytes_AS_STRING(k), len);
418 memcpy(p, PyBytes_AS_STRING(k), len);
419 p += len;
419 p += len;
420 o = PyDict_GetItem(copymap, k);
420 o = PyDict_GetItem(copymap, k);
421 if (o) {
421 if (o) {
422 *p++ = '\0';
422 *p++ = '\0';
423 l = PyBytes_GET_SIZE(o);
423 l = PyBytes_GET_SIZE(o);
424 memcpy(p, PyBytes_AS_STRING(o), l);
424 memcpy(p, PyBytes_AS_STRING(o), l);
425 p += l;
425 p += l;
426 len += l + 1;
426 len += l + 1;
427 }
427 }
428 putbe32((uint32_t)len, t);
428 putbe32((uint32_t)len, t);
429 }
429 }
430
430
431 pos = p - PyBytes_AS_STRING(packobj);
431 pos = p - PyBytes_AS_STRING(packobj);
432 if (pos != nbytes) {
432 if (pos != nbytes) {
433 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
433 PyErr_Format(PyExc_SystemError, "bad dirstate size: %ld != %ld",
434 (long)pos, (long)nbytes);
434 (long)pos, (long)nbytes);
435 goto bail;
435 goto bail;
436 }
436 }
437
437
438 return packobj;
438 return packobj;
439 bail:
439 bail:
440 Py_XDECREF(mtime_unset);
440 Py_XDECREF(mtime_unset);
441 Py_XDECREF(packobj);
441 Py_XDECREF(packobj);
442 Py_XDECREF(v);
442 Py_XDECREF(v);
443 return NULL;
443 return NULL;
444 }
444 }
445
445
446 #define BUMPED_FIX 1
446 #define BUMPED_FIX 1
447 #define USING_SHA_256 2
447 #define USING_SHA_256 2
448 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
448 #define FM1_HEADER_SIZE (4 + 8 + 2 + 2 + 1 + 1 + 1)
449
449
450 static PyObject *readshas(const char *source, unsigned char num,
450 static PyObject *readshas(const char *source, unsigned char num,
451 Py_ssize_t hashwidth)
451 Py_ssize_t hashwidth)
452 {
452 {
453 int i;
453 int i;
454 PyObject *list = PyTuple_New(num);
454 PyObject *list = PyTuple_New(num);
455 if (list == NULL) {
455 if (list == NULL) {
456 return NULL;
456 return NULL;
457 }
457 }
458 for (i = 0; i < num; i++) {
458 for (i = 0; i < num; i++) {
459 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
459 PyObject *hash = PyBytes_FromStringAndSize(source, hashwidth);
460 if (hash == NULL) {
460 if (hash == NULL) {
461 Py_DECREF(list);
461 Py_DECREF(list);
462 return NULL;
462 return NULL;
463 }
463 }
464 PyTuple_SET_ITEM(list, i, hash);
464 PyTuple_SET_ITEM(list, i, hash);
465 source += hashwidth;
465 source += hashwidth;
466 }
466 }
467 return list;
467 return list;
468 }
468 }
469
469
470 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
470 static PyObject *fm1readmarker(const char *databegin, const char *dataend,
471 uint32_t *msize)
471 uint32_t *msize)
472 {
472 {
473 const char *data = databegin;
473 const char *data = databegin;
474 const char *meta;
474 const char *meta;
475
475
476 double mtime;
476 double mtime;
477 int16_t tz;
477 int16_t tz;
478 uint16_t flags;
478 uint16_t flags;
479 unsigned char nsuccs, nparents, nmetadata;
479 unsigned char nsuccs, nparents, nmetadata;
480 Py_ssize_t hashwidth = 20;
480 Py_ssize_t hashwidth = 20;
481
481
482 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
482 PyObject *prec = NULL, *parents = NULL, *succs = NULL;
483 PyObject *metadata = NULL, *ret = NULL;
483 PyObject *metadata = NULL, *ret = NULL;
484 int i;
484 int i;
485
485
486 if (data + FM1_HEADER_SIZE > dataend) {
486 if (data + FM1_HEADER_SIZE > dataend) {
487 goto overflow;
487 goto overflow;
488 }
488 }
489
489
490 *msize = getbe32(data);
490 *msize = getbe32(data);
491 data += 4;
491 data += 4;
492 mtime = getbefloat64(data);
492 mtime = getbefloat64(data);
493 data += 8;
493 data += 8;
494 tz = getbeint16(data);
494 tz = getbeint16(data);
495 data += 2;
495 data += 2;
496 flags = getbeuint16(data);
496 flags = getbeuint16(data);
497 data += 2;
497 data += 2;
498
498
499 if (flags & USING_SHA_256) {
499 if (flags & USING_SHA_256) {
500 hashwidth = 32;
500 hashwidth = 32;
501 }
501 }
502
502
503 nsuccs = (unsigned char)(*data++);
503 nsuccs = (unsigned char)(*data++);
504 nparents = (unsigned char)(*data++);
504 nparents = (unsigned char)(*data++);
505 nmetadata = (unsigned char)(*data++);
505 nmetadata = (unsigned char)(*data++);
506
506
507 if (databegin + *msize > dataend) {
507 if (databegin + *msize > dataend) {
508 goto overflow;
508 goto overflow;
509 }
509 }
510 dataend = databegin + *msize; /* narrow down to marker size */
510 dataend = databegin + *msize; /* narrow down to marker size */
511
511
512 if (data + hashwidth > dataend) {
512 if (data + hashwidth > dataend) {
513 goto overflow;
513 goto overflow;
514 }
514 }
515 prec = PyBytes_FromStringAndSize(data, hashwidth);
515 prec = PyBytes_FromStringAndSize(data, hashwidth);
516 data += hashwidth;
516 data += hashwidth;
517 if (prec == NULL) {
517 if (prec == NULL) {
518 goto bail;
518 goto bail;
519 }
519 }
520
520
521 if (data + nsuccs * hashwidth > dataend) {
521 if (data + nsuccs * hashwidth > dataend) {
522 goto overflow;
522 goto overflow;
523 }
523 }
524 succs = readshas(data, nsuccs, hashwidth);
524 succs = readshas(data, nsuccs, hashwidth);
525 if (succs == NULL) {
525 if (succs == NULL) {
526 goto bail;
526 goto bail;
527 }
527 }
528 data += nsuccs * hashwidth;
528 data += nsuccs * hashwidth;
529
529
530 if (nparents == 1 || nparents == 2) {
530 if (nparents == 1 || nparents == 2) {
531 if (data + nparents * hashwidth > dataend) {
531 if (data + nparents * hashwidth > dataend) {
532 goto overflow;
532 goto overflow;
533 }
533 }
534 parents = readshas(data, nparents, hashwidth);
534 parents = readshas(data, nparents, hashwidth);
535 if (parents == NULL) {
535 if (parents == NULL) {
536 goto bail;
536 goto bail;
537 }
537 }
538 data += nparents * hashwidth;
538 data += nparents * hashwidth;
539 } else {
539 } else {
540 parents = Py_None;
540 parents = Py_None;
541 Py_INCREF(parents);
541 Py_INCREF(parents);
542 }
542 }
543
543
544 if (data + 2 * nmetadata > dataend) {
544 if (data + 2 * nmetadata > dataend) {
545 goto overflow;
545 goto overflow;
546 }
546 }
547 meta = data + (2 * nmetadata);
547 meta = data + (2 * nmetadata);
548 metadata = PyTuple_New(nmetadata);
548 metadata = PyTuple_New(nmetadata);
549 if (metadata == NULL) {
549 if (metadata == NULL) {
550 goto bail;
550 goto bail;
551 }
551 }
552 for (i = 0; i < nmetadata; i++) {
552 for (i = 0; i < nmetadata; i++) {
553 PyObject *tmp, *left = NULL, *right = NULL;
553 PyObject *tmp, *left = NULL, *right = NULL;
554 Py_ssize_t leftsize = (unsigned char)(*data++);
554 Py_ssize_t leftsize = (unsigned char)(*data++);
555 Py_ssize_t rightsize = (unsigned char)(*data++);
555 Py_ssize_t rightsize = (unsigned char)(*data++);
556 if (meta + leftsize + rightsize > dataend) {
556 if (meta + leftsize + rightsize > dataend) {
557 goto overflow;
557 goto overflow;
558 }
558 }
559 left = PyBytes_FromStringAndSize(meta, leftsize);
559 left = PyBytes_FromStringAndSize(meta, leftsize);
560 meta += leftsize;
560 meta += leftsize;
561 right = PyBytes_FromStringAndSize(meta, rightsize);
561 right = PyBytes_FromStringAndSize(meta, rightsize);
562 meta += rightsize;
562 meta += rightsize;
563 tmp = PyTuple_New(2);
563 tmp = PyTuple_New(2);
564 if (!left || !right || !tmp) {
564 if (!left || !right || !tmp) {
565 Py_XDECREF(left);
565 Py_XDECREF(left);
566 Py_XDECREF(right);
566 Py_XDECREF(right);
567 Py_XDECREF(tmp);
567 Py_XDECREF(tmp);
568 goto bail;
568 goto bail;
569 }
569 }
570 PyTuple_SET_ITEM(tmp, 0, left);
570 PyTuple_SET_ITEM(tmp, 0, left);
571 PyTuple_SET_ITEM(tmp, 1, right);
571 PyTuple_SET_ITEM(tmp, 1, right);
572 PyTuple_SET_ITEM(metadata, i, tmp);
572 PyTuple_SET_ITEM(metadata, i, tmp);
573 }
573 }
574 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
574 ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags, metadata, mtime,
575 (int)tz * 60, parents);
575 (int)tz * 60, parents);
576 goto bail; /* return successfully */
576 goto bail; /* return successfully */
577
577
578 overflow:
578 overflow:
579 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
579 PyErr_SetString(PyExc_ValueError, "overflow in obsstore");
580 bail:
580 bail:
581 Py_XDECREF(prec);
581 Py_XDECREF(prec);
582 Py_XDECREF(succs);
582 Py_XDECREF(succs);
583 Py_XDECREF(metadata);
583 Py_XDECREF(metadata);
584 Py_XDECREF(parents);
584 Py_XDECREF(parents);
585 return ret;
585 return ret;
586 }
586 }
587
587
588 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
588 static PyObject *fm1readmarkers(PyObject *self, PyObject *args)
589 {
589 {
590 const char *data, *dataend;
590 const char *data, *dataend;
591 Py_ssize_t datalen, offset, stop;
591 Py_ssize_t datalen, offset, stop;
592 PyObject *markers = NULL;
592 PyObject *markers = NULL;
593
593
594 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
594 if (!PyArg_ParseTuple(args, PY23("s#nn", "y#nn"), &data, &datalen,
595 &offset, &stop)) {
595 &offset, &stop)) {
596 return NULL;
596 return NULL;
597 }
597 }
598 if (offset < 0) {
598 if (offset < 0) {
599 PyErr_SetString(PyExc_ValueError,
599 PyErr_SetString(PyExc_ValueError,
600 "invalid negative offset in fm1readmarkers");
600 "invalid negative offset in fm1readmarkers");
601 return NULL;
601 return NULL;
602 }
602 }
603 if (stop > datalen) {
603 if (stop > datalen) {
604 PyErr_SetString(
604 PyErr_SetString(
605 PyExc_ValueError,
605 PyExc_ValueError,
606 "stop longer than data length in fm1readmarkers");
606 "stop longer than data length in fm1readmarkers");
607 return NULL;
607 return NULL;
608 }
608 }
609 dataend = data + datalen;
609 dataend = data + datalen;
610 data += offset;
610 data += offset;
611 markers = PyList_New(0);
611 markers = PyList_New(0);
612 if (!markers) {
612 if (!markers) {
613 return NULL;
613 return NULL;
614 }
614 }
615 while (offset < stop) {
615 while (offset < stop) {
616 uint32_t msize;
616 uint32_t msize;
617 int error;
617 int error;
618 PyObject *record = fm1readmarker(data, dataend, &msize);
618 PyObject *record = fm1readmarker(data, dataend, &msize);
619 if (!record) {
619 if (!record) {
620 goto bail;
620 goto bail;
621 }
621 }
622 error = PyList_Append(markers, record);
622 error = PyList_Append(markers, record);
623 Py_DECREF(record);
623 Py_DECREF(record);
624 if (error) {
624 if (error) {
625 goto bail;
625 goto bail;
626 }
626 }
627 data += msize;
627 data += msize;
628 offset += msize;
628 offset += msize;
629 }
629 }
630 return markers;
630 return markers;
631 bail:
631 bail:
632 Py_DECREF(markers);
632 Py_DECREF(markers);
633 return NULL;
633 return NULL;
634 }
634 }
635
635
636 static char parsers_doc[] = "Efficient content parsing.";
636 static char parsers_doc[] = "Efficient content parsing.";
637
637
638 PyObject *encodedir(PyObject *self, PyObject *args);
638 PyObject *encodedir(PyObject *self, PyObject *args);
639 PyObject *pathencode(PyObject *self, PyObject *args);
639 PyObject *pathencode(PyObject *self, PyObject *args);
640 PyObject *lowerencode(PyObject *self, PyObject *args);
640 PyObject *lowerencode(PyObject *self, PyObject *args);
641 PyObject *parse_index2(PyObject *self, PyObject *args);
641 PyObject *parse_index2(PyObject *self, PyObject *args);
642
642
643 static PyMethodDef methods[] = {
643 static PyMethodDef methods[] = {
644 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
644 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
645 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
645 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
646 "create a set containing non-normal and other parent entries of given "
646 "create a set containing non-normal and other parent entries of given "
647 "dirstate\n"},
647 "dirstate\n"},
648 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
648 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
649 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
649 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
650 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
650 {"isasciistr", isasciistr, METH_VARARGS, "check if an ASCII string\n"},
651 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
651 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
652 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
652 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},
653 {"dict_new_presized", dict_new_presized, METH_VARARGS,
653 {"dict_new_presized", dict_new_presized, METH_VARARGS,
654 "construct a dict with an expected size\n"},
654 "construct a dict with an expected size\n"},
655 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
655 {"make_file_foldmap", make_file_foldmap, METH_VARARGS,
656 "make file foldmap\n"},
656 "make file foldmap\n"},
657 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
657 {"jsonescapeu8fast", jsonescapeu8fast, METH_VARARGS,
658 "escape a UTF-8 byte string to JSON (fast path)\n"},
658 "escape a UTF-8 byte string to JSON (fast path)\n"},
659 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
659 {"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
660 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
660 {"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
661 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
661 {"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
662 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
662 {"fm1readmarkers", fm1readmarkers, METH_VARARGS,
663 "parse v1 obsolete markers\n"},
663 "parse v1 obsolete markers\n"},
664 {NULL, NULL}};
664 {NULL, NULL}};
665
665
666 void dirs_module_init(PyObject *mod);
666 void dirs_module_init(PyObject *mod);
667 void manifest_module_init(PyObject *mod);
667 void manifest_module_init(PyObject *mod);
668 void revlog_module_init(PyObject *mod);
668 void revlog_module_init(PyObject *mod);
669
669
670 static const int version = 12;
670 static const int version = 12;
671
671
672 static void module_init(PyObject *mod)
672 static void module_init(PyObject *mod)
673 {
673 {
674 PyObject *capsule = NULL;
674 PyModule_AddIntConstant(mod, "version", version);
675 PyModule_AddIntConstant(mod, "version", version);
675
676
676 /* This module constant has two purposes. First, it lets us unit test
677 /* This module constant has two purposes. First, it lets us unit test
677 * the ImportError raised without hard-coding any error text. This
678 * the ImportError raised without hard-coding any error text. This
678 * means we can change the text in the future without breaking tests,
679 * means we can change the text in the future without breaking tests,
679 * even across changesets without a recompile. Second, its presence
680 * even across changesets without a recompile. Second, its presence
680 * can be used to determine whether the version-checking logic is
681 * can be used to determine whether the version-checking logic is
681 * present, which also helps in testing across changesets without a
682 * present, which also helps in testing across changesets without a
682 * recompile. Note that this means the pure-Python version of parsers
683 * recompile. Note that this means the pure-Python version of parsers
683 * should not have this module constant. */
684 * should not have this module constant. */
684 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
685 PyModule_AddStringConstant(mod, "versionerrortext", versionerrortext);
685
686
686 dirs_module_init(mod);
687 dirs_module_init(mod);
687 manifest_module_init(mod);
688 manifest_module_init(mod);
688 revlog_module_init(mod);
689 revlog_module_init(mod);
689
690
691 capsule = PyCapsule_New(
692 make_dirstate_tuple,
693 "mercurial.cext.parsers.make_dirstate_tuple_CAPI", NULL);
694 if (capsule != NULL)
695 PyModule_AddObject(mod, "make_dirstate_tuple_CAPI", capsule);
696
690 if (PyType_Ready(&dirstateTupleType) < 0) {
697 if (PyType_Ready(&dirstateTupleType) < 0) {
691 return;
698 return;
692 }
699 }
693 Py_INCREF(&dirstateTupleType);
700 Py_INCREF(&dirstateTupleType);
694 PyModule_AddObject(mod, "dirstatetuple",
701 PyModule_AddObject(mod, "dirstatetuple",
695 (PyObject *)&dirstateTupleType);
702 (PyObject *)&dirstateTupleType);
696 }
703 }
697
704
698 static int check_python_version(void)
705 static int check_python_version(void)
699 {
706 {
700 PyObject *sys = PyImport_ImportModule("sys"), *ver;
707 PyObject *sys = PyImport_ImportModule("sys"), *ver;
701 long hexversion;
708 long hexversion;
702 if (!sys) {
709 if (!sys) {
703 return -1;
710 return -1;
704 }
711 }
705 ver = PyObject_GetAttrString(sys, "hexversion");
712 ver = PyObject_GetAttrString(sys, "hexversion");
706 Py_DECREF(sys);
713 Py_DECREF(sys);
707 if (!ver) {
714 if (!ver) {
708 return -1;
715 return -1;
709 }
716 }
710 hexversion = PyInt_AsLong(ver);
717 hexversion = PyInt_AsLong(ver);
711 Py_DECREF(ver);
718 Py_DECREF(ver);
712 /* sys.hexversion is a 32-bit number by default, so the -1 case
719 /* sys.hexversion is a 32-bit number by default, so the -1 case
713 * should only occur in unusual circumstances (e.g. if sys.hexversion
720 * should only occur in unusual circumstances (e.g. if sys.hexversion
714 * is manually set to an invalid value). */
721 * is manually set to an invalid value). */
715 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
722 if ((hexversion == -1) || (hexversion >> 16 != PY_VERSION_HEX >> 16)) {
716 PyErr_Format(PyExc_ImportError,
723 PyErr_Format(PyExc_ImportError,
717 "%s: The Mercurial extension "
724 "%s: The Mercurial extension "
718 "modules were compiled with Python " PY_VERSION
725 "modules were compiled with Python " PY_VERSION
719 ", but "
726 ", but "
720 "Mercurial is currently using Python with "
727 "Mercurial is currently using Python with "
721 "sys.hexversion=%ld: "
728 "sys.hexversion=%ld: "
722 "Python %s\n at: %s",
729 "Python %s\n at: %s",
723 versionerrortext, hexversion, Py_GetVersion(),
730 versionerrortext, hexversion, Py_GetVersion(),
724 Py_GetProgramFullPath());
731 Py_GetProgramFullPath());
725 return -1;
732 return -1;
726 }
733 }
727 return 0;
734 return 0;
728 }
735 }
729
736
730 #ifdef IS_PY3K
737 #ifdef IS_PY3K
731 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
738 static struct PyModuleDef parsers_module = {PyModuleDef_HEAD_INIT, "parsers",
732 parsers_doc, -1, methods};
739 parsers_doc, -1, methods};
733
740
734 PyMODINIT_FUNC PyInit_parsers(void)
741 PyMODINIT_FUNC PyInit_parsers(void)
735 {
742 {
736 PyObject *mod;
743 PyObject *mod;
737
744
738 if (check_python_version() == -1)
745 if (check_python_version() == -1)
739 return NULL;
746 return NULL;
740 mod = PyModule_Create(&parsers_module);
747 mod = PyModule_Create(&parsers_module);
741 module_init(mod);
748 module_init(mod);
742 return mod;
749 return mod;
743 }
750 }
744 #else
751 #else
745 PyMODINIT_FUNC initparsers(void)
752 PyMODINIT_FUNC initparsers(void)
746 {
753 {
747 PyObject *mod;
754 PyObject *mod;
748
755
749 if (check_python_version() == -1) {
756 if (check_python_version() == -1) {
750 return;
757 return;
751 }
758 }
752 mod = Py_InitModule3("parsers", methods, parsers_doc);
759 mod = Py_InitModule3("parsers", methods, parsers_doc);
753 module_init(mod);
760 module_init(mod);
754 }
761 }
755 #endif
762 #endif
@@ -1,341 +1,332 b''
1 [[package]]
1 [[package]]
2 name = "aho-corasick"
2 name = "aho-corasick"
3 version = "0.6.9"
3 version = "0.6.9"
4 source = "registry+https://github.com/rust-lang/crates.io-index"
4 source = "registry+https://github.com/rust-lang/crates.io-index"
5 dependencies = [
5 dependencies = [
6 "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
6 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
7 ]
7 ]
8
8
9 [[package]]
9 [[package]]
10 name = "autocfg"
10 name = "autocfg"
11 version = "0.1.2"
11 version = "0.1.2"
12 source = "registry+https://github.com/rust-lang/crates.io-index"
12 source = "registry+https://github.com/rust-lang/crates.io-index"
13
13
14 [[package]]
14 [[package]]
15 name = "bitflags"
15 name = "bitflags"
16 version = "1.0.4"
16 version = "1.0.4"
17 source = "registry+https://github.com/rust-lang/crates.io-index"
17 source = "registry+https://github.com/rust-lang/crates.io-index"
18
18
19 [[package]]
19 [[package]]
20 name = "cfg-if"
20 name = "byteorder"
21 version = "0.1.6"
21 version = "1.3.1"
22 source = "registry+https://github.com/rust-lang/crates.io-index"
22 source = "registry+https://github.com/rust-lang/crates.io-index"
23
23
24 [[package]]
24 [[package]]
25 name = "cloudabi"
25 name = "cloudabi"
26 version = "0.0.3"
26 version = "0.0.3"
27 source = "registry+https://github.com/rust-lang/crates.io-index"
27 source = "registry+https://github.com/rust-lang/crates.io-index"
28 dependencies = [
28 dependencies = [
29 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
29 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
30 ]
30 ]
31
31
32 [[package]]
32 [[package]]
33 name = "cpython"
33 name = "cpython"
34 version = "0.2.1"
34 version = "0.2.1"
35 source = "registry+https://github.com/rust-lang/crates.io-index"
35 source = "registry+https://github.com/rust-lang/crates.io-index"
36 dependencies = [
36 dependencies = [
37 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
37 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
38 "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
38 "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
39 "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
39 "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
40 "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
40 "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
41 ]
41 ]
42
42
43 [[package]]
43 [[package]]
44 name = "fuchsia-cprng"
44 name = "fuchsia-cprng"
45 version = "0.1.0"
45 version = "0.1.0"
46 source = "registry+https://github.com/rust-lang/crates.io-index"
46 source = "registry+https://github.com/rust-lang/crates.io-index"
47
47
48 [[package]]
48 [[package]]
49 name = "hg-core"
49 name = "hg-core"
50 version = "0.1.0"
50 version = "0.1.0"
51 dependencies = [
51 dependencies = [
52 "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
53 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
52 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
54 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
53 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
55 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
54 ]
56 ]
55
57
56 [[package]]
58 [[package]]
57 name = "hg-cpython"
59 name = "hg-cpython"
58 version = "0.1.0"
60 version = "0.1.0"
59 dependencies = [
61 dependencies = [
60 "cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
62 "cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
61 "hg-core 0.1.0",
63 "hg-core 0.1.0",
62 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
64 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
63 "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
65 "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
64 "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
66 "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
65 ]
67 ]
66
68
67 [[package]]
69 [[package]]
68 name = "hgdirectffi"
70 name = "hgdirectffi"
69 version = "0.1.0"
71 version = "0.1.0"
70 dependencies = [
72 dependencies = [
71 "hg-core 0.1.0",
73 "hg-core 0.1.0",
72 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
74 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
73 ]
75 ]
74
76
75 [[package]]
77 [[package]]
76 name = "lazy_static"
78 name = "lazy_static"
77 version = "1.2.0"
79 version = "1.2.0"
78 source = "registry+https://github.com/rust-lang/crates.io-index"
80 source = "registry+https://github.com/rust-lang/crates.io-index"
79
81
80 [[package]]
82 [[package]]
81 name = "libc"
83 name = "libc"
82 version = "0.2.45"
84 version = "0.2.45"
83 source = "registry+https://github.com/rust-lang/crates.io-index"
85 source = "registry+https://github.com/rust-lang/crates.io-index"
84
86
85 [[package]]
87 [[package]]
86 name = "memchr"
88 name = "memchr"
87 version = "2.1.2"
89 version = "2.2.0"
88 source = "registry+https://github.com/rust-lang/crates.io-index"
90 source = "registry+https://github.com/rust-lang/crates.io-index"
89 dependencies = [
90 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
91 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
92 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
93 ]
94
91
95 [[package]]
92 [[package]]
96 name = "num-traits"
93 name = "num-traits"
97 version = "0.2.6"
94 version = "0.2.6"
98 source = "registry+https://github.com/rust-lang/crates.io-index"
95 source = "registry+https://github.com/rust-lang/crates.io-index"
99
96
100 [[package]]
97 [[package]]
101 name = "python27-sys"
98 name = "python27-sys"
102 version = "0.2.1"
99 version = "0.2.1"
103 source = "registry+https://github.com/rust-lang/crates.io-index"
100 source = "registry+https://github.com/rust-lang/crates.io-index"
104 dependencies = [
101 dependencies = [
105 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
102 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
106 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
103 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
107 ]
104 ]
108
105
109 [[package]]
106 [[package]]
110 name = "python3-sys"
107 name = "python3-sys"
111 version = "0.2.1"
108 version = "0.2.1"
112 source = "registry+https://github.com/rust-lang/crates.io-index"
109 source = "registry+https://github.com/rust-lang/crates.io-index"
113 dependencies = [
110 dependencies = [
114 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
111 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
115 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
112 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
116 ]
113 ]
117
114
118 [[package]]
115 [[package]]
119 name = "rand"
116 name = "rand"
120 version = "0.6.5"
117 version = "0.6.5"
121 source = "registry+https://github.com/rust-lang/crates.io-index"
118 source = "registry+https://github.com/rust-lang/crates.io-index"
122 dependencies = [
119 dependencies = [
123 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
120 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
124 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
121 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
125 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
122 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
126 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
123 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
127 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
124 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
128 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
125 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
129 "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
126 "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
130 "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
127 "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
131 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
128 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
132 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
129 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
133 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
130 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
134 ]
131 ]
135
132
136 [[package]]
133 [[package]]
137 name = "rand_chacha"
134 name = "rand_chacha"
138 version = "0.1.1"
135 version = "0.1.1"
139 source = "registry+https://github.com/rust-lang/crates.io-index"
136 source = "registry+https://github.com/rust-lang/crates.io-index"
140 dependencies = [
137 dependencies = [
141 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
138 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
142 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
139 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
143 ]
140 ]
144
141
145 [[package]]
142 [[package]]
146 name = "rand_core"
143 name = "rand_core"
147 version = "0.3.1"
144 version = "0.3.1"
148 source = "registry+https://github.com/rust-lang/crates.io-index"
145 source = "registry+https://github.com/rust-lang/crates.io-index"
149 dependencies = [
146 dependencies = [
150 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
147 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
151 ]
148 ]
152
149
153 [[package]]
150 [[package]]
154 name = "rand_core"
151 name = "rand_core"
155 version = "0.4.0"
152 version = "0.4.0"
156 source = "registry+https://github.com/rust-lang/crates.io-index"
153 source = "registry+https://github.com/rust-lang/crates.io-index"
157
154
158 [[package]]
155 [[package]]
159 name = "rand_hc"
156 name = "rand_hc"
160 version = "0.1.0"
157 version = "0.1.0"
161 source = "registry+https://github.com/rust-lang/crates.io-index"
158 source = "registry+https://github.com/rust-lang/crates.io-index"
162 dependencies = [
159 dependencies = [
163 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
160 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
164 ]
161 ]
165
162
166 [[package]]
163 [[package]]
167 name = "rand_isaac"
164 name = "rand_isaac"
168 version = "0.1.1"
165 version = "0.1.1"
169 source = "registry+https://github.com/rust-lang/crates.io-index"
166 source = "registry+https://github.com/rust-lang/crates.io-index"
170 dependencies = [
167 dependencies = [
171 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
168 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
172 ]
169 ]
173
170
174 [[package]]
171 [[package]]
175 name = "rand_jitter"
172 name = "rand_jitter"
176 version = "0.1.2"
173 version = "0.1.2"
177 source = "registry+https://github.com/rust-lang/crates.io-index"
174 source = "registry+https://github.com/rust-lang/crates.io-index"
178 dependencies = [
175 dependencies = [
179 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
176 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
180 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
177 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
181 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
178 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
182 ]
179 ]
183
180
184 [[package]]
181 [[package]]
185 name = "rand_os"
182 name = "rand_os"
186 version = "0.1.2"
183 version = "0.1.2"
187 source = "registry+https://github.com/rust-lang/crates.io-index"
184 source = "registry+https://github.com/rust-lang/crates.io-index"
188 dependencies = [
185 dependencies = [
189 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
186 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
190 "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
187 "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
191 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
188 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
192 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
189 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
193 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
190 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
194 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
191 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
195 ]
192 ]
196
193
197 [[package]]
194 [[package]]
198 name = "rand_pcg"
195 name = "rand_pcg"
199 version = "0.1.1"
196 version = "0.1.1"
200 source = "registry+https://github.com/rust-lang/crates.io-index"
197 source = "registry+https://github.com/rust-lang/crates.io-index"
201 dependencies = [
198 dependencies = [
202 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
199 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
203 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
200 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
204 ]
201 ]
205
202
206 [[package]]
203 [[package]]
207 name = "rand_xorshift"
204 name = "rand_xorshift"
208 version = "0.1.1"
205 version = "0.1.1"
209 source = "registry+https://github.com/rust-lang/crates.io-index"
206 source = "registry+https://github.com/rust-lang/crates.io-index"
210 dependencies = [
207 dependencies = [
211 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
208 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
212 ]
209 ]
213
210
214 [[package]]
211 [[package]]
215 name = "rdrand"
212 name = "rdrand"
216 version = "0.4.0"
213 version = "0.4.0"
217 source = "registry+https://github.com/rust-lang/crates.io-index"
214 source = "registry+https://github.com/rust-lang/crates.io-index"
218 dependencies = [
215 dependencies = [
219 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
216 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
220 ]
217 ]
221
218
222 [[package]]
219 [[package]]
223 name = "regex"
220 name = "regex"
224 version = "1.1.0"
221 version = "1.1.0"
225 source = "registry+https://github.com/rust-lang/crates.io-index"
222 source = "registry+https://github.com/rust-lang/crates.io-index"
226 dependencies = [
223 dependencies = [
227 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
224 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
228 "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
225 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
229 "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
226 "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
230 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
227 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
231 "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
228 "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
232 ]
229 ]
233
230
234 [[package]]
231 [[package]]
235 name = "regex-syntax"
232 name = "regex-syntax"
236 version = "0.6.4"
233 version = "0.6.4"
237 source = "registry+https://github.com/rust-lang/crates.io-index"
234 source = "registry+https://github.com/rust-lang/crates.io-index"
238 dependencies = [
235 dependencies = [
239 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
236 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
240 ]
237 ]
241
238
242 [[package]]
239 [[package]]
243 name = "rustc_version"
240 name = "rustc_version"
244 version = "0.2.3"
241 version = "0.2.3"
245 source = "registry+https://github.com/rust-lang/crates.io-index"
242 source = "registry+https://github.com/rust-lang/crates.io-index"
246 dependencies = [
243 dependencies = [
247 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
244 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
248 ]
245 ]
249
246
250 [[package]]
247 [[package]]
251 name = "semver"
248 name = "semver"
252 version = "0.9.0"
249 version = "0.9.0"
253 source = "registry+https://github.com/rust-lang/crates.io-index"
250 source = "registry+https://github.com/rust-lang/crates.io-index"
254 dependencies = [
251 dependencies = [
255 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
252 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
256 ]
253 ]
257
254
258 [[package]]
255 [[package]]
259 name = "semver-parser"
256 name = "semver-parser"
260 version = "0.7.0"
257 version = "0.7.0"
261 source = "registry+https://github.com/rust-lang/crates.io-index"
258 source = "registry+https://github.com/rust-lang/crates.io-index"
262
259
263 [[package]]
260 [[package]]
264 name = "thread_local"
261 name = "thread_local"
265 version = "0.3.6"
262 version = "0.3.6"
266 source = "registry+https://github.com/rust-lang/crates.io-index"
263 source = "registry+https://github.com/rust-lang/crates.io-index"
267 dependencies = [
264 dependencies = [
268 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
265 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
269 ]
266 ]
270
267
271 [[package]]
268 [[package]]
272 name = "ucd-util"
269 name = "ucd-util"
273 version = "0.1.3"
270 version = "0.1.3"
274 source = "registry+https://github.com/rust-lang/crates.io-index"
271 source = "registry+https://github.com/rust-lang/crates.io-index"
275
272
276 [[package]]
273 [[package]]
277 name = "utf8-ranges"
274 name = "utf8-ranges"
278 version = "1.0.2"
275 version = "1.0.2"
279 source = "registry+https://github.com/rust-lang/crates.io-index"
276 source = "registry+https://github.com/rust-lang/crates.io-index"
280
277
281 [[package]]
278 [[package]]
282 name = "version_check"
283 version = "0.1.5"
284 source = "registry+https://github.com/rust-lang/crates.io-index"
285
286 [[package]]
287 name = "winapi"
279 name = "winapi"
288 version = "0.3.6"
280 version = "0.3.6"
289 source = "registry+https://github.com/rust-lang/crates.io-index"
281 source = "registry+https://github.com/rust-lang/crates.io-index"
290 dependencies = [
282 dependencies = [
291 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
283 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
292 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
284 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
293 ]
285 ]
294
286
295 [[package]]
287 [[package]]
296 name = "winapi-i686-pc-windows-gnu"
288 name = "winapi-i686-pc-windows-gnu"
297 version = "0.4.0"
289 version = "0.4.0"
298 source = "registry+https://github.com/rust-lang/crates.io-index"
290 source = "registry+https://github.com/rust-lang/crates.io-index"
299
291
300 [[package]]
292 [[package]]
301 name = "winapi-x86_64-pc-windows-gnu"
293 name = "winapi-x86_64-pc-windows-gnu"
302 version = "0.4.0"
294 version = "0.4.0"
303 source = "registry+https://github.com/rust-lang/crates.io-index"
295 source = "registry+https://github.com/rust-lang/crates.io-index"
304
296
305 [metadata]
297 [metadata]
306 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
298 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
307 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
299 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
308 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
300 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
309 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
301 "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
310 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
302 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
311 "checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940"
303 "checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940"
312 "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"
304 "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"
313 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
305 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
314 "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
306 "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
315 "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9"
307 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
316 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
308 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
317 "checksum python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56114c37d4dca82526d74009df7782a28c871ac9d36b19d4cb9e67672258527e"
309 "checksum python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56114c37d4dca82526d74009df7782a28c871ac9d36b19d4cb9e67672258527e"
318 "checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444"
310 "checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444"
319 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
311 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
320 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
312 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
321 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
313 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
322 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
314 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
323 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
315 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
324 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
316 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
325 "checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0"
317 "checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0"
326 "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
318 "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
327 "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
319 "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
328 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
320 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
329 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
321 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
330 "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
322 "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
331 "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
323 "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
332 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
324 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
333 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
325 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
334 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
326 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
335 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
327 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
336 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
328 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
337 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
329 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
338 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
339 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
330 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
340 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
331 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
341 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
332 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
@@ -1,71 +1,75 b''
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
2 //
2 //
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5 extern crate byteorder;
5 extern crate byteorder;
6 extern crate memchr;
6 extern crate memchr;
7
7
8 mod ancestors;
8 mod ancestors;
9 pub mod dagops;
9 pub mod dagops;
10 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
10 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
11 pub mod testing; // unconditionally built, for use from integration tests
11 mod dirstate;
12 pub mod discovery;
12 pub mod discovery;
13 pub mod testing; // unconditionally built, for use from integration tests
14 pub use dirstate::{
15 pack_dirstate, parse_dirstate, CopyVec, CopyVecEntry, DirstateEntry,
16 DirstateParents, DirstateVec,
17 };
13
18
14 /// Mercurial revision numbers
19 /// Mercurial revision numbers
15 ///
20 ///
16 /// As noted in revlog.c, revision numbers are actually encoded in
21 /// As noted in revlog.c, revision numbers are actually encoded in
17 /// 4 bytes, and are liberally converted to ints, whence the i32
22 /// 4 bytes, and are liberally converted to ints, whence the i32
18 pub type Revision = i32;
23 pub type Revision = i32;
19
24
20
21 /// Marker expressing the absence of a parent
25 /// Marker expressing the absence of a parent
22 ///
26 ///
23 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
27 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
24 /// to be smaller that all existing revisions.
28 /// to be smaller that all existing revisions.
25 pub const NULL_REVISION: Revision = -1;
29 pub const NULL_REVISION: Revision = -1;
26
30
27 /// Same as `mercurial.node.wdirrev`
31 /// Same as `mercurial.node.wdirrev`
28 ///
32 ///
29 /// This is also equal to `i32::max_value()`, but it's better to spell
33 /// This is also equal to `i32::max_value()`, but it's better to spell
30 /// it out explicitely, same as in `mercurial.node`
34 /// it out explicitely, same as in `mercurial.node`
31 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
35 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
32
36
33 /// The simplest expression of what we need of Mercurial DAGs.
37 /// The simplest expression of what we need of Mercurial DAGs.
34 pub trait Graph {
38 pub trait Graph {
35 /// Return the two parents of the given `Revision`.
39 /// Return the two parents of the given `Revision`.
36 ///
40 ///
37 /// Each of the parents can be independently `NULL_REVISION`
41 /// Each of the parents can be independently `NULL_REVISION`
38 fn parents(&self, Revision) -> Result<[Revision; 2], GraphError>;
42 fn parents(&self, Revision) -> Result<[Revision; 2], GraphError>;
39 }
43 }
40
44
41 #[derive(Clone, Debug, PartialEq)]
45 #[derive(Clone, Debug, PartialEq)]
42 pub enum GraphError {
46 pub enum GraphError {
43 ParentOutOfRange(Revision),
47 ParentOutOfRange(Revision),
44 WorkingDirectoryUnsupported,
48 WorkingDirectoryUnsupported,
45 }
49 }
46
50
47 #[derive(Clone, Debug, PartialEq)]
51 #[derive(Clone, Debug, PartialEq)]
48 pub enum DirstateParseError {
52 pub enum DirstateParseError {
49 TooLittleData,
53 TooLittleData,
50 Overflow,
54 Overflow,
51 CorruptedEntry(String),
55 CorruptedEntry(String),
52 }
56 }
53
57
54 #[derive(Debug, PartialEq)]
58 #[derive(Debug, PartialEq)]
55 pub enum DirstatePackError {
59 pub enum DirstatePackError {
56 CorruptedEntry(String),
60 CorruptedEntry(String),
57 CorruptedParent,
61 CorruptedParent,
58 BadSize(usize, usize),
62 BadSize(usize, usize),
59 }
63 }
60
64
61 impl From<std::io::Error> for DirstatePackError {
65 impl From<std::io::Error> for DirstatePackError {
62 fn from(e: std::io::Error) -> Self {
66 fn from(e: std::io::Error) -> Self {
63 DirstatePackError::CorruptedEntry(e.to_string())
67 DirstatePackError::CorruptedEntry(e.to_string())
64 }
68 }
65 }
69 }
66
70
67 impl From<std::io::Error> for DirstateParseError {
71 impl From<std::io::Error> for DirstateParseError {
68 fn from(e: std::io::Error) -> Self {
72 fn from(e: std::io::Error) -> Self {
69 DirstateParseError::CorruptedEntry(e.to_string())
73 DirstateParseError::CorruptedEntry(e.to_string())
70 }
74 }
71 }
75 }
@@ -1,47 +1,50 b''
1 // lib.rs
1 // lib.rs
2 //
2 //
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Python bindings of `hg-core` objects using the `cpython` crate.
8 //! Python bindings of `hg-core` objects using the `cpython` crate.
9 //! Once compiled, the resulting single shared library object can be placed in
9 //! Once compiled, the resulting single shared library object can be placed in
10 //! the `mercurial` package directly as `rustext.so` or `rustext.dll`.
10 //! the `mercurial` package directly as `rustext.so` or `rustext.dll`.
11 //! It holds several modules, so that from the point of view of Python,
11 //! It holds several modules, so that from the point of view of Python,
12 //! it behaves as the `cext` package.
12 //! it behaves as the `cext` package.
13 //!
13 //!
14 //! Example:
14 //! Example:
15 //!
15 //!
16 //! ```text
16 //! ```text
17 //! >>> from mercurial.rustext import ancestor
17 //! >>> from mercurial.rustext import ancestor
18 //! >>> ancestor.__doc__
18 //! >>> ancestor.__doc__
19 //! 'Generic DAG ancestor algorithms - Rust implementation'
19 //! 'Generic DAG ancestor algorithms - Rust implementation'
20 //! ```
20 //! ```
21
21
22 #[macro_use]
22 #[macro_use]
23 extern crate cpython;
23 extern crate cpython;
24 extern crate hg;
24 extern crate hg;
25 extern crate libc;
25 extern crate libc;
26 extern crate python27_sys;
26
27
27 pub mod ancestors;
28 pub mod ancestors;
28 mod cindex;
29 mod cindex;
29 mod conversion;
30 mod conversion;
30 pub mod dagops;
31 pub mod dagops;
31 pub mod discovery;
32 pub mod discovery;
32 pub mod exceptions;
33 pub mod exceptions;
34 pub mod dirstate;
33
35
34 py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| {
36 py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| {
35 m.add(
37 m.add(
36 py,
38 py,
37 "__doc__",
39 "__doc__",
38 "Mercurial core concepts - Rust implementation",
40 "Mercurial core concepts - Rust implementation",
39 )?;
41 )?;
40
42
41 let dotted_name: String = m.get(py, "__name__")?.extract(py)?;
43 let dotted_name: String = m.get(py, "__name__")?.extract(py)?;
42 m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?;
44 m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?;
43 m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?;
45 m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?;
44 m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?;
46 m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?;
47 m.add(py, "dirstate", dirstate::init_module(py, &dotted_name)?)?;
45 m.add(py, "GraphError", py.get_type::<exceptions::GraphError>())?;
48 m.add(py, "GraphError", py.get_type::<exceptions::GraphError>())?;
46 Ok(())
49 Ok(())
47 });
50 });
General Comments 0
You need to be logged in to leave comments. Login now