From 15326b731f7cf4d40be9526ce23092ec1674f17d Mon Sep 17 00:00:00 2001
From: Jason Ziglar <jasedit@gmail.com>
Date: Sun, 5 Mar 2017 21:40:32 -0500
Subject: [PATCH] Add update_submodules() command

---
 src/repository.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/src/repository.c b/src/repository.c
index ab00baf..7dcee7e 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1355,6 +1355,73 @@ Repository_init_submodules(Repository* self, PyObject *args, PyObject *kwds)
     Py_RETURN_NONE;
 }
 
+PyDoc_STRVAR(Repository_update_submodules__doc__,
+    "update_submodules(submodules=None, init=False)\n"
+    "\n"
+    "Updates the specified submodules, or all if None are specified\n"
+    "init: Flag indicating if submodules should be automatically initialized if necessary.\n");
+
+static int foreach_sub_update_cb(git_submodule *submodule, const char *name, void *payload)
+{
+    git_submodule_update_options opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
+    return git_submodule_update(submodule, *(int*)payload, &opts);
+}
+
+PyObject *
+Repository_update_submodules(Repository *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *list = Py_None;
+    PyObject *py_init = Py_False;
+    PyObject *iter, *next, *subpath;
+    int init, err;
+    const char *c_subpath;
+    git_submodule *submodule;
+    git_submodule_update_options opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
+
+    char *kwlist[] = {"submodules", "init", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &list, &py_init))
+        return NULL;
+
+    init = PyObject_IsTrue(py_init);
+
+    if (init != 0 && init != 1)
+        init = 0;
+
+    if (list == Py_None) {
+        err = git_submodule_foreach(self->repo, foreach_sub_update_cb, &init);
+        if (err != 0)
+            return Error_set(err);
+        Py_RETURN_NONE;
+    }
+
+    iter = PyObject_GetIter(list);
+    if (!iter)
+        return NULL;
+
+    while (1) {
+        next = PyIter_Next(iter);
+        if (!next)
+            break;
+
+        c_subpath = py_str_borrow_c_str(&subpath, next, NULL);
+
+        git_submodule_lookup(&submodule, self->repo, c_subpath);
+        Py_DECREF(subpath);
+        if (!submodule) {
+            PyErr_SetString(PyExc_KeyError,
+                "Submodule does not exist");
+            return NULL;
+        }
+
+        err = git_submodule_update(submodule, init, &opts);
+        if (err != 0) {
+            return Error_set(err);
+        }
+    }
+
+    Py_RETURN_NONE;
+}
 
 PyDoc_STRVAR(Repository_lookup_reference__doc__,
   "lookup_reference(name) -> Reference\n"
@@ -1783,6 +1850,7 @@ PyMethodDef Repository_methods[] = {
     METHOD(Repository, listall_reference_objects, METH_NOARGS),
     METHOD(Repository, listall_submodules, METH_NOARGS),
     METHOD(Repository, init_submodules, METH_VARARGS | METH_KEYWORDS),
+    METHOD(Repository, update_submodules, METH_VARARGS | METH_KEYWORDS),
     METHOD(Repository, lookup_reference, METH_O),
     METHOD(Repository, revparse_single, METH_O),
     METHOD(Repository, status, METH_NOARGS),