Patchwork D12179: revlog: register changelogv2 C implementation in parsers

login
register
mail settings
Submitter phabricator
Date Feb. 14, 2022, 6:07 p.m.
Message ID <differential-rev-PHID-DREV-zgtocrf6oqt4w53ykknx-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50514/
State New
Headers show

Comments

phabricator - Feb. 14, 2022, 6:07 p.m.
pacien created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This allows Python code to make use of the C implementation of the changelogv2
  base operations when the C extensions are enabled.
  
  The `format_version` values are now shared between the C and Python sides,
  avoiding an additional translation for the selection of the format version to
  use.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D12179

AFFECTED FILES
  mercurial/cext/revlog.c
  mercurial/pure/parsers.py
  mercurial/revlog.py
  tests/test-parseindex2.py

CHANGE DETAILS




To: pacien, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-parseindex2.py b/tests/test-parseindex2.py
--- a/tests/test-parseindex2.py
+++ b/tests/test-parseindex2.py
@@ -134,8 +134,8 @@ 
 )
 
 
-def parse_index2(data, inline, revlogv2=False):
-    index, chunkcache = parsers.parse_index2(data, inline, revlogv2=revlogv2)
+def parse_index2(data, inline, format=constants.REVLOGV1):
+    index, chunkcache = parsers.parse_index2(data, inline, format=format)
     return list(index), chunkcache
 
 
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -101,6 +101,7 @@ 
 REVLOGV0
 REVLOGV1
 REVLOGV2
+CHANGELOGV2
 FLAG_INLINE_DATA
 FLAG_GENERALDELTA
 REVLOG_DEFAULT_FLAGS
@@ -199,16 +200,13 @@ 
 
 def parse_index_v2(data, inline):
     # call the C implementation to parse the index data
-    index, cache = parsers.parse_index2(data, inline, revlogv2=True)
+    index, cache = parsers.parse_index2(data, inline, format=REVLOGV2)
     return index, cache
 
 
 def parse_index_cl_v2(data, inline):
     # call the C implementation to parse the index data
-    assert not inline
-    from .pure.parsers import parse_index_cl_v2
-
-    index, cache = parse_index_cl_v2(data)
+    index, cache = parsers.parse_index2(data, inline, format=CHANGELOGV2)
     return index, cache
 
 
diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -799,9 +799,14 @@ 
         return self._offsets[i]
 
 
-def parse_index2(data, inline, revlogv2=False):
+def parse_index2(data, inline, format=revlog_constants.REVLOGV1):
+    if format == revlog_constants.CHANGELOGV2:
+        return parse_index_cl_v2(data)
     if not inline:
-        cls = IndexObject2 if revlogv2 else IndexObject
+        if format == revlog_constants.REVLOGV2:
+            cls = IndexObject2
+        else:
+            cls = IndexObject
         return cls(data), None
     cls = InlinedIndexObject
     return cls(data, inline), (0, data)
diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
--- a/mercurial/cext/revlog.c
+++ b/mercurial/cext/revlog.c
@@ -103,8 +103,7 @@ 
 	                  */
 	long rust_ext_compat; /* compatibility with being used in rust
 	                         extensions */
-	char format_version;  /* size of index headers. Differs in v1 v.s. v2
-	                         format */
+	long format_version;  /* format version selector (format_*) */
 };
 
 static Py_ssize_t index_length(const indexObject *self)
@@ -133,9 +132,14 @@ 
 /* A Revlogv2 index entry is 96 bytes long. */
 static const long v2_entry_size = 96;
 
-static const long format_v1 = 1;  /* Internal only, could be any number */
-static const long format_v2 = 2;  /* Internal only, could be any number */
-static const long format_cl2 = 3; /* Internal only, could be any number */
+/* A Changelogv2 index entry is 96 bytes long. */
+static const long cl2_entry_size = 96;
+
+/* Internal format version.
+ * Must match their counterparts in revlogutils/constants.py */
+static const long format_v1 = 1;       /* constants.py: REVLOGV1 */
+static const long format_v2 = 0xDEAD;  /* constants.py: REVLOGV2 */
+static const long format_cl2 = 0xD34D; /* constants.py: CHANGELOGV2 */
 
 static const long entry_v1_offset_high = 0;
 static const long entry_v1_offset_offset_flags = 4;
@@ -2973,10 +2977,10 @@ 
 
 static int index_init(indexObject *self, PyObject *args, PyObject *kwargs)
 {
-	PyObject *data_obj, *inlined_obj, *revlogv2;
+	PyObject *data_obj, *inlined_obj;
 	Py_ssize_t size;
 
-	static char *kwlist[] = {"data", "inlined", "revlogv2", NULL};
+	static char *kwlist[] = {"data", "inlined", "format", NULL};
 
 	/* Initialize before argument-checking to avoid index_dealloc() crash.
 	 */
@@ -2993,10 +2997,11 @@ 
 	self->nodelen = 20;
 	self->nullentry = NULL;
 	self->rust_ext_compat = 1;
-
-	revlogv2 = NULL;
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", kwlist,
-	                                 &data_obj, &inlined_obj, &revlogv2))
+	self->format_version = format_v1;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|l", kwlist,
+	                                 &data_obj, &inlined_obj,
+	                                 &(self->format_version)))
 		return -1;
 	if (!PyObject_CheckBuffer(data_obj)) {
 		PyErr_SetString(PyExc_TypeError,
@@ -3008,12 +3013,12 @@ 
 		return -1;
 	}
 
-	if (revlogv2 && PyObject_IsTrue(revlogv2)) {
-		self->format_version = format_v2;
+	if (self->format_version == format_v1) {
+		self->entry_size = v1_entry_size;
+	} else if (self->format_version == format_v2) {
 		self->entry_size = v2_entry_size;
-	} else {
-		self->format_version = format_v1;
-		self->entry_size = v1_entry_size;
+	} else if (self->format_version == format_cl2) {
+		self->entry_size = cl2_entry_size;
 	}
 
 	self->nullentry =