diff --git a/mercurial/cext/bdiff.c b/mercurial/cext/bdiff.c
--- a/mercurial/cext/bdiff.c
+++ b/mercurial/cext/bdiff.c
@@ -182,6 +182,55 @@
 	return result ? result : PyErr_NoMemory();
 }
 
+bool sliceintolist(PyObject *list, Py_ssize_t destidx,
+		   const char *source, Py_ssize_t len) {
+	PyObject *sliced = PyString_FromStringAndSize(source, len);
+	if (sliced == NULL)
+		return false;
+	PyList_SetItem(list, destidx, sliced);
+	return true;
+}
+
+static PyObject *splitnewlines(PyObject *self, PyObject *args)
+{
+	const char *text;
+	int i, start = 0;
+	Py_ssize_t nelts = 0, size;
+	PyObject *result;
+
+	if (!PyArg_ParseTuple(args, "s#", &text, &size))
+		goto abort;
+	if (!size) {
+		return PyList_New(0);
+	}
+	/* This loops to size-1 because if the last byte is a newline,
+	 * we don't want to perform a split there. */
+	for (i = 0; i < size - 1; ++i) {
+		if (text[i] == '\n') {
+			++nelts;
+		}
+	}
+	if ((result = PyList_New(nelts+1)) == NULL)
+		goto abort;
+	nelts = 0;
+	for (i = 0; i < size - 1; ++i) {
+		if (text[i] == '\n') {
+			if (!sliceintolist(
+				    result, nelts++, text+start, i-start+1))
+				goto abort;
+			start = i+1;
+		}
+	}
+	if (start < size) {
+		if (!sliceintolist(result, nelts++, text+start, size-start))
+			goto abort;
+	}
+	return result;
+abort:
+	Py_XDECREF(result);
+	return NULL;
+}
+
 
 static char mdiff_doc[] = "Efficient binary diff.";
 
@@ -189,6 +238,8 @@
 	{"bdiff", bdiff, METH_VARARGS, "calculate a binary diff\n"},
 	{"blocks", blocks, METH_VARARGS, "find a list of matching lines\n"},
 	{"fixws", fixws, METH_VARARGS, "normalize diff whitespaces\n"},
+	{"splitnewlines", splitnewlines, METH_VARARGS,
+	 "like str.splitlines, but only split on newlines\n"},
 	{NULL, NULL}
 };
 
diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py
--- a/mercurial/mdiff.py
+++ b/mercurial/mdiff.py
@@ -40,6 +40,8 @@
             lines[-1] = lines[-1][:-1]
     return lines
 
+splitnewlines = getattr(bdiff, 'splitnewlines', splitnewlines)
+
 class diffopts(object):
     '''context is the number of context lines
     text treats all files as text