mercurial/diffhelpers.c
changeset 4897 4574925db5c0
equal deleted inserted replaced
4896:ee04732fe61d 4897:4574925db5c0
       
     1 /*
       
     2  * diffhelpers.c - helper routines for mpatch
       
     3  *
       
     4  * Copyright 2007 Chris Mason <chris.mason@oracle.com>
       
     5  *
       
     6  * This software may be used and distributed according to the terms
       
     7  * of the GNU General Public License v2, incorporated herein by reference.
       
     8  */
       
     9 
       
    10 #include <Python.h>
       
    11 #include <stdlib.h>
       
    12 #include <string.h>
       
    13 
       
    14 static char diffhelpers_doc[] = "Efficient diff parsing";
       
    15 static PyObject *diffhelpers_Error;
       
    16 
       
    17 
       
    18 /* fixup the last lines of a and b when the patch has no newline at eof */
       
    19 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
       
    20 {
       
    21 	int hunksz = PyList_Size(hunk);
       
    22 	PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
       
    23 	char *l = PyString_AS_STRING(s);
       
    24 	int sz = PyString_GET_SIZE(s);
       
    25 	int alen = PyList_Size(a);
       
    26 	int blen = PyList_Size(b);
       
    27 	char c = l[0];
       
    28 
       
    29 	PyObject *hline = PyString_FromStringAndSize(l, sz-1);
       
    30 	if (c == ' ' || c == '+') {
       
    31 		PyObject *rline = PyString_FromStringAndSize(l+1, sz-2);
       
    32 		PyList_SetItem(b, blen-1, rline);
       
    33 	}
       
    34 	if (c == ' ' || c == '-') {
       
    35 		Py_INCREF(hline);
       
    36 		PyList_SetItem(a, alen-1, hline);
       
    37 	}
       
    38 	PyList_SetItem(hunk, hunksz-1, hline);
       
    39 }
       
    40 
       
    41 /* python callable form of _fix_newline */
       
    42 static PyObject *
       
    43 fix_newline(PyObject *self, PyObject *args)
       
    44 {
       
    45 	PyObject *hunk, *a, *b;
       
    46 	if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
       
    47 		return NULL;
       
    48 	_fix_newline(hunk, a, b);
       
    49 	return Py_BuildValue("l", 0);
       
    50 }
       
    51 
       
    52 /*
       
    53  * read lines from fp into the hunk.  The hunk is parsed into two arrays
       
    54  * a and b.  a gets the old state of the text, b gets the new state
       
    55  * The control char from the hunk is saved when inserting into a, but not b
       
    56  * (for performance while deleting files)
       
    57  */
       
    58 static PyObject *
       
    59 addlines(PyObject *self, PyObject *args)
       
    60 {
       
    61 
       
    62 	PyObject *fp, *hunk, *a, *b, *x;
       
    63 	int i;
       
    64 	int lena, lenb;
       
    65 	int num;
       
    66 	int todoa, todob;
       
    67 	char *s, c;
       
    68 	PyObject *l;
       
    69 	if (!PyArg_ParseTuple(args, "OOiiOO", &fp, &hunk, &lena, &lenb, &a, &b))
       
    70 		return NULL;
       
    71 
       
    72 	while(1) {
       
    73 		todoa = lena - PyList_Size(a);
       
    74 		todob = lenb - PyList_Size(b);
       
    75 		num = todoa > todob ? todoa : todob;
       
    76 		if (num == 0)
       
    77 		    break;
       
    78 		for (i = 0 ; i < num ; i++) {
       
    79 			x = PyFile_GetLine(fp, 0);
       
    80 			s = PyString_AS_STRING(x);
       
    81 			c = *s;
       
    82 			if (strcmp(s, "\\ No newline at end of file\n") == 0) {
       
    83 				_fix_newline(hunk, a, b);
       
    84 				continue;
       
    85 			}
       
    86 			PyList_Append(hunk, x);
       
    87 			if (c == '+') {
       
    88 				l = PyString_FromString(s + 1);
       
    89 				PyList_Append(b, l);
       
    90 				Py_DECREF(l);
       
    91 			} else if (c == '-') {
       
    92 				PyList_Append(a, x);
       
    93 			} else {
       
    94 				l = PyString_FromString(s + 1);
       
    95 				PyList_Append(b, l);
       
    96 				Py_DECREF(l);
       
    97 				PyList_Append(a, x);
       
    98 			}
       
    99 			Py_DECREF(x);
       
   100 		}
       
   101 	}
       
   102 	return Py_BuildValue("l", 0);
       
   103 }
       
   104 
       
   105 /*
       
   106  * compare the lines in a with the lines in b.  a is assumed to have
       
   107  * a control char at the start of each line, this char is ignored in the
       
   108  * compare
       
   109  */
       
   110 static PyObject *
       
   111 testhunk(PyObject *self, PyObject *args)
       
   112 {
       
   113 
       
   114 	PyObject *a, *b;
       
   115 	long bstart;
       
   116 	int alen, blen;
       
   117 	int i;
       
   118 	char *sa, *sb;
       
   119 
       
   120 	if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
       
   121 		return NULL;
       
   122 	alen = PyList_Size(a);
       
   123 	blen = PyList_Size(b);
       
   124 	if (alen > blen - bstart) {
       
   125 		return Py_BuildValue("l", -1);
       
   126 	}
       
   127 	for (i = 0 ; i < alen ; i++) {
       
   128 		sa = PyString_AS_STRING(PyList_GET_ITEM(a, i));
       
   129 		sb = PyString_AS_STRING(PyList_GET_ITEM(b, i + bstart));
       
   130 		if (strcmp(sa+1, sb) != 0)
       
   131 			return Py_BuildValue("l", -1);
       
   132 	}
       
   133 	return Py_BuildValue("l", 0);
       
   134 }
       
   135 
       
   136 static PyMethodDef methods[] = {
       
   137 	{"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
       
   138 	{"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
       
   139 	{"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
       
   140 	{NULL, NULL}
       
   141 };
       
   142 
       
   143 PyMODINIT_FUNC
       
   144 initdiffhelpers(void)
       
   145 {
       
   146 	Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
       
   147 	diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
       
   148 	                                        NULL, NULL);
       
   149 }
       
   150