Mercurial > hg
comparison mercurial/cext/manifest.c @ 44702:0b0e72b5d551
manifest: start removing 40-byte hash restrictions from C code
Differential Revision: https://phab.mercurial-scm.org/D8368
author | Augie Fackler <augie@google.com> |
---|---|
date | Tue, 07 Jan 2020 13:47:29 -0500 |
parents | f0a4084f82d6 |
children | d0ef8c1dddd4 |
comparison
equal
deleted
inserted
replaced
44701:ecbba7b2e444 | 44702:0b0e72b5d551 |
---|---|
51 /* get the node value of a single line */ | 51 /* get the node value of a single line */ |
52 static PyObject *nodeof(line *l) | 52 static PyObject *nodeof(line *l) |
53 { | 53 { |
54 char *s = l->start; | 54 char *s = l->start; |
55 Py_ssize_t llen = pathlen(l); | 55 Py_ssize_t llen = pathlen(l); |
56 Py_ssize_t hlen = l->len - llen - 2; | |
57 Py_ssize_t hlen_raw = 20; | |
56 PyObject *hash; | 58 PyObject *hash; |
57 if (llen + 1 + 40 + 1 > l->len) { /* path '\0' hash '\n' */ | 59 if (llen + 1 + 40 + 1 > l->len) { /* path '\0' hash '\n' */ |
58 PyErr_SetString(PyExc_ValueError, "manifest line too short"); | 60 PyErr_SetString(PyExc_ValueError, "manifest line too short"); |
59 return NULL; | 61 return NULL; |
60 } | 62 } |
61 hash = unhexlify(s + llen + 1, 40); | 63 switch (hlen) { |
64 case 40: /* sha1 */ | |
65 case 41: /* sha1 with cruft for a merge */ | |
66 break; | |
67 case 64: /* new hash */ | |
68 case 65: /* new hash with cruft for a merge */ | |
69 hlen_raw = 32; | |
70 break; | |
71 default: | |
72 PyErr_SetString(PyExc_ValueError, "invalid node length in manifest"); | |
73 return NULL; | |
74 } | |
75 hash = unhexlify(s + llen + 1, hlen_raw * 2); | |
62 if (!hash) { | 76 if (!hash) { |
63 return NULL; | 77 return NULL; |
64 } | 78 } |
65 if (l->hash_suffix != '\0') { | 79 if (l->hash_suffix != '\0') { |
66 char newhash[21]; | 80 char newhash[33]; |
67 memcpy(newhash, PyBytes_AsString(hash), 20); | 81 memcpy(newhash, PyBytes_AsString(hash), hlen_raw); |
68 Py_DECREF(hash); | 82 Py_DECREF(hash); |
69 newhash[20] = l->hash_suffix; | 83 newhash[hlen_raw] = l->hash_suffix; |
70 hash = PyBytes_FromStringAndSize(newhash, 21); | 84 hash = PyBytes_FromStringAndSize(newhash, hlen_raw+1); |
71 } | 85 } |
72 return hash; | 86 return hash; |
73 } | 87 } |
74 | 88 |
75 /* get the node hash and flags of a line as a tuple */ | 89 /* get the node hash and flags of a line as a tuple */ |
76 static PyObject *hashflags(line *l) | 90 static PyObject *hashflags(line *l) |
77 { | 91 { |
78 char *s = l->start; | 92 char *s = l->start; |
79 Py_ssize_t plen = pathlen(l); | 93 Py_ssize_t plen = pathlen(l); |
80 PyObject *hash = nodeof(l); | 94 PyObject *hash = nodeof(l); |
81 | 95 ssize_t hlen; |
82 /* 40 for hash, 1 for null byte, 1 for newline */ | 96 Py_ssize_t hplen, flen; |
83 Py_ssize_t hplen = plen + 42; | |
84 Py_ssize_t flen = l->len - hplen; | |
85 PyObject *flags; | 97 PyObject *flags; |
86 PyObject *tup; | 98 PyObject *tup; |
87 | 99 |
88 if (!hash) | 100 if (!hash) |
89 return NULL; | 101 return NULL; |
102 /* hash is either 20 or 21 bytes for an old hash, so we use a | |
103 ternary here to get the "real" hexlified sha length. */ | |
104 hlen = PyBytes_GET_SIZE(hash) < 22 ? 40 : 64; | |
105 /* 1 for null byte, 1 for newline */ | |
106 hplen = plen + hlen + 2; | |
107 flen = l->len - hplen; | |
108 | |
90 flags = PyBytes_FromStringAndSize(s + hplen - 1, flen); | 109 flags = PyBytes_FromStringAndSize(s + hplen - 1, flen); |
91 if (!flags) { | 110 if (!flags) { |
92 Py_DECREF(hash); | 111 Py_DECREF(hash); |
93 return NULL; | 112 return NULL; |
94 } | 113 } |