1 #include <string.h>
2
3 #include "git2.h"
4
5 #include "egit.h"
6 #include "egit-options.h"
7 #include "egit-util.h"
8 #include "interface.h"
9 #include "egit-submodule.h"
10
11
12 // =============================================================================
13 // Helpers - status values
14
status_decode(emacs_env * env,emacs_value flag,unsigned int status)15 static emacs_value status_decode(emacs_env *env, emacs_value flag, unsigned int status)
16 {
17 if (EM_EXTRACT_BOOLEAN(flag)) {
18 emacs_value retval;
19 em_checkflag_submodule_status(&retval, env, flag, status, true);
20 return retval;
21 }
22
23 return em_getlist_submodule_status(env, status);
24 }
25
26
27 // =============================================================================
28 // Constructors
29
30 EGIT_DOC(submodule_add_setup, "REPO URL PATH &optional LINKP",
31 "Set up a new submodule for checkout.\n"
32 "This emulates `git submodule add' up to fetch and checkout.\n"
33 "If LINK is non-nil, PATH will contain a git link to a repo\n"
34 "in REPO's own .git/modules.");
egit_submodule_add_setup(emacs_env * env,emacs_value _repo,emacs_value _url,emacs_value _path,emacs_value linkp)35 emacs_value egit_submodule_add_setup(
36 emacs_env *env, emacs_value _repo, emacs_value _url,
37 emacs_value _path, emacs_value linkp)
38 {
39 EGIT_ASSERT_REPOSITORY(_repo);
40 EM_ASSERT_STRING(_url);
41 EM_ASSERT_STRING(_path);
42
43 git_repository *repo = EGIT_EXTRACT(_repo);
44 char *url = EM_EXTRACT_STRING(_url);
45 char *path = EM_EXTRACT_STRING(_path);
46 git_submodule *sub;
47 int retval = git_submodule_add_setup(&sub, repo, url, path, EM_EXTRACT_BOOLEAN(linkp));
48 free(url);
49 free(path);
50 EGIT_CHECK_ERROR(retval);
51
52 return egit_wrap(env, EGIT_SUBMODULE, sub, EM_EXTRACT_USER_PTR(_repo));
53 }
54
55 EGIT_DOC(submodule_lookup, "REPO NAME", "Look up a submodule in REPO by NAME or path.");
egit_submodule_lookup(emacs_env * env,emacs_value _repo,emacs_value _name)56 emacs_value egit_submodule_lookup(emacs_env *env, emacs_value _repo, emacs_value _name)
57 {
58 EGIT_ASSERT_REPOSITORY(_repo);
59 EM_ASSERT_STRING(_name);
60
61 git_repository *repo = EGIT_EXTRACT(_repo);
62 char *name = EM_EXTRACT_STRING(_name);
63 git_submodule *sub;
64 int retval = git_submodule_lookup(&sub, repo, name);
65 free(name);
66 EGIT_CHECK_ERROR(retval);
67
68 return egit_wrap(env, EGIT_SUBMODULE, sub, EM_EXTRACT_USER_PTR(_repo));
69 }
70
71
72 // =============================================================================
73 // Getters
74
75 EGIT_DOC(submodule_branch, "SUBMODULE", "Get the branch name for SUBMODULE.");
egit_submodule_branch(emacs_env * env,emacs_value _sub)76 emacs_value egit_submodule_branch(emacs_env *env, emacs_value _sub)
77 {
78 EGIT_ASSERT_SUBMODULE(_sub);
79 git_submodule *sub = EGIT_EXTRACT(_sub);
80 const char *branch = git_submodule_branch(sub);
81 if (!branch)
82 return esym_nil;
83 return EM_STRING(branch);
84 }
85
86 EGIT_DOC(submodule_fetch_recurse_submodules, "SUBMODULE",
87 "Get the fetchRecurseSubmodules rule for SUBMODULE.\n"
88 "This is `nil', `ondemand' or `t'.");
egit_submodule_fetch_recurse_submodules(emacs_env * env,emacs_value _sub)89 emacs_value egit_submodule_fetch_recurse_submodules(emacs_env *env, emacs_value _sub)
90 {
91 EGIT_ASSERT_SUBMODULE(_sub);
92 git_submodule *sub = EGIT_EXTRACT(_sub);
93 git_submodule_recurse_t rec = git_submodule_fetch_recurse_submodules(sub);
94 return em_findenum_submodule_recurse(rec);
95 }
96
97 EGIT_DOC(submodule_head_id, "SUBMODULE", "Get the ID for SUBMODULE in HEAD.");
egit_submodule_head_id(emacs_env * env,emacs_value _sub)98 emacs_value egit_submodule_head_id(emacs_env *env, emacs_value _sub)
99 {
100 EGIT_ASSERT_SUBMODULE(_sub);
101 git_submodule *sub = EGIT_EXTRACT(_sub);
102 const git_oid *oid = git_submodule_head_id(sub);
103 if (!oid)
104 return esym_nil;
105 const char *oid_s = git_oid_tostr_s(oid);
106 return EM_STRING(oid_s);
107 }
108
109 EGIT_DOC(submodule_ignore, "SUBMODULE",
110 "Get the ignore rule for SUBMODULE.\n"
111 "This is one of the symbols `none', `untracked', `dirty' and `all'.");
egit_submodule_ignore(emacs_env * env,emacs_value _sub)112 emacs_value egit_submodule_ignore(emacs_env *env, emacs_value _sub)
113 {
114 EGIT_ASSERT_SUBMODULE(_sub);
115 git_submodule *sub = EGIT_EXTRACT(_sub);
116 git_submodule_ignore_t ignore = git_submodule_ignore(sub);
117 return em_findenum_submodule_ignore(ignore);
118 }
119
120 EGIT_DOC(submodule_index_id, "SUBMODULE", "Get the ID for SUBMODULE in the index.");
egit_submodule_index_id(emacs_env * env,emacs_value _sub)121 emacs_value egit_submodule_index_id(emacs_env *env, emacs_value _sub)
122 {
123 EGIT_ASSERT_SUBMODULE(_sub);
124 git_submodule *sub = EGIT_EXTRACT(_sub);
125 const git_oid *oid = git_submodule_index_id(sub);
126 if (!oid)
127 return esym_nil;
128 const char *oid_s = git_oid_tostr_s(oid);
129 return EM_STRING(oid_s);
130 }
131
132 EGIT_DOC(submodule_location, "SUBMODULE &optional FLAG",
133 "Get the location of SUBMODULE.\n"
134 "This is a lightweight version of `libgit-submodule-status',\n"
135 "only checking the first four status values: `in-head', `in-index',\n"
136 "`in-config' and `in-wd'.\n\n"
137 "See `libgit-submodule-status' for an explanation of FLAG.");
egit_submodule_location(emacs_env * env,emacs_value _sub,emacs_value flag)138 emacs_value egit_submodule_location(emacs_env *env, emacs_value _sub, emacs_value flag)
139 {
140 EGIT_ASSERT_SUBMODULE(_sub);
141 git_submodule *sub = EGIT_EXTRACT(_sub);
142 unsigned int loc;
143 int retval = git_submodule_location(&loc, sub);
144 EGIT_CHECK_ERROR(retval);
145
146 return status_decode(env, flag, loc);
147 }
148
149 EGIT_DOC(submodule_name, "SUBMODULE", "Get the name of SUBMODULE.");
egit_submodule_name(emacs_env * env,emacs_value _sub)150 emacs_value egit_submodule_name(emacs_env *env, emacs_value _sub)
151 {
152 EGIT_ASSERT_SUBMODULE(_sub);
153 git_submodule *sub = EGIT_EXTRACT(_sub);
154 const char *name = git_submodule_name(sub);
155 return EM_STRING(name);
156 }
157
158 EGIT_DOC(submodule_open, "SUBMODULE", "Get the sub-repository associated with SUBMODULE.");
egit_submodule_open(emacs_env * env,emacs_value _sub)159 emacs_value egit_submodule_open(emacs_env *env, emacs_value _sub)
160 {
161 EGIT_ASSERT_SUBMODULE(_sub);
162 git_submodule *sub = EGIT_EXTRACT(_sub);
163 git_repository *repo;
164 int retval = git_submodule_open(&repo, sub);
165 EGIT_CHECK_ERROR(retval);
166 return egit_wrap(env, EGIT_REPOSITORY, repo, NULL);
167 }
168
169 EGIT_DOC(submodule_owner, "SUBMODULE", "Get the repository in which SUBMODULE lives.");
egit_submodule_owner(emacs_env * env,emacs_value _sub)170 emacs_value egit_submodule_owner(emacs_env *env, emacs_value _sub)
171 {
172 EGIT_ASSERT_SUBMODULE(_sub);
173 egit_object *owner = EGIT_EXTRACT_PARENT(_sub);
174 owner->refcount++;
175 return EM_USER_PTR(owner, egit_finalize);
176 }
177
178 EGIT_DOC(submodule_path, "SUBMODULE", "Get the path of SUBMODULE.");
egit_submodule_path(emacs_env * env,emacs_value _sub)179 emacs_value egit_submodule_path(emacs_env *env, emacs_value _sub)
180 {
181 EGIT_ASSERT_SUBMODULE(_sub);
182 git_submodule *sub = EGIT_EXTRACT(_sub);
183 const char *path = git_submodule_path(sub);
184 return EM_STRING(path);
185 }
186
187 EGIT_DOC(submodule_status, "REPO NAME &optional IGNORE FLAG",
188 "Get a list of symbols describing the status of a submodule.\n"
189 "REPO is the repository to search in, and NAME is the name of the submodule.\n"
190 "IGNORE indicates the ignore rule to use, one of `none' (default), `untracked',\n"
191 "`dirty' and `all'.\n\n"
192 "The following are always returned.\n"
193 "- `in-head': superproject head contains submodule\n"
194 "- `in-index': superproject index contains submodule\n"
195 "- `in-config': superproject gitmodules contains submodule\n"
196 "- `in-wd': superproject workdir contains submodule\n\n"
197 "The following are returned as long as IGNORE is not `all'.\n"
198 "- `index-added': submodule is in index, not in head\n"
199 "- `index-deleted': submodule is in head, not in index\n"
200 "- `index-modified': index and head don't match\n"
201 "- `wd-uninitialized': workdir contains empty directory\n"
202 "- `wd-added': in workdir, but not index\n"
203 "- `wd-deleted': in index, but not workdir\n"
204 "- `wd-modified': index and workdir head don't match\n\n"
205 "The following are only returned if IGNORE Is `none' or `untracked'.\n"
206 "- `wd-index-modified': submodule workdir index is dirty\n"
207 "- `wd-wd-modified': submodule workdir has modified files\n\n"
208 "The following is only returned if the IGNORE is `none':\n"
209 "- `wd-untracked': submodule workdir contains untracked files\n\n"
210 "If the optional FLAG is non-nil, it may be any of the above symbols,\n"
211 "in which case the return value is non-nil if that flag is present.\n"
212 "In other words, these are equivalent:\n\n"
213 "(libgit-submodule-status REPO NAME IGNORE FLAG)\n\n"
214 "(memq FLAG (libgit-submodule-status REPO NAME IGNORE))");
egit_submodule_status(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _ignore,emacs_value flag)215 emacs_value egit_submodule_status(
216 emacs_env *env, emacs_value _repo, emacs_value _name,
217 emacs_value _ignore, emacs_value flag)
218 {
219 EGIT_ASSERT_REPOSITORY(_repo);
220 EM_ASSERT_STRING(_name);
221
222 git_submodule_ignore_t ignore;
223 if (!em_findsym_submodule_ignore(&ignore, env, _ignore, true))
224 return esym_nil;
225
226 git_repository *repo = EGIT_EXTRACT(_repo);
227 char *name = EM_EXTRACT_STRING(_name);
228
229 unsigned int status;
230 int retval = git_submodule_status(&status, repo, name, ignore);
231 free(name);
232 EGIT_CHECK_ERROR(retval);
233
234 return status_decode(env, flag, status);
235 }
236
237 EGIT_DOC(submodule_update_strategy, "SUBMODULE",
238 "Get the update rule for SUBMODULE.\n"
239 "This is one of the symbols `checkout', `rebase', `merge' and `none'.");
egit_submodule_update_strategy(emacs_env * env,emacs_value _sub)240 emacs_value egit_submodule_update_strategy(emacs_env *env, emacs_value _sub)
241 {
242 EGIT_ASSERT_SUBMODULE(_sub);
243 git_submodule *sub = EGIT_EXTRACT(_sub);
244 git_submodule_update_t update = git_submodule_update_strategy(sub);
245 return em_findenum_submodule_update(update);
246 }
247
248 EGIT_DOC(submodule_url, "SUBMODULE", "Get the url of SUBMODULE.");
egit_submodule_url(emacs_env * env,emacs_value _sub)249 emacs_value egit_submodule_url(emacs_env *env, emacs_value _sub)
250 {
251 EGIT_ASSERT_SUBMODULE(_sub);
252 git_submodule *sub = EGIT_EXTRACT(_sub);
253 const char *url = git_submodule_url(sub);
254 return EM_STRING(url);
255 }
256
257 EGIT_DOC(submodule_wd_id, "SUBMODULE", "Get the ID for SUBMODULE in the working directory.");
egit_submodule_wd_id(emacs_env * env,emacs_value _sub)258 emacs_value egit_submodule_wd_id(emacs_env *env, emacs_value _sub)
259 {
260 EGIT_ASSERT_SUBMODULE(_sub);
261 git_submodule *sub = EGIT_EXTRACT(_sub);
262 const git_oid *oid = git_submodule_wd_id(sub);
263 if (!oid)
264 return esym_nil;
265 const char *oid_s = git_oid_tostr_s(oid);
266 return EM_STRING(oid_s);
267 }
268
269
270 // =============================================================================
271 // Foreach
272
submodule_callback(git_submodule * sub,const char * name,void * payload)273 static int submodule_callback(git_submodule *sub, const char *name, void *payload)
274 {
275 egit_generic_payload *ctx = (egit_generic_payload*) payload;
276 emacs_env *env = ctx->env;
277
278 emacs_value args[2];
279 args[0] = egit_wrap(env, EGIT_SUBMODULE, sub, ctx->parent);
280 args[1] = EM_STRING(name);
281 env->funcall(env, ctx->func, 2, args);
282
283 EM_RETURN_IF_NLE(GIT_EUSER);
284 return 0;
285 }
286
287 EGIT_DOC(submodule_foreach, "REPO FUNC",
288 "Call FUNC for each submodule in REPO.\n"
289 "FUNC receives two arguments: the submodule object and its name.");
egit_submodule_foreach(emacs_env * env,emacs_value _repo,emacs_value func)290 emacs_value egit_submodule_foreach(emacs_env *env, emacs_value _repo, emacs_value func)
291 {
292 EGIT_ASSERT_REPOSITORY(_repo);
293 EM_ASSERT_FUNCTION(func);
294
295 egit_generic_payload ctx = {.env = env, .func = func, .parent = EM_EXTRACT_USER_PTR(_repo)};
296 git_repository *repo = EGIT_EXTRACT(_repo);
297 int retval = git_submodule_foreach(repo, &submodule_callback, &ctx);
298
299 EM_RETURN_NIL_IF_NLE();
300 if (retval == GIT_EUSER)
301 return esym_nil;
302 EGIT_CHECK_ERROR(retval);
303 return esym_nil;
304 }
305
306
307 // =============================================================================
308 // Operations
309
310 EGIT_DOC(submodule_add_finalize, "SUBMODULE",
311 "Resolve the setup of SUBMODULE.\n"
312 "This should be called after `libgit-add-setup', and after clone.");
egit_submodule_add_finalize(emacs_env * env,emacs_value _sub)313 emacs_value egit_submodule_add_finalize(emacs_env *env, emacs_value _sub)
314 {
315 EGIT_ASSERT_SUBMODULE(_sub);
316 git_submodule *sub = EGIT_EXTRACT(_sub);
317 int retval = git_submodule_add_finalize(sub);
318 EGIT_CHECK_ERROR(retval);
319 return esym_nil;
320 }
321
322 EGIT_DOC(submodule_add_to_index, "SUBMODULE WRITE",
323 "Add HEAD of SUBMODULE to index in superproject.\n"
324 "If WRITE is non-nil, the index will be immediately written.");
egit_submodule_add_to_index(emacs_env * env,emacs_value _sub,emacs_value write)325 emacs_value egit_submodule_add_to_index(emacs_env *env, emacs_value _sub, emacs_value write)
326 {
327 EGIT_ASSERT_SUBMODULE(_sub);
328 git_submodule *sub = EGIT_EXTRACT(_sub);
329 int retval = git_submodule_add_to_index(sub, EM_EXTRACT_BOOLEAN(write));
330 EGIT_CHECK_ERROR(retval);
331 return esym_nil;
332 }
333
334 EGIT_DOC(submodule_init, "SUBMODULE &optional FORCE",
335 "Copy submodule info to .git/config.\n"
336 "If FORCE is non-nil, overwrite even if an entry already exists.");
egit_submodule_init(emacs_env * env,emacs_value _sub,emacs_value force)337 emacs_value egit_submodule_init(emacs_env *env, emacs_value _sub, emacs_value force)
338 {
339 EGIT_ASSERT_SUBMODULE(_sub);
340 git_submodule *sub = EGIT_EXTRACT(_sub);
341 int retval = git_submodule_init(sub, EM_EXTRACT_BOOLEAN(force));
342 EGIT_CHECK_ERROR(retval);
343 return esym_nil;
344 }
345
346 EGIT_DOC(submodule_reload, "SUBMODULE &optional FORCE",
347 "Re-read info about SUBMODULE from config, index and HEAD.\n"
348 "If FORCE is non-nil, force reload even if data does not seem\n"
349 "outdated.");
egit_submodule_reload(emacs_env * env,emacs_value _sub,emacs_value force)350 emacs_value egit_submodule_reload(emacs_env *env, emacs_value _sub, emacs_value force)
351 {
352 EGIT_ASSERT_SUBMODULE(_sub);
353 git_submodule *sub = EGIT_EXTRACT(_sub);
354 int retval = git_submodule_reload(sub, EM_EXTRACT_BOOLEAN(force));
355 EGIT_CHECK_ERROR(retval);
356 return esym_nil;
357 }
358
359 EGIT_DOC(submodule_repo_init, "SUBMODULE &optional LINKP",
360 "Set up and return the subrepo for SUBMODULE in preparation for clone.\n"
361 "If LINK is non-nil, the subrepo will contain a git link to a repo\n"
362 "in the parent repository's own .git/modules.");
egit_submodule_repo_init(emacs_env * env,emacs_value _sub,emacs_value linkp)363 emacs_value egit_submodule_repo_init(emacs_env *env, emacs_value _sub, emacs_value linkp)
364 {
365 EGIT_ASSERT_SUBMODULE(_sub);
366 git_submodule *sub = EGIT_EXTRACT(_sub);
367 git_repository *repo;
368 int retval = git_submodule_repo_init(&repo, sub, EM_EXTRACT_BOOLEAN(linkp));
369 EGIT_CHECK_ERROR(retval);
370 return egit_wrap(env, EGIT_REPOSITORY, repo, NULL);
371 }
372
373 EGIT_DOC(submodule_set_branch, "REPO NAME BRANCHNAME",
374 "Set the branch of submodule NAME to BRANCHNAME.\n"
375 "After this, you may wish to call `libgit-submodule-sync'.");
egit_submodule_set_branch(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _refname)376 emacs_value egit_submodule_set_branch(
377 emacs_env *env, emacs_value _repo, emacs_value _name, emacs_value _refname)
378 {
379 EGIT_ASSERT_REPOSITORY(_repo);
380 EM_ASSERT_STRING(_name);
381 EM_ASSERT_STRING(_refname);
382
383 git_repository *repo = EGIT_EXTRACT(_repo);
384 char *name = EM_EXTRACT_STRING(_name);
385 char *refname = EM_EXTRACT_STRING(_refname);
386 int retval = git_submodule_set_branch(repo, name, refname);
387 free(name);
388 free(refname);
389 EGIT_CHECK_ERROR(retval);
390
391 return esym_nil;
392 }
393
394 EGIT_DOC(submodule_set_fetch_recurse_submodules, "REPO NAME &optional VALUE",
395 "Set the fetchRecurseSubmodules rule for submodule NAME.\n"
396 "Possible VALUE are nil, `ondemand', or other non-nil.");
egit_submodule_set_fetch_recurse_submodules(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _value)397 emacs_value egit_submodule_set_fetch_recurse_submodules(
398 emacs_env *env, emacs_value _repo, emacs_value _name, emacs_value _value)
399 {
400 EGIT_ASSERT_REPOSITORY(_repo);
401 EM_ASSERT_STRING(_name);
402
403 git_submodule_recurse_t value;
404 if (!em_findsym_submodule_recurse(&value, env, _value, false))
405 value = GIT_SUBMODULE_RECURSE_YES;
406
407 git_repository *repo = EGIT_EXTRACT(_repo);
408 char *name = EM_EXTRACT_STRING(_name);
409 int retval = git_submodule_set_fetch_recurse_submodules(repo, name, value);
410 free(name);
411 EGIT_CHECK_ERROR(retval);
412
413 return esym_nil;
414 }
415
416 EGIT_DOC(submodule_set_ignore, "REPO NAME VALUE",
417 "Set the ignore rule for submodule NAME.\n"
418 "Possible VALUE are `none', `dirty', `untracked' and `all'.");
egit_submodule_set_ignore(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _value)419 emacs_value egit_submodule_set_ignore(
420 emacs_env *env, emacs_value _repo, emacs_value _name, emacs_value _value)
421 {
422 EGIT_ASSERT_REPOSITORY(_repo);
423 EM_ASSERT_STRING(_name);
424
425 git_submodule_ignore_t value;
426 if (!em_findsym_submodule_ignore(&value, env, _value, true))
427 return esym_nil;
428
429 git_repository *repo = EGIT_EXTRACT(_repo);
430 char *name = EM_EXTRACT_STRING(_name);
431 int retval = git_submodule_set_ignore(repo, name, value);
432 free(name);
433 EGIT_CHECK_ERROR(retval);
434
435 return esym_nil;
436 }
437
438 EGIT_DOC(submodule_set_update, "REPO NAME VALUE",
439 "Set the ignore rule for submodule NAME.\n"
440 "Possible VALUE are `checkout', `rebase', `merge' and `none'.");
egit_submodule_set_update(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _value)441 emacs_value egit_submodule_set_update(
442 emacs_env *env, emacs_value _repo, emacs_value _name, emacs_value _value)
443 {
444 EGIT_ASSERT_REPOSITORY(_repo);
445 EM_ASSERT_STRING(_name);
446
447 git_submodule_update_t value;
448 if (!em_findsym_submodule_update(&value, env, _value, true))
449 return esym_nil;
450
451 git_repository *repo = EGIT_EXTRACT(_repo);
452 char *name = EM_EXTRACT_STRING(_name);
453 int retval = git_submodule_set_update(repo, name, value);
454 free(name);
455 EGIT_CHECK_ERROR(retval);
456
457 return esym_nil;
458 }
459
460 EGIT_DOC(submodule_set_url, "REPO NAME URL",
461 "Set the URL of submodule NAME to URL.\n"
462 "After this, you may wish to call `libgit-submodule-sync'.");
egit_submodule_set_url(emacs_env * env,emacs_value _repo,emacs_value _name,emacs_value _url)463 emacs_value egit_submodule_set_url(
464 emacs_env *env, emacs_value _repo, emacs_value _name, emacs_value _url)
465 {
466 EGIT_ASSERT_REPOSITORY(_repo);
467 EM_ASSERT_STRING(_name);
468 EM_ASSERT_STRING(_url);
469
470 git_repository *repo = EGIT_EXTRACT(_repo);
471 char *name = EM_EXTRACT_STRING(_name);
472 char *url = EM_EXTRACT_STRING(_url);
473 int retval = git_submodule_set_url(repo, name, url);
474 free(name);
475 free(url);
476 EGIT_CHECK_ERROR(retval);
477
478 return esym_nil;
479 }
480
481 EGIT_DOC(submodule_sync, "SUBMODULE", "Copy SUBMODULE's remote info into its repository.");
egit_submodule_sync(emacs_env * env,emacs_value _sub)482 emacs_value egit_submodule_sync(emacs_env *env, emacs_value _sub)
483 {
484 EGIT_ASSERT_SUBMODULE(_sub);
485 git_submodule *sub = EGIT_EXTRACT(_sub);
486 int retval = git_submodule_sync(sub);
487 EGIT_CHECK_ERROR(retval);
488 return esym_nil;
489 }
490
491 EGIT_DOC(submodule_update, "SUBMODULE &optional INITP FETCHP CHECKOUT-OPTS FETCH-OPTS",
492 "Update a submodule and checkout the subrepo to the commit\n"
493 "specified in the index of the parent repo.\n"
494 "If the submodule is missing it will be cloned.\n"
495 "If INITP is non-nil, initialize the submodule if not already done.\n"
496 "If FETCHP is non-nil, fetch from the remote if the subrepo does not\n"
497 "contain the desired commit.\n"
498 "For CHECKOUT-OPTS, see `libgit-checkout-head', and for FETCH-OPTS,\n"
499 "see `libgit-remote-fetch'.");
egit_submodule_update(emacs_env * env,emacs_value _sub,emacs_value initp,emacs_value fetchp,emacs_value checkout_opts,emacs_value fetch_opts)500 emacs_value egit_submodule_update(
501 emacs_env *env, emacs_value _sub, emacs_value initp, emacs_value fetchp,
502 emacs_value checkout_opts, emacs_value fetch_opts)
503 {
504 EGIT_ASSERT_SUBMODULE(_sub);
505
506 git_submodule_update_options opts;
507 opts.allow_fetch = EM_EXTRACT_BOOLEAN(fetchp);
508
509 egit_checkout_options_parse(env, checkout_opts, &opts.checkout_opts);
510 EM_RETURN_NIL_IF_NLE();
511
512 egit_fetch_options_parse(env, fetch_opts, &opts.fetch_opts);
513 EM_RETURN_NIL_IF_NLE();
514
515 git_submodule *sub = EGIT_EXTRACT(_sub);
516 int retval = git_submodule_update(sub, EM_EXTRACT_BOOLEAN(initp), &opts);
517 egit_checkout_options_release(&opts.checkout_opts);
518 egit_fetch_options_release(&opts.fetch_opts);
519 EGIT_CHECK_ERROR(retval);
520
521 return esym_nil;
522 }
523