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 } |