From 1acd488c68b9f4b419aee2e177875e4b705f2375 Mon Sep 17 00:00:00 2001 From: Martin Lenders <mlenders@elegosoft.com> Date: Fri, 8 Jun 2012 17:13:48 +0200 Subject: [PATCH] Wrap git_config_foreach in Config --- include/pygit2/config.h | 1 + src/pygit2/config.c | 56 +++++++++++++++++++++++++++++++++++++++++ test/test_config.py | 10 ++++++++ 3 files changed, 67 insertions(+) diff --git a/include/pygit2/config.h b/include/pygit2/config.h index 9d6017f..3ae9d4b 100644 --- a/include/pygit2/config.h +++ b/include/pygit2/config.h @@ -9,6 +9,7 @@ PyObject* Config_get_global_config(void); PyObject* Config_get_system_config(void); PyObject* Config_add_file(Config *self, PyObject *args); PyObject* Config_getitem(Config *self, PyObject *key); +PyObject* Config_foreach(Config *self, PyObject *args); int Config_setitem(Config *self, PyObject *key, PyObject *value); #endif diff --git a/src/pygit2/config.c b/src/pygit2/config.c index b18977a..ab18962 100644 --- a/src/pygit2/config.c +++ b/src/pygit2/config.c @@ -186,6 +186,56 @@ Config_setitem(Config *self, PyObject *py_key, PyObject *py_value) return 0; } +int +Config_foreach_callback_wrapper(const char *c_name, const char *c_value, + void *c_payload) +{ + PyObject *args = (PyObject *)c_payload; + PyObject *py_callback = NULL; + PyObject *py_payload = NULL; + PyObject *py_result = NULL; + int c_result; + + if (!PyArg_ParseTuple(args, "O|O", &py_callback, &py_payload)) + return 0; + + if (py_payload) + args = Py_BuildValue("ssO", c_name, c_value, py_payload); + else + args = Py_BuildValue("ss", c_name, c_value); + + if (!(py_result = PyObject_CallObject(py_callback,args))) + return 0; + + if (!(c_result = PyLong_AsLong(py_result))) + return 0; + + return c_result; +} + +PyObject * +Config_foreach(Config *self, PyObject *args) +{ + int ret; + PyObject *py_callback; + PyObject *py_payload; + + + if (!PyArg_ParseTuple(args, "O|O", &py_callback, &py_payload)) + return NULL; + + + if (!PyCallable_Check(py_callback)) { + PyErr_SetString(PyExc_TypeError,"Argument 'callback' is not callable"); + return NULL; + } + + ret = git_config_foreach(self->config, Config_foreach_callback_wrapper, + (void *)args); + + return PyInt_FromLong((long)ret); +} + PyObject * Config_add_file(Config *self, PyObject *args) { @@ -212,6 +262,12 @@ PyMethodDef Config_methods[] = { {"get_global_config", (PyCFunction)Config_get_global_config, METH_NOARGS | METH_STATIC, "Return an object representing the global configuration file."}, + {"foreach", (PyCFunction)Config_foreach, METH_VARARGS, + "Perform an operation on each config variable.\n\n" + "The callback must be of type Callable and receives the normalized name " + "and value of each variable in the config backend, and an optional " + "payload passed to this method. As soon as one of the callbacks returns " + "an integer other than 0, this function returns that value."}, {"add_file", (PyCFunction)Config_add_file, METH_VARARGS, "Add a config file instance to an existing config."}, {NULL} diff --git a/test/test_config.py b/test/test_config.py index b9e6aae..328217e 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -38,6 +38,10 @@ __author__ = 'mlenders@elegosoft.com (M. Lenders)' config_filename = "test_config" +def foreach_test_wrapper(key, name, lst): + lst[key] = name + return 1 + class ConfigTest(utils.RepoTestCase): def test_config(self): @@ -135,6 +139,12 @@ class ConfigTest(utils.RepoTestCase): del config['core.dummy3'] self.assertFalse('core.dummy3' in config) + def test_foreach(self): + config = self.repo.config + lst = {} + config.foreach(foreach_test_wrapper, lst) + self.assertTrue('core.bare' in lst) + self.assertTrue(lst['core.bare']) if __name__ == '__main__': unittest.main()