mercurial/dirs.c
changeset 18901 66d3aebe2d95
parent 18900 02ee846b246a
child 18902 8c0a7eeda06d
equal deleted inserted replaced
18900:02ee846b246a 18901:66d3aebe2d95
    12 #include "util.h"
    12 #include "util.h"
    13 
    13 
    14 /*
    14 /*
    15  * This is a multiset of directory names, built from the files that
    15  * This is a multiset of directory names, built from the files that
    16  * appear in a dirstate or manifest.
    16  * appear in a dirstate or manifest.
       
    17  *
       
    18  * A few implementation notes:
       
    19  *
       
    20  * We modify Python integers for refcounting, but those integers are
       
    21  * never visible to Python code.
    17  */
    22  */
    18 typedef struct {
    23 typedef struct {
    19 	PyObject_HEAD
    24 	PyObject_HEAD
    20 	PyObject *dict;
    25 	PyObject *dict;
    21 } dirsObject;
    26 } dirsObject;
    34 }
    39 }
    35 
    40 
    36 static int _addpath(PyObject *dirs, PyObject *path)
    41 static int _addpath(PyObject *dirs, PyObject *path)
    37 {
    42 {
    38 	Py_ssize_t pos = PyString_GET_SIZE(path);
    43 	Py_ssize_t pos = PyString_GET_SIZE(path);
    39 	PyObject *newval = NULL, *key = NULL;
    44 	PyObject *key = NULL;
    40 	int ret = -1;
    45 	int ret = -1;
    41 
    46 
    42 	while ((pos = _finddir(path, pos - 1)) != -1) {
    47 	while ((pos = _finddir(path, pos - 1)) != -1) {
    43 		PyObject *val;
    48 		PyObject *val;
    44 		long v = 0;
       
    45 
    49 
    46 		key = PyString_FromStringAndSize(PyString_AS_STRING(path), pos);
    50 		key = PyString_FromStringAndSize(PyString_AS_STRING(path), pos);
    47 
    51 
    48 		if (key == NULL)
    52 		if (key == NULL)
    49 			goto bail;
    53 			goto bail;
    50 
    54 
    51 		val = PyDict_GetItem(dirs, key);
    55 		val = PyDict_GetItem(dirs, key);
    52 		if (val != NULL)
    56 		if (val != NULL) {
    53 			v = PyInt_AS_LONG(val);
    57 			PyInt_AS_LONG(val) += 1;
    54 
    58 			Py_CLEAR(key);
    55 		newval = PyInt_FromLong(v + 1);
    59 			continue;
    56 
    60 		}
    57 		if (newval == NULL)
    61 
    58 			goto bail;
    62 		/* Force Python to not reuse a small shared int. */
    59 
    63 		val = PyInt_FromLong(0x1eadbeef);
    60 		ret = PyDict_SetItem(dirs, key, newval);
    64 
       
    65 		if (val == NULL)
       
    66 			goto bail;
       
    67 
       
    68 		PyInt_AS_LONG(val) = 1;
       
    69 		ret = PyDict_SetItem(dirs, key, val);
       
    70 		Py_DECREF(val);
    61 		if (ret == -1)
    71 		if (ret == -1)
    62 			goto bail;
    72 			goto bail;
    63 		Py_CLEAR(key);
    73 		Py_CLEAR(key);
    64 		Py_CLEAR(newval);
       
    65 	}
    74 	}
    66 	ret = 0;
    75 	ret = 0;
    67 
    76 
    68 bail:
    77 bail:
    69 	Py_XDECREF(key);
    78 	Py_XDECREF(key);
    70 	Py_XDECREF(newval);
       
    71 
    79 
    72 	return ret;
    80 	return ret;
    73 }
    81 }
    74 
    82 
    75 static int _delpath(PyObject *dirs, PyObject *path)
    83 static int _delpath(PyObject *dirs, PyObject *path)
    76 {
    84 {
    77 	Py_ssize_t pos = PyString_GET_SIZE(path);
    85 	Py_ssize_t pos = PyString_GET_SIZE(path);
    78 	PyObject *newval = NULL, *key = NULL;
    86 	PyObject *key = NULL;
    79 	int ret = -1;
    87 	int ret = -1;
    80 
    88 
    81 	while ((pos = _finddir(path, pos - 1)) != -1) {
    89 	while ((pos = _finddir(path, pos - 1)) != -1) {
    82 		PyObject *val;
    90 		PyObject *val;
    83 		long v;
       
    84 
    91 
    85 		key = PyString_FromStringAndSize(PyString_AS_STRING(path), pos);
    92 		key = PyString_FromStringAndSize(PyString_AS_STRING(path), pos);
    86 
    93 
    87 		if (key == NULL)
    94 		if (key == NULL)
    88 			goto bail;
    95 			goto bail;
    91 		if (val == NULL) {
    98 		if (val == NULL) {
    92 			PyErr_SetString(PyExc_ValueError,
    99 			PyErr_SetString(PyExc_ValueError,
    93 					"expected a value, found none");
   100 					"expected a value, found none");
    94 			goto bail;
   101 			goto bail;
    95 		}
   102 		}
    96 		v = PyInt_AS_LONG(val);
   103 
    97 
   104 		if (--PyInt_AS_LONG(val) <= 0 &&
    98 		if (v <= 1) {
   105 		    PyDict_DelItem(dirs, key) == -1)
    99 			if (PyDict_DelItem(dirs, key) == -1)
       
   100 				goto bail;
       
   101 			continue;
       
   102 		}
       
   103 		newval = PyInt_FromLong(v - 1);
       
   104 
       
   105 		if (newval == NULL)
       
   106 			goto bail;
       
   107 
       
   108 		ret = PyDict_SetItem(dirs, key, newval);
       
   109 		if (ret == -1)
       
   110 			goto bail;
   106 			goto bail;
   111 		Py_CLEAR(key);
   107 		Py_CLEAR(key);
   112 		Py_CLEAR(newval);
       
   113 	}
   108 	}
   114 	ret = 0;
   109 	ret = 0;
   115 
   110 
   116 bail:
   111 bail:
   117 	Py_XDECREF(key);
   112 	Py_XDECREF(key);
   118 	Py_XDECREF(newval);
       
   119 
   113 
   120 	return ret;
   114 	return ret;
   121 }
   115 }
   122 
   116 
   123 static int dirs_fromdict(PyObject *dirs, PyObject *source, char skipchar)
   117 static int dirs_fromdict(PyObject *dirs, PyObject *source, char skipchar)