mercurial/cext/manifest.c
changeset 44702 0b0e72b5d551
parent 44132 f0a4084f82d6
child 45118 d0ef8c1dddd4
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 	}