Show More
@@ -28,6 +28,7 b' typedef struct {' | |||||
28 | typedef struct { |
|
28 | typedef struct { | |
29 | PyObject_HEAD |
|
29 | PyObject_HEAD | |
30 | PyObject *pydata; |
|
30 | PyObject *pydata; | |
|
31 | Py_ssize_t nodelen; | |||
31 | line *lines; |
|
32 | line *lines; | |
32 | int numlines; /* number of line entries */ |
|
33 | int numlines; /* number of line entries */ | |
33 | int livelines; /* number of non-deleted lines */ |
|
34 | int livelines; /* number of non-deleted lines */ | |
@@ -49,12 +50,11 b' static Py_ssize_t pathlen(line *l)' | |||||
49 | } |
|
50 | } | |
50 |
|
51 | |||
51 | /* get the node value of a single line */ |
|
52 | /* get the node value of a single line */ | |
52 | static PyObject *nodeof(line *l, char *flag) |
|
53 | static PyObject *nodeof(Py_ssize_t nodelen, line *l, char *flag) | |
53 | { |
|
54 | { | |
54 | char *s = l->start; |
|
55 | char *s = l->start; | |
55 | Py_ssize_t llen = pathlen(l); |
|
56 | Py_ssize_t llen = pathlen(l); | |
56 | Py_ssize_t hlen = l->len - llen - 2; |
|
57 | Py_ssize_t hlen = l->len - llen - 2; | |
57 | Py_ssize_t hlen_raw; |
|
|||
58 | PyObject *hash; |
|
58 | PyObject *hash; | |
59 | if (llen + 1 + 40 + 1 > l->len) { /* path '\0' hash '\n' */ |
|
59 | if (llen + 1 + 40 + 1 > l->len) { /* path '\0' hash '\n' */ | |
60 | PyErr_SetString(PyExc_ValueError, "manifest line too short"); |
|
60 | PyErr_SetString(PyExc_ValueError, "manifest line too short"); | |
@@ -73,36 +73,29 b' static PyObject *nodeof(line *l, char *f' | |||||
73 | break; |
|
73 | break; | |
74 | } |
|
74 | } | |
75 |
|
75 | |||
76 | switch (hlen) { |
|
76 | if (hlen != 2 * nodelen) { | |
77 | case 40: /* sha1 */ |
|
|||
78 | hlen_raw = 20; |
|
|||
79 | break; |
|
|||
80 | case 64: /* new hash */ |
|
|||
81 | hlen_raw = 32; |
|
|||
82 | break; |
|
|||
83 | default: |
|
|||
84 | PyErr_SetString(PyExc_ValueError, "invalid node length in manifest"); |
|
77 | PyErr_SetString(PyExc_ValueError, "invalid node length in manifest"); | |
85 | return NULL; |
|
78 | return NULL; | |
86 | } |
|
79 | } | |
87 |
hash = unhexlify(s + llen + 1, |
|
80 | hash = unhexlify(s + llen + 1, nodelen * 2); | |
88 | if (!hash) { |
|
81 | if (!hash) { | |
89 | return NULL; |
|
82 | return NULL; | |
90 | } |
|
83 | } | |
91 | if (l->hash_suffix != '\0') { |
|
84 | if (l->hash_suffix != '\0') { | |
92 | char newhash[33]; |
|
85 | char newhash[33]; | |
93 |
memcpy(newhash, PyBytes_AsString(hash), |
|
86 | memcpy(newhash, PyBytes_AsString(hash), nodelen); | |
94 | Py_DECREF(hash); |
|
87 | Py_DECREF(hash); | |
95 |
newhash[ |
|
88 | newhash[nodelen] = l->hash_suffix; | |
96 |
hash = PyBytes_FromStringAndSize(newhash, |
|
89 | hash = PyBytes_FromStringAndSize(newhash, nodelen + 1); | |
97 | } |
|
90 | } | |
98 | return hash; |
|
91 | return hash; | |
99 | } |
|
92 | } | |
100 |
|
93 | |||
101 | /* get the node hash and flags of a line as a tuple */ |
|
94 | /* get the node hash and flags of a line as a tuple */ | |
102 | static PyObject *hashflags(line *l) |
|
95 | static PyObject *hashflags(Py_ssize_t nodelen, line *l) | |
103 | { |
|
96 | { | |
104 | char flag; |
|
97 | char flag; | |
105 | PyObject *hash = nodeof(l, &flag); |
|
98 | PyObject *hash = nodeof(nodelen, l, &flag); | |
106 | PyObject *flags; |
|
99 | PyObject *flags; | |
107 | PyObject *tup; |
|
100 | PyObject *tup; | |
108 |
|
101 | |||
@@ -190,17 +183,23 b' static void lazymanifest_init_early(lazy' | |||||
190 | static int lazymanifest_init(lazymanifest *self, PyObject *args) |
|
183 | static int lazymanifest_init(lazymanifest *self, PyObject *args) | |
191 | { |
|
184 | { | |
192 | char *data; |
|
185 | char *data; | |
193 | Py_ssize_t len; |
|
186 | Py_ssize_t nodelen, len; | |
194 | int err, ret; |
|
187 | int err, ret; | |
195 | PyObject *pydata; |
|
188 | PyObject *pydata; | |
196 |
|
189 | |||
197 | lazymanifest_init_early(self); |
|
190 | lazymanifest_init_early(self); | |
198 | if (!PyArg_ParseTuple(args, "S", &pydata)) { |
|
191 | if (!PyArg_ParseTuple(args, "nS", &nodelen, &pydata)) { | |
199 | return -1; |
|
192 | return -1; | |
200 | } |
|
193 | } | |
201 | err = PyBytes_AsStringAndSize(pydata, &data, &len); |
|
194 | if (nodelen != 20 && nodelen != 32) { | |
|
195 | /* See fixed buffer in nodeof */ | |||
|
196 | PyErr_Format(PyExc_ValueError, "Unsupported node length"); | |||
|
197 | return -1; | |||
|
198 | } | |||
|
199 | self->nodelen = nodelen; | |||
|
200 | self->dirty = false; | |||
202 |
|
201 | |||
203 | self->dirty = false; |
|
202 | err = PyBytes_AsStringAndSize(pydata, &data, &len); | |
204 | if (err == -1) |
|
203 | if (err == -1) | |
205 | return -1; |
|
204 | return -1; | |
206 | self->pydata = pydata; |
|
205 | self->pydata = pydata; | |
@@ -291,17 +290,18 b' static line *lmiter_nextline(lmIter *sel' | |||||
291 |
|
290 | |||
292 | static PyObject *lmiter_iterentriesnext(PyObject *o) |
|
291 | static PyObject *lmiter_iterentriesnext(PyObject *o) | |
293 | { |
|
292 | { | |
|
293 | lmIter *self = (lmIter *)o; | |||
294 | Py_ssize_t pl; |
|
294 | Py_ssize_t pl; | |
295 | line *l; |
|
295 | line *l; | |
296 | char flag; |
|
296 | char flag; | |
297 | PyObject *ret = NULL, *path = NULL, *hash = NULL, *flags = NULL; |
|
297 | PyObject *ret = NULL, *path = NULL, *hash = NULL, *flags = NULL; | |
298 |
l = lmiter_nextline( |
|
298 | l = lmiter_nextline(self); | |
299 | if (!l) { |
|
299 | if (!l) { | |
300 | goto done; |
|
300 | goto done; | |
301 | } |
|
301 | } | |
302 | pl = pathlen(l); |
|
302 | pl = pathlen(l); | |
303 | path = PyBytes_FromStringAndSize(l->start, pl); |
|
303 | path = PyBytes_FromStringAndSize(l->start, pl); | |
304 | hash = nodeof(l, &flag); |
|
304 | hash = nodeof(self->m->nodelen, l, &flag); | |
305 | if (!path || !hash) { |
|
305 | if (!path || !hash) { | |
306 | goto done; |
|
306 | goto done; | |
307 | } |
|
307 | } | |
@@ -471,7 +471,7 b' static PyObject *lazymanifest_getitem(la' | |||||
471 | PyErr_Format(PyExc_KeyError, "No such manifest entry."); |
|
471 | PyErr_Format(PyExc_KeyError, "No such manifest entry."); | |
472 | return NULL; |
|
472 | return NULL; | |
473 | } |
|
473 | } | |
474 | return hashflags(hit); |
|
474 | return hashflags(self->nodelen, hit); | |
475 | } |
|
475 | } | |
476 |
|
476 | |||
477 | static int lazymanifest_delitem(lazymanifest *self, PyObject *key) |
|
477 | static int lazymanifest_delitem(lazymanifest *self, PyObject *key) | |
@@ -568,13 +568,13 b' static int lazymanifest_setitem(' | |||||
568 | pyhash = PyTuple_GetItem(value, 0); |
|
568 | pyhash = PyTuple_GetItem(value, 0); | |
569 | if (!PyBytes_Check(pyhash)) { |
|
569 | if (!PyBytes_Check(pyhash)) { | |
570 | PyErr_Format(PyExc_TypeError, |
|
570 | PyErr_Format(PyExc_TypeError, | |
571 |
"node must be a |
|
571 | "node must be a %zi bytes string", self->nodelen); | |
572 | return -1; |
|
572 | return -1; | |
573 | } |
|
573 | } | |
574 | hlen = PyBytes_Size(pyhash); |
|
574 | hlen = PyBytes_Size(pyhash); | |
575 |
if (hlen != |
|
575 | if (hlen != self->nodelen) { | |
576 | PyErr_Format(PyExc_TypeError, |
|
576 | PyErr_Format(PyExc_TypeError, | |
577 |
"node must be a |
|
577 | "node must be a %zi bytes string", self->nodelen); | |
578 | return -1; |
|
578 | return -1; | |
579 | } |
|
579 | } | |
580 | hash = PyBytes_AsString(pyhash); |
|
580 | hash = PyBytes_AsString(pyhash); | |
@@ -739,6 +739,7 b' static lazymanifest *lazymanifest_copy(l' | |||||
739 | goto nomem; |
|
739 | goto nomem; | |
740 | } |
|
740 | } | |
741 | lazymanifest_init_early(copy); |
|
741 | lazymanifest_init_early(copy); | |
|
742 | copy->nodelen = self->nodelen; | |||
742 | copy->numlines = self->numlines; |
|
743 | copy->numlines = self->numlines; | |
743 | copy->livelines = self->livelines; |
|
744 | copy->livelines = self->livelines; | |
744 | copy->dirty = false; |
|
745 | copy->dirty = false; | |
@@ -777,6 +778,7 b' static lazymanifest *lazymanifest_filter' | |||||
777 | goto nomem; |
|
778 | goto nomem; | |
778 | } |
|
779 | } | |
779 | lazymanifest_init_early(copy); |
|
780 | lazymanifest_init_early(copy); | |
|
781 | copy->nodelen = self->nodelen; | |||
780 | copy->dirty = true; |
|
782 | copy->dirty = true; | |
781 | copy->lines = malloc(self->maxlines * sizeof(line)); |
|
783 | copy->lines = malloc(self->maxlines * sizeof(line)); | |
782 | if (!copy->lines) { |
|
784 | if (!copy->lines) { | |
@@ -872,7 +874,7 b' static PyObject *lazymanifest_diff(lazym' | |||||
872 | if (!key) |
|
874 | if (!key) | |
873 | goto nomem; |
|
875 | goto nomem; | |
874 | if (result < 0) { |
|
876 | if (result < 0) { | |
875 | PyObject *l = hashflags(left); |
|
877 | PyObject *l = hashflags(self->nodelen, left); | |
876 | if (!l) { |
|
878 | if (!l) { | |
877 | goto nomem; |
|
879 | goto nomem; | |
878 | } |
|
880 | } | |
@@ -885,7 +887,7 b' static PyObject *lazymanifest_diff(lazym' | |||||
885 | Py_DECREF(outer); |
|
887 | Py_DECREF(outer); | |
886 | sneedle++; |
|
888 | sneedle++; | |
887 | } else if (result > 0) { |
|
889 | } else if (result > 0) { | |
888 | PyObject *r = hashflags(right); |
|
890 | PyObject *r = hashflags(self->nodelen, right); | |
889 | if (!r) { |
|
891 | if (!r) { | |
890 | goto nomem; |
|
892 | goto nomem; | |
891 | } |
|
893 | } | |
@@ -902,12 +904,12 b' static PyObject *lazymanifest_diff(lazym' | |||||
902 | if (left->len != right->len |
|
904 | if (left->len != right->len | |
903 | || memcmp(left->start, right->start, left->len) |
|
905 | || memcmp(left->start, right->start, left->len) | |
904 | || left->hash_suffix != right->hash_suffix) { |
|
906 | || left->hash_suffix != right->hash_suffix) { | |
905 | PyObject *l = hashflags(left); |
|
907 | PyObject *l = hashflags(self->nodelen, left); | |
906 | PyObject *r; |
|
908 | PyObject *r; | |
907 | if (!l) { |
|
909 | if (!l) { | |
908 | goto nomem; |
|
910 | goto nomem; | |
909 | } |
|
911 | } | |
910 | r = hashflags(right); |
|
912 | r = hashflags(self->nodelen, right); | |
911 | if (!r) { |
|
913 | if (!r) { | |
912 | Py_DECREF(l); |
|
914 | Py_DECREF(l); | |
913 | goto nomem; |
|
915 | goto nomem; |
@@ -668,7 +668,7 b' void dirs_module_init(PyObject *mod);' | |||||
668 | void manifest_module_init(PyObject *mod); |
|
668 | void manifest_module_init(PyObject *mod); | |
669 | void revlog_module_init(PyObject *mod); |
|
669 | void revlog_module_init(PyObject *mod); | |
670 |
|
670 | |||
671 |
static const int version = 1 |
|
671 | static const int version = 18; | |
672 |
|
672 | |||
673 | static void module_init(PyObject *mod) |
|
673 | static void module_init(PyObject *mod) | |
674 | { |
|
674 | { |
@@ -29,7 +29,7 b' class dirs:' | |||||
29 |
|
29 | |||
30 | # From manifest.c |
|
30 | # From manifest.c | |
31 | class lazymanifest: |
|
31 | class lazymanifest: | |
32 | def __init__(self, data: bytes): ... |
|
32 | def __init__(self, nodelen: int, data: bytes): ... | |
33 | def __iter__(self) -> Iterator[bytes]: ... |
|
33 | def __iter__(self) -> Iterator[bytes]: ... | |
34 |
|
34 | |||
35 | def __len__(self) -> int: ... |
|
35 | def __len__(self) -> int: ... |
@@ -42,7 +42,7 b' propertycache = util.propertycache' | |||||
42 | FASTDELTA_TEXTDIFF_THRESHOLD = 1000 |
|
42 | FASTDELTA_TEXTDIFF_THRESHOLD = 1000 | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | def _parse(data): |
|
45 | def _parse(nodelen, data): | |
46 | # This method does a little bit of excessive-looking |
|
46 | # This method does a little bit of excessive-looking | |
47 | # precondition checking. This is so that the behavior of this |
|
47 | # precondition checking. This is so that the behavior of this | |
48 | # class exactly matches its C counterpart to try and help |
|
48 | # class exactly matches its C counterpart to try and help | |
@@ -63,7 +63,7 b' def _parse(data):' | |||||
63 | nl -= 1 |
|
63 | nl -= 1 | |
64 | else: |
|
64 | else: | |
65 | flags = b'' |
|
65 | flags = b'' | |
66 |
if nl |
|
66 | if nl != 2 * nodelen: | |
67 | raise ValueError(b'Invalid manifest line') |
|
67 | raise ValueError(b'Invalid manifest line') | |
68 |
|
68 | |||
69 | yield f, bin(n), flags |
|
69 | yield f, bin(n), flags | |
@@ -131,7 +131,7 b' class lazymanifestiterentries(object):' | |||||
131 | else: |
|
131 | else: | |
132 | hlen = nlpos - zeropos - 1 |
|
132 | hlen = nlpos - zeropos - 1 | |
133 | flags = b'' |
|
133 | flags = b'' | |
134 | if hlen not in (40, 64): |
|
134 | if hlen != 2 * self.lm._nodelen: | |
135 | raise error.StorageError(b'Invalid manifest line') |
|
135 | raise error.StorageError(b'Invalid manifest line') | |
136 | hashval = unhexlify( |
|
136 | hashval = unhexlify( | |
137 | data, self.lm.extrainfo[self.pos], zeropos + 1, hlen |
|
137 | data, self.lm.extrainfo[self.pos], zeropos + 1, hlen | |
@@ -176,12 +176,14 b' class _lazymanifest(object):' | |||||
176 |
|
176 | |||
177 | def __init__( |
|
177 | def __init__( | |
178 | self, |
|
178 | self, | |
|
179 | nodelen, | |||
179 | data, |
|
180 | data, | |
180 | positions=None, |
|
181 | positions=None, | |
181 | extrainfo=None, |
|
182 | extrainfo=None, | |
182 | extradata=None, |
|
183 | extradata=None, | |
183 | hasremovals=False, |
|
184 | hasremovals=False, | |
184 | ): |
|
185 | ): | |
|
186 | self._nodelen = nodelen | |||
185 | if positions is None: |
|
187 | if positions is None: | |
186 | self.positions = self.findlines(data) |
|
188 | self.positions = self.findlines(data) | |
187 | self.extrainfo = [0] * len(self.positions) |
|
189 | self.extrainfo = [0] * len(self.positions) | |
@@ -288,7 +290,7 b' class _lazymanifest(object):' | |||||
288 | hlen -= 1 |
|
290 | hlen -= 1 | |
289 | else: |
|
291 | else: | |
290 | flags = b'' |
|
292 | flags = b'' | |
291 | if hlen not in (40, 64): |
|
293 | if hlen != 2 * self._nodelen: | |
292 | raise error.StorageError(b'Invalid manifest line') |
|
294 | raise error.StorageError(b'Invalid manifest line') | |
293 | hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen) |
|
295 | hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen) | |
294 | return (hashval, flags) |
|
296 | return (hashval, flags) | |
@@ -344,6 +346,7 b' class _lazymanifest(object):' | |||||
344 | def copy(self): |
|
346 | def copy(self): | |
345 | # XXX call _compact like in C? |
|
347 | # XXX call _compact like in C? | |
346 | return _lazymanifest( |
|
348 | return _lazymanifest( | |
|
349 | self._nodelen, | |||
347 | self.data, |
|
350 | self.data, | |
348 | self.positions, |
|
351 | self.positions, | |
349 | self.extrainfo, |
|
352 | self.extrainfo, | |
@@ -454,7 +457,7 b' class _lazymanifest(object):' | |||||
454 |
|
457 | |||
455 | def filtercopy(self, filterfn): |
|
458 | def filtercopy(self, filterfn): | |
456 | # XXX should be optimized |
|
459 | # XXX should be optimized | |
457 | c = _lazymanifest(b'') |
|
460 | c = _lazymanifest(self._nodelen, b'') | |
458 | for f, n, fl in self.iterentries(): |
|
461 | for f, n, fl in self.iterentries(): | |
459 | if filterfn(f): |
|
462 | if filterfn(f): | |
460 | c[f] = n, fl |
|
463 | c[f] = n, fl | |
@@ -469,8 +472,9 b' except AttributeError:' | |||||
469 |
|
472 | |||
470 | @interfaceutil.implementer(repository.imanifestdict) |
|
473 | @interfaceutil.implementer(repository.imanifestdict) | |
471 | class manifestdict(object): |
|
474 | class manifestdict(object): | |
472 | def __init__(self, data=b''): |
|
475 | def __init__(self, nodelen, data=b''): | |
473 | self._lm = _lazymanifest(data) |
|
476 | self._nodelen = nodelen | |
|
477 | self._lm = _lazymanifest(nodelen, data) | |||
474 |
|
478 | |||
475 | def __getitem__(self, key): |
|
479 | def __getitem__(self, key): | |
476 | return self._lm[key][0] |
|
480 | return self._lm[key][0] | |
@@ -578,14 +582,14 b' class manifestdict(object):' | |||||
578 | return self.copy() |
|
582 | return self.copy() | |
579 |
|
583 | |||
580 | if self._filesfastpath(match): |
|
584 | if self._filesfastpath(match): | |
581 | m = manifestdict() |
|
585 | m = manifestdict(self._nodelen) | |
582 | lm = self._lm |
|
586 | lm = self._lm | |
583 | for fn in match.files(): |
|
587 | for fn in match.files(): | |
584 | if fn in lm: |
|
588 | if fn in lm: | |
585 | m._lm[fn] = lm[fn] |
|
589 | m._lm[fn] = lm[fn] | |
586 | return m |
|
590 | return m | |
587 |
|
591 | |||
588 | m = manifestdict() |
|
592 | m = manifestdict(self._nodelen) | |
589 | m._lm = self._lm.filtercopy(match) |
|
593 | m._lm = self._lm.filtercopy(match) | |
590 | return m |
|
594 | return m | |
591 |
|
595 | |||
@@ -628,7 +632,7 b' class manifestdict(object):' | |||||
628 | return b'' |
|
632 | return b'' | |
629 |
|
633 | |||
630 | def copy(self): |
|
634 | def copy(self): | |
631 | c = manifestdict() |
|
635 | c = manifestdict(self._nodelen) | |
632 | c._lm = self._lm.copy() |
|
636 | c._lm = self._lm.copy() | |
633 | return c |
|
637 | return c | |
634 |
|
638 | |||
@@ -795,6 +799,7 b' class treemanifest(object):' | |||||
795 | self._dir = dir |
|
799 | self._dir = dir | |
796 | self.nodeconstants = nodeconstants |
|
800 | self.nodeconstants = nodeconstants | |
797 | self._node = self.nodeconstants.nullid |
|
801 | self._node = self.nodeconstants.nullid | |
|
802 | self._nodelen = self.nodeconstants.nodelen | |||
798 | self._loadfunc = _noop |
|
803 | self._loadfunc = _noop | |
799 | self._copyfunc = _noop |
|
804 | self._copyfunc = _noop | |
800 | self._dirty = False |
|
805 | self._dirty = False | |
@@ -1322,7 +1327,7 b' class treemanifest(object):' | |||||
1322 |
|
1327 | |||
1323 | def parse(self, text, readsubtree): |
|
1328 | def parse(self, text, readsubtree): | |
1324 | selflazy = self._lazydirs |
|
1329 | selflazy = self._lazydirs | |
1325 | for f, n, fl in _parse(text): |
|
1330 | for f, n, fl in _parse(self._nodelen, text): | |
1326 | if fl == b't': |
|
1331 | if fl == b't': | |
1327 | f = f + b'/' |
|
1332 | f = f + b'/' | |
1328 | # False below means "doesn't need to be copied" and can use the |
|
1333 | # False below means "doesn't need to be copied" and can use the | |
@@ -2019,7 +2024,7 b' class manifestlog(object):' | |||||
2019 | class memmanifestctx(object): |
|
2024 | class memmanifestctx(object): | |
2020 | def __init__(self, manifestlog): |
|
2025 | def __init__(self, manifestlog): | |
2021 | self._manifestlog = manifestlog |
|
2026 | self._manifestlog = manifestlog | |
2022 | self._manifestdict = manifestdict() |
|
2027 | self._manifestdict = manifestdict(manifestlog.nodeconstants.nodelen) | |
2023 |
|
2028 | |||
2024 | def _storage(self): |
|
2029 | def _storage(self): | |
2025 | return self._manifestlog.getstorage(b'') |
|
2030 | return self._manifestlog.getstorage(b'') | |
@@ -2081,8 +2086,9 b' class manifestctx(object):' | |||||
2081 |
|
2086 | |||
2082 | def read(self): |
|
2087 | def read(self): | |
2083 | if self._data is None: |
|
2088 | if self._data is None: | |
2084 |
|
|
2089 | nc = self._manifestlog.nodeconstants | |
2085 |
|
|
2090 | if self._node == nc.nullid: | |
|
2091 | self._data = manifestdict(nc.nodelen) | |||
2086 | else: |
|
2092 | else: | |
2087 | store = self._storage() |
|
2093 | store = self._storage() | |
2088 | if self._node in store.fulltextcache: |
|
2094 | if self._node in store.fulltextcache: | |
@@ -2091,7 +2097,7 b' class manifestctx(object):' | |||||
2091 | text = store.revision(self._node) |
|
2097 | text = store.revision(self._node) | |
2092 | arraytext = bytearray(text) |
|
2098 | arraytext = bytearray(text) | |
2093 | store.fulltextcache[self._node] = arraytext |
|
2099 | store.fulltextcache[self._node] = arraytext | |
2094 | self._data = manifestdict(text) |
|
2100 | self._data = manifestdict(nc.nodelen, text) | |
2095 | return self._data |
|
2101 | return self._data | |
2096 |
|
2102 | |||
2097 | def readfast(self, shallow=False): |
|
2103 | def readfast(self, shallow=False): | |
@@ -2118,7 +2124,7 b' class manifestctx(object):' | |||||
2118 | store = self._storage() |
|
2124 | store = self._storage() | |
2119 | r = store.rev(self._node) |
|
2125 | r = store.rev(self._node) | |
2120 | d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) |
|
2126 | d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) | |
2121 | return manifestdict(d) |
|
2127 | return manifestdict(store.nodeconstants.nodelen, d) | |
2122 |
|
2128 | |||
2123 | def find(self, key): |
|
2129 | def find(self, key): | |
2124 | return self.read().find(key) |
|
2130 | return self.read().find(key) | |
@@ -2244,7 +2250,7 b' class treemanifestctx(object):' | |||||
2244 | if shallow: |
|
2250 | if shallow: | |
2245 | r = store.rev(self._node) |
|
2251 | r = store.rev(self._node) | |
2246 | d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) |
|
2252 | d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) | |
2247 | return manifestdict(d) |
|
2253 | return manifestdict(store.nodeconstants.nodelen, d) | |
2248 | else: |
|
2254 | else: | |
2249 | # Need to perform a slow delta |
|
2255 | # Need to perform a slow delta | |
2250 | r0 = store.deltaparent(store.rev(self._node)) |
|
2256 | r0 = store.deltaparent(store.rev(self._node)) | |
@@ -2273,7 +2279,9 b' class treemanifestctx(object):' | |||||
2273 | return self.readdelta(shallow=shallow) |
|
2279 | return self.readdelta(shallow=shallow) | |
2274 |
|
2280 | |||
2275 | if shallow: |
|
2281 | if shallow: | |
2276 |
return manifestdict( |
|
2282 | return manifestdict( | |
|
2283 | store.nodeconstants.nodelen, store.revision(self._node) | |||
|
2284 | ) | |||
2277 | else: |
|
2285 | else: | |
2278 | return self.read() |
|
2286 | return self.read() | |
2279 |
|
2287 |
@@ -80,7 +80,7 b' def _importfrom(pkgname, modname):' | |||||
80 | ('cext', 'bdiff'): 3, |
|
80 | ('cext', 'bdiff'): 3, | |
81 | ('cext', 'mpatch'): 1, |
|
81 | ('cext', 'mpatch'): 1, | |
82 | ('cext', 'osutil'): 4, |
|
82 | ('cext', 'osutil'): 4, | |
83 |
('cext', 'parsers'): 1 |
|
83 | ('cext', 'parsers'): 18, | |
84 | } |
|
84 | } | |
85 |
|
85 | |||
86 | # map import request to other package or module |
|
86 | # map import request to other package or module |
@@ -81,12 +81,12 b' class basemanifesttests(object):' | |||||
81 | raise NotImplementedError('parsemanifest not implemented by test case') |
|
81 | raise NotImplementedError('parsemanifest not implemented by test case') | |
82 |
|
82 | |||
83 | def testEmptyManifest(self): |
|
83 | def testEmptyManifest(self): | |
84 | m = self.parsemanifest(EMTPY_MANIFEST) |
|
84 | m = self.parsemanifest(20, EMTPY_MANIFEST) | |
85 | self.assertEqual(0, len(m)) |
|
85 | self.assertEqual(0, len(m)) | |
86 | self.assertEqual([], list(m)) |
|
86 | self.assertEqual([], list(m)) | |
87 |
|
87 | |||
88 | def testManifest(self): |
|
88 | def testManifest(self): | |
89 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
89 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
90 | self.assertEqual([b'bar/baz/qux.py', b'foo'], list(m)) |
|
90 | self.assertEqual([b'bar/baz/qux.py', b'foo'], list(m)) | |
91 | self.assertEqual(BIN_HASH_2, m[b'bar/baz/qux.py']) |
|
91 | self.assertEqual(BIN_HASH_2, m[b'bar/baz/qux.py']) | |
92 | self.assertEqual(b'l', m.flags(b'bar/baz/qux.py')) |
|
92 | self.assertEqual(b'l', m.flags(b'bar/baz/qux.py')) | |
@@ -95,20 +95,16 b' class basemanifesttests(object):' | |||||
95 | with self.assertRaises(KeyError): |
|
95 | with self.assertRaises(KeyError): | |
96 | m[b'wat'] |
|
96 | m[b'wat'] | |
97 |
|
97 | |||
98 | def testManifestLongHashes(self): |
|
|||
99 | m = self.parsemanifest(b'a\0' + b'f' * 64 + b'\n') |
|
|||
100 | self.assertEqual(binascii.unhexlify(b'f' * 64), m[b'a']) |
|
|||
101 |
|
||||
102 | def testSetItem(self): |
|
98 | def testSetItem(self): | |
103 | want = BIN_HASH_1 |
|
99 | want = BIN_HASH_1 | |
104 |
|
100 | |||
105 | m = self.parsemanifest(EMTPY_MANIFEST) |
|
101 | m = self.parsemanifest(20, EMTPY_MANIFEST) | |
106 | m[b'a'] = want |
|
102 | m[b'a'] = want | |
107 | self.assertIn(b'a', m) |
|
103 | self.assertIn(b'a', m) | |
108 | self.assertEqual(want, m[b'a']) |
|
104 | self.assertEqual(want, m[b'a']) | |
109 | self.assertEqual(b'a\0' + HASH_1 + b'\n', m.text()) |
|
105 | self.assertEqual(b'a\0' + HASH_1 + b'\n', m.text()) | |
110 |
|
106 | |||
111 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
107 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
112 | m[b'a'] = want |
|
108 | m[b'a'] = want | |
113 | self.assertEqual(want, m[b'a']) |
|
109 | self.assertEqual(want, m[b'a']) | |
114 | self.assertEqual(b'a\0' + HASH_1 + b'\n' + A_SHORT_MANIFEST, m.text()) |
|
110 | self.assertEqual(b'a\0' + HASH_1 + b'\n' + A_SHORT_MANIFEST, m.text()) | |
@@ -116,14 +112,14 b' class basemanifesttests(object):' | |||||
116 | def testSetFlag(self): |
|
112 | def testSetFlag(self): | |
117 | want = b'x' |
|
113 | want = b'x' | |
118 |
|
114 | |||
119 | m = self.parsemanifest(EMTPY_MANIFEST) |
|
115 | m = self.parsemanifest(20, EMTPY_MANIFEST) | |
120 | # first add a file; a file-less flag makes no sense |
|
116 | # first add a file; a file-less flag makes no sense | |
121 | m[b'a'] = BIN_HASH_1 |
|
117 | m[b'a'] = BIN_HASH_1 | |
122 | m.setflag(b'a', want) |
|
118 | m.setflag(b'a', want) | |
123 | self.assertEqual(want, m.flags(b'a')) |
|
119 | self.assertEqual(want, m.flags(b'a')) | |
124 | self.assertEqual(b'a\0' + HASH_1 + want + b'\n', m.text()) |
|
120 | self.assertEqual(b'a\0' + HASH_1 + want + b'\n', m.text()) | |
125 |
|
121 | |||
126 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
122 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
127 | # first add a file; a file-less flag makes no sense |
|
123 | # first add a file; a file-less flag makes no sense | |
128 | m[b'a'] = BIN_HASH_1 |
|
124 | m[b'a'] = BIN_HASH_1 | |
129 | m.setflag(b'a', want) |
|
125 | m.setflag(b'a', want) | |
@@ -133,7 +129,7 b' class basemanifesttests(object):' | |||||
133 | ) |
|
129 | ) | |
134 |
|
130 | |||
135 | def testCopy(self): |
|
131 | def testCopy(self): | |
136 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
132 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
137 | m[b'a'] = BIN_HASH_1 |
|
133 | m[b'a'] = BIN_HASH_1 | |
138 | m2 = m.copy() |
|
134 | m2 = m.copy() | |
139 | del m |
|
135 | del m | |
@@ -142,7 +138,7 b' class basemanifesttests(object):' | |||||
142 | def testCompaction(self): |
|
138 | def testCompaction(self): | |
143 | unhex = binascii.unhexlify |
|
139 | unhex = binascii.unhexlify | |
144 | h1, h2 = unhex(HASH_1), unhex(HASH_2) |
|
140 | h1, h2 = unhex(HASH_1), unhex(HASH_2) | |
145 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
141 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
146 | m[b'alpha'] = h1 |
|
142 | m[b'alpha'] = h1 | |
147 | m[b'beta'] = h2 |
|
143 | m[b'beta'] = h2 | |
148 | del m[b'foo'] |
|
144 | del m[b'foo'] | |
@@ -164,7 +160,7 b' class basemanifesttests(object):' | |||||
164 | m[b'foo'] |
|
160 | m[b'foo'] | |
165 |
|
161 | |||
166 | def testMatchException(self): |
|
162 | def testMatchException(self): | |
167 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
163 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
168 | match = matchmod.match(util.localpath(b'/repo'), b'', [b're:.*']) |
|
164 | match = matchmod.match(util.localpath(b'/repo'), b'', [b're:.*']) | |
169 |
|
165 | |||
170 | def filt(path): |
|
166 | def filt(path): | |
@@ -177,7 +173,7 b' class basemanifesttests(object):' | |||||
177 | m._matches(match) |
|
173 | m._matches(match) | |
178 |
|
174 | |||
179 | def testRemoveItem(self): |
|
175 | def testRemoveItem(self): | |
180 | m = self.parsemanifest(A_SHORT_MANIFEST) |
|
176 | m = self.parsemanifest(20, A_SHORT_MANIFEST) | |
181 | del m[b'foo'] |
|
177 | del m[b'foo'] | |
182 | with self.assertRaises(KeyError): |
|
178 | with self.assertRaises(KeyError): | |
183 | m[b'foo'] |
|
179 | m[b'foo'] | |
@@ -193,9 +189,9 b' class basemanifesttests(object):' | |||||
193 | addl = b'z-only-in-left\0' + HASH_1 + b'\n' |
|
189 | addl = b'z-only-in-left\0' + HASH_1 + b'\n' | |
194 | addr = b'z-only-in-right\0' + HASH_2 + b'x\n' |
|
190 | addr = b'z-only-in-right\0' + HASH_2 + b'x\n' | |
195 | left = self.parsemanifest( |
|
191 | left = self.parsemanifest( | |
196 | A_SHORT_MANIFEST.replace(HASH_1, HASH_3 + b'x') + addl |
|
192 | 20, A_SHORT_MANIFEST.replace(HASH_1, HASH_3 + b'x') + addl | |
197 | ) |
|
193 | ) | |
198 | right = self.parsemanifest(A_SHORT_MANIFEST + addr) |
|
194 | right = self.parsemanifest(20, A_SHORT_MANIFEST + addr) | |
199 | want = { |
|
195 | want = { | |
200 | b'foo': ((BIN_HASH_3, b'x'), (BIN_HASH_1, b'')), |
|
196 | b'foo': ((BIN_HASH_3, b'x'), (BIN_HASH_1, b'')), | |
201 | b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), |
|
197 | b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), | |
@@ -208,14 +204,18 b' class basemanifesttests(object):' | |||||
208 | b'foo': (MISSING, (BIN_HASH_3, b'x')), |
|
204 | b'foo': (MISSING, (BIN_HASH_3, b'x')), | |
209 | b'z-only-in-left': (MISSING, (BIN_HASH_1, b'')), |
|
205 | b'z-only-in-left': (MISSING, (BIN_HASH_1, b'')), | |
210 | } |
|
206 | } | |
211 | self.assertEqual(want, self.parsemanifest(EMTPY_MANIFEST).diff(left)) |
|
207 | self.assertEqual( | |
|
208 | want, self.parsemanifest(20, EMTPY_MANIFEST).diff(left) | |||
|
209 | ) | |||
212 |
|
210 | |||
213 | want = { |
|
211 | want = { | |
214 | b'bar/baz/qux.py': ((BIN_HASH_2, b'l'), MISSING), |
|
212 | b'bar/baz/qux.py': ((BIN_HASH_2, b'l'), MISSING), | |
215 | b'foo': ((BIN_HASH_3, b'x'), MISSING), |
|
213 | b'foo': ((BIN_HASH_3, b'x'), MISSING), | |
216 | b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), |
|
214 | b'z-only-in-left': ((BIN_HASH_1, b''), MISSING), | |
217 | } |
|
215 | } | |
218 | self.assertEqual(want, left.diff(self.parsemanifest(EMTPY_MANIFEST))) |
|
216 | self.assertEqual( | |
|
217 | want, left.diff(self.parsemanifest(20, EMTPY_MANIFEST)) | |||
|
218 | ) | |||
219 | copy = right.copy() |
|
219 | copy = right.copy() | |
220 | del copy[b'z-only-in-right'] |
|
220 | del copy[b'z-only-in-right'] | |
221 | del right[b'foo'] |
|
221 | del right[b'foo'] | |
@@ -225,7 +225,7 b' class basemanifesttests(object):' | |||||
225 | } |
|
225 | } | |
226 | self.assertEqual(want, right.diff(copy)) |
|
226 | self.assertEqual(want, right.diff(copy)) | |
227 |
|
227 | |||
228 | short = self.parsemanifest(A_SHORT_MANIFEST) |
|
228 | short = self.parsemanifest(20, A_SHORT_MANIFEST) | |
229 | pruned = short.copy() |
|
229 | pruned = short.copy() | |
230 | del pruned[b'foo'] |
|
230 | del pruned[b'foo'] | |
231 | want = { |
|
231 | want = { | |
@@ -247,27 +247,27 b' class basemanifesttests(object):' | |||||
247 | l + b'\n' for l in reversed(A_SHORT_MANIFEST.split(b'\n')) if l |
|
247 | l + b'\n' for l in reversed(A_SHORT_MANIFEST.split(b'\n')) if l | |
248 | ) |
|
248 | ) | |
249 | try: |
|
249 | try: | |
250 | self.parsemanifest(backwards) |
|
250 | self.parsemanifest(20, backwards) | |
251 | self.fail('Should have raised ValueError') |
|
251 | self.fail('Should have raised ValueError') | |
252 | except ValueError as v: |
|
252 | except ValueError as v: | |
253 | self.assertIn('Manifest lines not in sorted order.', str(v)) |
|
253 | self.assertIn('Manifest lines not in sorted order.', str(v)) | |
254 |
|
254 | |||
255 | def testNoTerminalNewline(self): |
|
255 | def testNoTerminalNewline(self): | |
256 | try: |
|
256 | try: | |
257 | self.parsemanifest(A_SHORT_MANIFEST + b'wat') |
|
257 | self.parsemanifest(20, A_SHORT_MANIFEST + b'wat') | |
258 | self.fail('Should have raised ValueError') |
|
258 | self.fail('Should have raised ValueError') | |
259 | except ValueError as v: |
|
259 | except ValueError as v: | |
260 | self.assertIn('Manifest did not end in a newline.', str(v)) |
|
260 | self.assertIn('Manifest did not end in a newline.', str(v)) | |
261 |
|
261 | |||
262 | def testNoNewLineAtAll(self): |
|
262 | def testNoNewLineAtAll(self): | |
263 | try: |
|
263 | try: | |
264 | self.parsemanifest(b'wat') |
|
264 | self.parsemanifest(20, b'wat') | |
265 | self.fail('Should have raised ValueError') |
|
265 | self.fail('Should have raised ValueError') | |
266 | except ValueError as v: |
|
266 | except ValueError as v: | |
267 | self.assertIn('Manifest did not end in a newline.', str(v)) |
|
267 | self.assertIn('Manifest did not end in a newline.', str(v)) | |
268 |
|
268 | |||
269 | def testHugeManifest(self): |
|
269 | def testHugeManifest(self): | |
270 | m = self.parsemanifest(A_HUGE_MANIFEST) |
|
270 | m = self.parsemanifest(20, A_HUGE_MANIFEST) | |
271 | self.assertEqual(HUGE_MANIFEST_ENTRIES, len(m)) |
|
271 | self.assertEqual(HUGE_MANIFEST_ENTRIES, len(m)) | |
272 | self.assertEqual(len(m), len(list(m))) |
|
272 | self.assertEqual(len(m), len(list(m))) | |
273 |
|
273 | |||
@@ -275,7 +275,7 b' class basemanifesttests(object):' | |||||
275 | """Tests matches() for a few specific files to make sure that both |
|
275 | """Tests matches() for a few specific files to make sure that both | |
276 | the set of files as well as their flags and nodeids are correct in |
|
276 | the set of files as well as their flags and nodeids are correct in | |
277 | the resulting manifest.""" |
|
277 | the resulting manifest.""" | |
278 | m = self.parsemanifest(A_HUGE_MANIFEST) |
|
278 | m = self.parsemanifest(20, A_HUGE_MANIFEST) | |
279 |
|
279 | |||
280 | match = matchmod.exact([b'file1', b'file200', b'file300']) |
|
280 | match = matchmod.exact([b'file1', b'file200', b'file300']) | |
281 | m2 = m._matches(match) |
|
281 | m2 = m._matches(match) | |
@@ -291,7 +291,7 b' class basemanifesttests(object):' | |||||
291 | """Tests matches() for a small set of specific files, including one |
|
291 | """Tests matches() for a small set of specific files, including one | |
292 | nonexistent file to make sure in only matches against existing files. |
|
292 | nonexistent file to make sure in only matches against existing files. | |
293 | """ |
|
293 | """ | |
294 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
294 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
295 |
|
295 | |||
296 | match = matchmod.exact( |
|
296 | match = matchmod.exact( | |
297 | [b'a/b/c/bar.txt', b'a/b/d/qux.py', b'readme.txt', b'nonexistent'] |
|
297 | [b'a/b/c/bar.txt', b'a/b/d/qux.py', b'readme.txt', b'nonexistent'] | |
@@ -305,7 +305,7 b' class basemanifesttests(object):' | |||||
305 | def testMatchesNonexistentDirectory(self): |
|
305 | def testMatchesNonexistentDirectory(self): | |
306 | """Tests matches() for a relpath match on a directory that doesn't |
|
306 | """Tests matches() for a relpath match on a directory that doesn't | |
307 | actually exist.""" |
|
307 | actually exist.""" | |
308 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
308 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
309 |
|
309 | |||
310 | match = matchmod.match( |
|
310 | match = matchmod.match( | |
311 | util.localpath(b'/repo'), b'', [b'a/f'], default=b'relpath' |
|
311 | util.localpath(b'/repo'), b'', [b'a/f'], default=b'relpath' | |
@@ -316,7 +316,7 b' class basemanifesttests(object):' | |||||
316 |
|
316 | |||
317 | def testMatchesExactLarge(self): |
|
317 | def testMatchesExactLarge(self): | |
318 | """Tests matches() for files matching a large list of exact files.""" |
|
318 | """Tests matches() for files matching a large list of exact files.""" | |
319 | m = self.parsemanifest(A_HUGE_MANIFEST) |
|
319 | m = self.parsemanifest(20, A_HUGE_MANIFEST) | |
320 |
|
320 | |||
321 | flist = m.keys()[80:300] |
|
321 | flist = m.keys()[80:300] | |
322 | match = matchmod.exact(flist) |
|
322 | match = matchmod.exact(flist) | |
@@ -326,7 +326,7 b' class basemanifesttests(object):' | |||||
326 |
|
326 | |||
327 | def testMatchesFull(self): |
|
327 | def testMatchesFull(self): | |
328 | '''Tests matches() for what should be a full match.''' |
|
328 | '''Tests matches() for what should be a full match.''' | |
329 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
329 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
330 |
|
330 | |||
331 | match = matchmod.match(util.localpath(b'/repo'), b'', [b'']) |
|
331 | match = matchmod.match(util.localpath(b'/repo'), b'', [b'']) | |
332 | m2 = m._matches(match) |
|
332 | m2 = m._matches(match) | |
@@ -336,7 +336,7 b' class basemanifesttests(object):' | |||||
336 | def testMatchesDirectory(self): |
|
336 | def testMatchesDirectory(self): | |
337 | """Tests matches() on a relpath match on a directory, which should |
|
337 | """Tests matches() on a relpath match on a directory, which should | |
338 | match against all files within said directory.""" |
|
338 | match against all files within said directory.""" | |
339 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
339 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
340 |
|
340 | |||
341 | match = matchmod.match( |
|
341 | match = matchmod.match( | |
342 | util.localpath(b'/repo'), b'', [b'a/b'], default=b'relpath' |
|
342 | util.localpath(b'/repo'), b'', [b'a/b'], default=b'relpath' | |
@@ -362,7 +362,7 b' class basemanifesttests(object):' | |||||
362 | """Tests matches() on an exact match on a directory, which should |
|
362 | """Tests matches() on an exact match on a directory, which should | |
363 | result in an empty manifest because you can't perform an exact match |
|
363 | result in an empty manifest because you can't perform an exact match | |
364 | against a directory.""" |
|
364 | against a directory.""" | |
365 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
365 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
366 |
|
366 | |||
367 | match = matchmod.exact([b'a/b']) |
|
367 | match = matchmod.exact([b'a/b']) | |
368 | m2 = m._matches(match) |
|
368 | m2 = m._matches(match) | |
@@ -372,7 +372,7 b' class basemanifesttests(object):' | |||||
372 | def testMatchesCwd(self): |
|
372 | def testMatchesCwd(self): | |
373 | """Tests matches() on a relpath match with the current directory ('.') |
|
373 | """Tests matches() on a relpath match with the current directory ('.') | |
374 | when not in the root directory.""" |
|
374 | when not in the root directory.""" | |
375 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
375 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
376 |
|
376 | |||
377 | match = matchmod.match( |
|
377 | match = matchmod.match( | |
378 | util.localpath(b'/repo'), b'a/b', [b'.'], default=b'relpath' |
|
378 | util.localpath(b'/repo'), b'a/b', [b'.'], default=b'relpath' | |
@@ -397,7 +397,7 b' class basemanifesttests(object):' | |||||
397 | def testMatchesWithPattern(self): |
|
397 | def testMatchesWithPattern(self): | |
398 | """Tests matches() for files matching a pattern that reside |
|
398 | """Tests matches() for files matching a pattern that reside | |
399 | deeper than the specified directory.""" |
|
399 | deeper than the specified directory.""" | |
400 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
400 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
401 |
|
401 | |||
402 | match = matchmod.match(util.localpath(b'/repo'), b'', [b'a/b/*/*.txt']) |
|
402 | match = matchmod.match(util.localpath(b'/repo'), b'', [b'a/b/*/*.txt']) | |
403 | m2 = m._matches(match) |
|
403 | m2 = m._matches(match) | |
@@ -408,8 +408,12 b' class basemanifesttests(object):' | |||||
408 |
|
408 | |||
409 |
|
409 | |||
410 | class testmanifestdict(unittest.TestCase, basemanifesttests): |
|
410 | class testmanifestdict(unittest.TestCase, basemanifesttests): | |
411 | def parsemanifest(self, text): |
|
411 | def parsemanifest(self, nodelen, text): | |
412 | return manifestmod.manifestdict(text) |
|
412 | return manifestmod.manifestdict(nodelen, text) | |
|
413 | ||||
|
414 | def testManifestLongHashes(self): | |||
|
415 | m = self.parsemanifest(32, b'a\0' + b'f' * 64 + b'\n') | |||
|
416 | self.assertEqual(binascii.unhexlify(b'f' * 64), m[b'a']) | |||
413 |
|
417 | |||
414 | def testObviouslyBogusManifest(self): |
|
418 | def testObviouslyBogusManifest(self): | |
415 | # This is a 163k manifest that came from oss-fuzz. It was a |
|
419 | # This is a 163k manifest that came from oss-fuzz. It was a | |
@@ -433,15 +437,15 b' class testmanifestdict(unittest.TestCase' | |||||
433 | b'\xac\xbe' |
|
437 | b'\xac\xbe' | |
434 | ) |
|
438 | ) | |
435 | with self.assertRaises(ValueError): |
|
439 | with self.assertRaises(ValueError): | |
436 | self.parsemanifest(data) |
|
440 | self.parsemanifest(20, data) | |
437 |
|
441 | |||
438 |
|
442 | |||
439 | class testtreemanifest(unittest.TestCase, basemanifesttests): |
|
443 | class testtreemanifest(unittest.TestCase, basemanifesttests): | |
440 | def parsemanifest(self, text): |
|
444 | def parsemanifest(self, nodelen, text): | |
441 | return manifestmod.treemanifest(sha1nodeconstants, b'', text) |
|
445 | return manifestmod.treemanifest(sha1nodeconstants, b'', text) | |
442 |
|
446 | |||
443 | def testWalkSubtrees(self): |
|
447 | def testWalkSubtrees(self): | |
444 | m = self.parsemanifest(A_DEEPER_MANIFEST) |
|
448 | m = self.parsemanifest(20, A_DEEPER_MANIFEST) | |
445 |
|
449 | |||
446 | dirs = [s._dir for s in m.walksubtrees()] |
|
450 | dirs = [s._dir for s in m.walksubtrees()] | |
447 | self.assertEqual( |
|
451 | self.assertEqual( |
General Comments 0
You need to be logged in to leave comments.
Login now