[PATCH 2 of 2 V3] changelog: fix bug in heads computation

Laurent Charignon lcharignon at fb.com
Thu May 21 17:59:49 CDT 2015


# HG changeset patch
# User Laurent Charignon <lcharignon at fb.com>
# Date 1432248471 25200
#      Thu May 21 15:47:51 2015 -0700
# Node ID 13c35e19e9b943fabee197431f87d098d8c5fdfd
# Parent  facf49ded5ab213fbbd4599c6e50af742de2fe13
changelog: fix bug in heads computation

This patch refactors the native computation of heads. It fixes a bug where
filtered heads in the pending index could be returned by the native code
despite their filtering.

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -1193,7 +1193,7 @@
 
 static PyObject *index_headrevs(indexObject *self, PyObject *args)
 {
-	Py_ssize_t i, len, addlen;
+	int i, j, len;
 	char *nothead = NULL;
 	PyObject *heads = NULL;
 	PyObject *filter = NULL;
@@ -1236,9 +1236,9 @@
 	if (nothead == NULL)
 		goto bail;
 
-	for (i = 0; i < self->raw_length; i++) {
-		const char *data;
-		int parent_1, parent_2, isfiltered;
+	for (i = 0; i < len; i++) {
+		int isfiltered;
+		int parents[2];
 
 		isfiltered = check_filter(filter, i);
 		if (isfiltered == -1) {
@@ -1252,49 +1252,11 @@
 			continue;
 		}
 
-		data = index_deref(self, i);
-		parent_1 = getbe32(data + 24);
-		parent_2 = getbe32(data + 28);
-
-		if (parent_1 >= 0)
-			nothead[parent_1] = 1;
-		if (parent_2 >= 0)
-			nothead[parent_2] = 1;
-	}
-
-	addlen = self->added ? PyList_GET_SIZE(self->added) : 0;
-
-	for (i = 0; i < addlen; i++) {
-		PyObject *rev = PyList_GET_ITEM(self->added, i);
-		PyObject *p1 = PyTuple_GET_ITEM(rev, 5);
-		PyObject *p2 = PyTuple_GET_ITEM(rev, 6);
-		long parent_1, parent_2;
-		int isfiltered;
-
-		if (!PyInt_Check(p1) || !PyInt_Check(p2)) {
-			PyErr_SetString(PyExc_TypeError,
-					"revlog parents are invalid");
-			goto bail;
+		index_get_parents(self, i, parents);
+		for (j = 0; j < 2 ; j++){
+			if (parents[j] >= 0)
+				nothead[parents[j]] = 1;
 		}
-
-		isfiltered = check_filter(filter, i);
-		if (isfiltered == -1) {
-			PyErr_SetString(PyExc_TypeError,
-				"unable to check filter");
-			goto bail;
-		}
-
-		if (isfiltered) {
-			nothead[i] = 1;
-			continue;
-		}
-
-		parent_1 = PyInt_AS_LONG(p1);
-		parent_2 = PyInt_AS_LONG(p2);
-		if (parent_1 >= 0)
-			nothead[parent_1] = 1;
-		if (parent_2 >= 0)
-			nothead[parent_2] = 1;
 	}
 
 	for (i = 0; i < len; i++) {
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -886,3 +886,33 @@
 
 #endif
 
+Test heads computation on pending index changes with obsolescence markers
+  $ cd ..
+  $ cat >$TESTTMP/test_extension.py  << EOF
+  > from mercurial import cmdutil
+  > from mercurial.i18n import _
+  > 
+  > cmdtable = {}
+  > command = cmdutil.command(cmdtable)
+  > @command("amendtransient",[], _('hg amendtransient [rev]'))
+  > def amend(ui, repo, *pats, **opts):
+  >   def commitfunc(ui, repo, message, match, opts):
+  >     return repo.commit(message, repo['.'].user(), repo['.'].date(), match)
+  >   opts['message'] = 'Test'
+  >   opts['logfile'] = None
+  >   cmdutil.amend(ui, repo, commitfunc, repo['.'], {}, pats, opts)
+  >   print repo.changelog.headrevs()
+  > EOF
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > testextension=$TESTTMP/test_extension.py
+  > EOF
+  $ hg init repo-issue-nativerevs-pending-changes
+  $ cd repo-issue-nativerevs-pending-changes
+  $ mkcommit a
+  $ mkcommit b
+  $ hg up ".^"
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo aa > a
+  $ hg amendtransient
+  [1, 3]


More information about the Mercurial-devel mailing list