Patchwork [13,of,22] obsstore: let read marker API optionally return marker offsets

login
register
mail settings
Submitter Jun Wu
Date June 4, 2017, 11:59 p.m.
Message ID <a159006b556c924bc0b9.1496620765@x1c>
Download mbox | patch
Permalink /patch/21193/
State Accepted
Headers show

Comments

Jun Wu - June 4, 2017, 11:59 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1496596321 25200
#      Sun Jun 04 10:12:01 2017 -0700
# Node ID a159006b556c924bc0b9cb01c251574b44383063
# Parent  985b38cca3131ca81a961ba4ab2006a3ef23ebb0
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r a159006b556c
obsstore: let read marker API optionally return marker offsets

This patch adds "withoffsets" flag to all obsmarker reading APIs, once set,
(markers, offsets) will be returned instead of just markers.

Offsets will be useful as "marker identities" to be stored in radixlink.

Patch

diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c
--- a/mercurial/cext/parsers.c
+++ b/mercurial/cext/parsers.c
@@ -859,8 +859,12 @@  static PyObject *fm1readmarkers(PyObject
 	const char *data, *dataend;
 	int datalen;
+	int withoffsets = 0;
 	Py_ssize_t offset, stop;
 	PyObject *markers = NULL;
+	PyObject *offsets = NULL;
+	PyObject *result = NULL;
 
-	if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
+	if (!PyArg_ParseTuple(args, "s#nn|i", &data, &datalen, &offset, &stop,
+				&withoffsets)) {
 		return NULL;
 	}
@@ -868,6 +872,10 @@  static PyObject *fm1readmarkers(PyObject
 	data += offset;
 	markers = PyList_New(0);
-	if (!markers) {
-		return NULL;
+	if (!markers)
+		goto bail;
+	if (withoffsets) {
+		offsets = PyList_New(0);
+		if (!offsets)
+			goto bail;
 	}
 	while (offset < stop) {
@@ -883,10 +891,29 @@  static PyObject *fm1readmarkers(PyObject
 			goto bail;
 		}
+		if (withoffsets) {
+			PyObject *pyoffset = PyInt_FromSsize_t(offset);
+			if (!pyoffset)
+				goto bail;
+			error = PyList_Append(offsets, pyoffset);
+			Py_DECREF(pyoffset);
+			if (error)
+				goto bail;
+		}
 		data += msize;
 		offset += msize;
 	}
-	return markers;
+	if (withoffsets) {
+		result = Py_BuildValue("(OO)", markers, offsets);
+		if (!result)
+			goto bail;
+		Py_DECREF(markers);
+		Py_DECREF(offsets);
+	} else {
+		result = markers;
+	}
+	return result;
 bail:
-	Py_DECREF(markers);
+	Py_XDECREF(markers);
+	Py_XDECREF(offsets);
 	return NULL;
 }
@@ -925,5 +952,5 @@  void manifest_module_init(PyObject *mod)
 void revlog_module_init(PyObject *mod);
 
-static const int version = 1;
+static const int version = 2;
 
 static void module_init(PyObject *mod)
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -179,7 +179,11 @@  usingsha256 = 2
 _fm0fnodesize = _calcsize(_fm0node)
 
-def _fm0readmarkers(data, off, stop):
+def _fm0readmarkers(data, off, stop, withoffsets=False):
     # Loop on markers
+    markers = []
+    offsets = []
     while off < stop:
+        if withoffsets:
+            offsets.append(off)
         # read fixed part
         cur = data[off:off + _fm0fsize]
@@ -228,5 +232,9 @@  def _fm0readmarkers(data, off, stop):
         metadata = tuple(sorted(metadata.iteritems()))
 
-        yield (pre, sucs, flags, metadata, date, parents)
+        markers.append((pre, sucs, flags, metadata, date, parents))
+    if withoffsets:
+        return markers, offsets
+    else:
+        return markers
 
 def _fm0encodeonemarker(marker):
@@ -317,5 +325,5 @@  def _fm0decodemeta(data):
 _fm1metapairsize = _calcsize('BB')
 
-def _fm1purereadmarkers(data, off, stop):
+def _fm1purereadmarkers(data, off, stop, withoffsets=False):
     # make some global constants local for performance
     noneflag = _fm1parentnone
@@ -333,5 +341,9 @@  def _fm1purereadmarkers(data, off, stop)
     ufixed = struct.Struct(_fm1fixed).unpack
 
+    markers = []
+    offsets = []
     while off < stop:
+        if withoffsets:
+            offsets.append(off)
         # read fixed part
         o1 = off + fsize
@@ -389,5 +401,10 @@  def _fm1purereadmarkers(data, off, stop)
             off = o2
 
-        yield (prec, sucs, flags, tuple(metadata), (secs, tz * 60), parents)
+        markers.append((prec, sucs, flags, tuple(metadata), (secs, tz * 60),
+                        parents))
+    if withoffsets:
+        return markers, offsets
+    else:
+        return markers
 
 def _fm1encodeonemarker(marker):
@@ -427,9 +444,9 @@  def _fm1encodeonemarker(marker):
     return ''.join(data)
 
-def _fm1readmarkers(data, off, stop):
+def _fm1readmarkers(data, off, stop, withoffsets=False):
     native = getattr(parsers, 'fm1readmarkers', None)
     if not native:
-        return _fm1purereadmarkers(data, off, stop)
-    return native(data, off, stop)
+        return _fm1purereadmarkers(data, off, stop, withoffsets)
+    return native(data, off, stop, withoffsets)
 
 # mapping to read/write various marker formats
@@ -442,5 +459,5 @@  def _readmarkerversion(data):
 
 @util.nogc
-def _readmarkers(data, off=None, stop=None):
+def _readmarkers(data, off=None, stop=None, withoffsets=False):
     """Read and enumerate markers from raw data"""
     diskversion = _readmarkerversion(data)
@@ -452,5 +469,5 @@  def _readmarkers(data, off=None, stop=No
         msg = _('parsing obsolete marker: unknown version %r') % diskversion
         raise error.UnknownVersion(msg, version=diskversion)
-    return diskversion, formats[diskversion][0](data, off, stop)
+    return diskversion, formats[diskversion][0](data, off, stop, withoffsets)
 
 def encodeheader(version=_fm0version):
diff --git a/mercurial/policy.py b/mercurial/policy.py
--- a/mercurial/policy.py
+++ b/mercurial/policy.py
@@ -76,5 +76,5 @@  def _importfrom(pkgname, modname):
     (r'cext', r'mpatch'): 1,
     (r'cext', r'osutil'): 1,
-    (r'cext', r'parsers'): 1,
+    (r'cext', r'parsers'): 2,
     (r'cext', r'radixlink'): 1,
 }