diff mercurial/cext/revlog.c @ 47034:0d8ff1f4ab0c

revlog: add a `entry_binary` method on index The revlog index is already responsible for unpacking the binary entry, it would be simpler to make it responsible for packing them. In practice the C version of the index is already doing this internally. We introduce a "entry_binary" method that return the binary version of an existing revision. The method currently need to also take the revlog header to deal with the "first revision" special case. We will introduce further refactor in a later changeset to split that logic out. Differential Revision: https://phab.mercurial-scm.org/D10508
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 08 Apr 2021 00:01:11 +0200
parents 3c9208702db3
children 4f2b5f9d8cc4
line wrap: on
line diff
--- a/mercurial/cext/revlog.c	Thu Apr 15 12:08:34 2021 +0200
+++ b/mercurial/cext/revlog.c	Thu Apr 08 00:01:11 2021 +0200
@@ -342,6 +342,38 @@
 		                     sidedata_offset, sidedata_comp_len);
 	}
 }
+/*
+ * Return the raw binary string representing a revision
+ */
+static PyObject *index_entry_binary(indexObject *self, PyObject *args)
+{
+	long rev;
+	int header;
+	const char *data;
+	char entry[v2_hdrsize];
+
+	Py_ssize_t length = index_length(self);
+
+	if (!PyArg_ParseTuple(args, "lI", &rev, &header)) {
+		return NULL;
+	}
+	if (rev < 0 || rev >= length) {
+		PyErr_Format(PyExc_ValueError, "revlog index out of range: %ld",
+		             rev);
+		return NULL;
+	};
+
+	data = index_deref(self, rev);
+	if (data == NULL)
+		return NULL;
+	if (rev == 0) {
+		// put the header at the start of the first entry
+		memcpy(entry, data, self->hdrsize);
+		putbe32(header, entry);
+		return PyBytes_FromStringAndSize(entry, self->hdrsize);
+	}
+	return PyBytes_FromStringAndSize(data, self->hdrsize);
+}
 
 /*
  * Return the hash of node corresponding to the given rev.
@@ -2859,6 +2891,8 @@
     {"shortest", (PyCFunction)index_shortest, METH_VARARGS,
      "find length of shortest hex nodeid of a binary ID"},
     {"stats", (PyCFunction)index_stats, METH_NOARGS, "stats for the index"},
+    {"entry_binary", (PyCFunction)index_entry_binary, METH_VARARGS,
+     "return an entry in binary form"},
     {NULL} /* Sentinel */
 };