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 }