Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 95f75e6

Browse files
committed
submodule: provide a wrapper for simple submodule clone steps
1 parent 9aa049d commit 95f75e6

File tree

5 files changed

+93
-30
lines changed

5 files changed

+93
-30
lines changed

include/git2/submodule.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ GIT_EXTERN(int) git_submodule_foreach(
263263
* from the working directory to the new repo.
264264
*
265265
* To fully emulate "git submodule add" call this function, then open the
266-
* submodule repo and perform the clone step as needed. Lastly, call
266+
* submodule repo and perform the clone step as needed (if you don't need
267+
* anything custom see `git_submodule_add_clone()`). Lastly, call
267268
* `git_submodule_add_finalize()` to wrap up adding the new submodule and
268269
* .gitmodules to the index to be ready to commit.
269270
*
@@ -285,6 +286,20 @@ GIT_EXTERN(int) git_submodule_add_setup(
285286
const char *path,
286287
int use_gitlink);
287288

289+
/**
290+
* Perform the clone step for a newly created submodule.
291+
*
292+
* This performs the necessary `git_clone` to setup a newly-created submodule.
293+
*
294+
* @param out The newly created repository object. Optional.
295+
* @param submodule The submodule currently waiting for its clone.
296+
*
297+
* @return 0 on success, -1 on other errors (see git_clone).
298+
*/
299+
GIT_EXTERN(int) git_submodule_add_clone(
300+
git_repository **out,
301+
git_submodule *submodule);
302+
288303
/**
289304
* Resolve the setup of a new git submodule.
290305
*

src/clone.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,12 @@ int git_clone__should_clone_local(const char *url_or_path, git_clone_local_t loc
382382
return is_local;
383383
}
384384

385-
int git_clone(
385+
static int git__clone(
386386
git_repository **out,
387387
const char *url,
388388
const char *local_path,
389-
const git_clone_options *_options)
389+
const git_clone_options *_options,
390+
int use_existing)
390391
{
391392
int error = 0;
392393
git_repository *repo = NULL;
@@ -403,7 +404,7 @@ int git_clone(
403404
GIT_ERROR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
404405

405406
/* Only clone to a new directory or an empty directory */
406-
if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) {
407+
if (git_path_exists(local_path) && !use_existing && !git_path_is_empty_dir(local_path)) {
407408
git_error_set(GIT_ERROR_INVALID,
408409
"'%s' exists and is not an empty directory", local_path);
409410
return GIT_EEXISTS;
@@ -455,6 +456,25 @@ int git_clone(
455456
return error;
456457
}
457458

459+
int git_clone(
460+
git_repository **out,
461+
const char *url,
462+
const char *local_path,
463+
const git_clone_options *_options)
464+
{
465+
return git__clone(out, url, local_path, _options, 0);
466+
}
467+
468+
int git_clone__submodule(
469+
git_repository **out,
470+
const char *url,
471+
const char *local_path,
472+
const git_clone_options *_options)
473+
{
474+
return git__clone(out, url, local_path, _options, 1);
475+
}
476+
477+
458478
int git_clone_init_options(git_clone_options *opts, unsigned int version)
459479
{
460480
GIT_INIT_STRUCTURE_FROM_TEMPLATE(

src/clone.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "git2/clone.h"
1313

14+
extern int git_clone__submodule(git_repository **out,
15+
const char *url, const char *local_path,
16+
const git_clone_options *_options);
17+
1418
extern int git_clone__should_clone_local(const char *url, git_clone_local_t local);
1519

1620
#endif

src/submodule.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "path.h"
2424
#include "index.h"
2525
#include "worktree.h"
26+
#include "clone.h"
2627

2728
#define GIT_MODULES_FILE ".gitmodules"
2829

@@ -815,6 +816,54 @@ int git_submodule_repo_init(
815816
return error;
816817
}
817818

819+
static int clone_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
820+
{
821+
GIT_UNUSED(url);
822+
GIT_UNUSED(payload);
823+
return git_remote_lookup(out, repo, name);
824+
}
825+
826+
static int clone_return_repo(git_repository **out, const char *path, int bare, void *payload)
827+
{
828+
git_submodule *sm = payload;
829+
830+
GIT_UNUSED(path);
831+
GIT_UNUSED(bare);
832+
return git_submodule_open(out, sm);
833+
}
834+
835+
int git_submodule_add_clone(git_repository **out, git_submodule *submodule)
836+
{
837+
int error;
838+
git_repository *clone;
839+
git_buf rel_path = GIT_BUF_INIT;
840+
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
841+
842+
assert(submodule);
843+
844+
opts.repository_cb = clone_return_repo;
845+
opts.repository_cb_payload = submodule;
846+
opts.remote_cb = clone_return_origin;
847+
opts.remote_cb_payload = submodule;
848+
849+
git_buf_puts(&rel_path, git_repository_workdir(git_submodule_owner(submodule)));
850+
git_buf_joinpath(&rel_path, git_buf_cstr(&rel_path), git_submodule_path(submodule));
851+
852+
error = git_clone__submodule(&clone, git_submodule_url(submodule), git_buf_cstr(&rel_path), &opts);
853+
if (error < 0)
854+
goto cleanup;
855+
856+
if (!out)
857+
git_repository_free(clone);
858+
else
859+
*out = clone;
860+
861+
cleanup:
862+
git_buf_dispose(&rel_path);
863+
864+
return error;
865+
}
866+
818867
int git_submodule_add_finalize(git_submodule *sm)
819868
{
820869
int error;

tests/clone/nonetwork.c

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -353,44 +353,19 @@ void test_clone_nonetwork__clone_from_empty_sets_upstream(void)
353353
cl_fixture_cleanup("./repowithunborn");
354354
}
355355

356-
static int just_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload)
357-
{
358-
GIT_UNUSED(url); GIT_UNUSED(payload);
359-
360-
return git_remote_lookup(out, repo, name);
361-
}
362-
363-
static int just_return_repo(git_repository **out, const char *path, int bare, void *payload)
364-
{
365-
git_submodule *sm = payload;
366-
367-
GIT_UNUSED(path); GIT_UNUSED(bare);
368-
369-
return git_submodule_open(out, sm);
370-
}
371-
372356
void test_clone_nonetwork__clone_submodule(void)
373357
{
374-
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
375358
git_index *index;
376359
git_oid tree_id, commit_id;
377360
git_submodule *sm;
378361
git_signature *sig;
379-
git_repository *sm_repo;
380362

381363
cl_git_pass(git_repository_init(&g_repo, "willaddsubmodule", false));
382364

383-
384365
/* Create the submodule structure, clone into it and finalize */
385366
cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo", true));
386-
387-
clone_opts.repository_cb = just_return_repo;
388-
clone_opts.repository_cb_payload = sm;
389-
clone_opts.remote_cb = just_return_origin;
390-
clone_opts.remote_cb_payload = sm;
391-
cl_git_pass(git_clone(&sm_repo, cl_fixture("testrepo.git"), "testrepo", &clone_opts));
367+
cl_git_pass(git_submodule_add_clone(NULL, sm));
392368
cl_git_pass(git_submodule_add_finalize(sm));
393-
git_repository_free(sm_repo);
394369
git_submodule_free(sm);
395370

396371
cl_git_pass(git_repository_index(&index, g_repo));

0 commit comments

Comments
 (0)