Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
4c0dea5a
Unverified
Commit
4c0dea5a
authored
Oct 17, 2019
by
Patrick Steinhardt
Committed by
GitHub
Oct 17, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4637 from tiennou/feature/submodule-easy-clone
Provide a wrapper for simple submodule clone steps
parents
0298e0a6
73e9535d
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
169 additions
and
58 deletions
+169
-58
include/git2/submodule.h
+18
-1
src/clone.c
+22
-3
src/clone.h
+4
-0
src/submodule.c
+59
-0
tests/clone/nonetwork.c
+0
-54
tests/submodule/add.c
+66
-0
No files found.
include/git2/submodule.h
View file @
4c0dea5a
...
...
@@ -263,7 +263,8 @@ GIT_EXTERN(int) git_submodule_foreach(
* from the working directory to the new repo.
*
* To fully emulate "git submodule add" call this function, then open the
* submodule repo and perform the clone step as needed. Lastly, call
* submodule repo and perform the clone step as needed (if you don't need
* anything custom see `git_submodule_add_clone()`). Lastly, call
* `git_submodule_add_finalize()` to wrap up adding the new submodule and
* .gitmodules to the index to be ready to commit.
*
...
...
@@ -286,6 +287,22 @@ GIT_EXTERN(int) git_submodule_add_setup(
int
use_gitlink
);
/**
* Perform the clone step for a newly created submodule.
*
* This performs the necessary `git_clone` to setup a newly-created submodule.
*
* @param out The newly created repository object. Optional.
* @param submodule The submodule currently waiting for its clone.
* @param opts The options to use.
*
* @return 0 on success, -1 on other errors (see git_clone).
*/
GIT_EXTERN
(
int
)
git_submodule_clone
(
git_repository
**
out
,
git_submodule
*
submodule
,
const
git_submodule_update_options
*
opts
);
/**
* Resolve the setup of a new git submodule.
*
* This should be called on a submodule once you have called add setup
...
...
src/clone.c
View file @
4c0dea5a
...
...
@@ -382,11 +382,12 @@ done:
return
is_local
;
}
int
git
_clone
(
static
int
git_
_clone
(
git_repository
**
out
,
const
char
*
url
,
const
char
*
local_path
,
const
git_clone_options
*
_options
)
const
git_clone_options
*
_options
,
int
use_existing
)
{
int
error
=
0
;
git_repository
*
repo
=
NULL
;
...
...
@@ -403,7 +404,7 @@ int git_clone(
GIT_ERROR_CHECK_VERSION
(
&
options
,
GIT_CLONE_OPTIONS_VERSION
,
"git_clone_options"
);
/* Only clone to a new directory or an empty directory */
if
(
git_path_exists
(
local_path
)
&&
!
git_path_is_empty_dir
(
local_path
))
{
if
(
git_path_exists
(
local_path
)
&&
!
use_existing
&&
!
git_path_is_empty_dir
(
local_path
))
{
git_error_set
(
GIT_ERROR_INVALID
,
"'%s' exists and is not an empty directory"
,
local_path
);
return
GIT_EEXISTS
;
...
...
@@ -455,6 +456,24 @@ int git_clone(
return
error
;
}
int
git_clone
(
git_repository
**
out
,
const
char
*
url
,
const
char
*
local_path
,
const
git_clone_options
*
_options
)
{
return
git__clone
(
out
,
url
,
local_path
,
_options
,
0
);
}
int
git_clone__submodule
(
git_repository
**
out
,
const
char
*
url
,
const
char
*
local_path
,
const
git_clone_options
*
_options
)
{
return
git__clone
(
out
,
url
,
local_path
,
_options
,
1
);
}
int
git_clone_options_init
(
git_clone_options
*
opts
,
unsigned
int
version
)
{
GIT_INIT_STRUCTURE_FROM_TEMPLATE
(
...
...
src/clone.h
View file @
4c0dea5a
...
...
@@ -11,6 +11,10 @@
#include "git2/clone.h"
extern
int
git_clone__submodule
(
git_repository
**
out
,
const
char
*
url
,
const
char
*
local_path
,
const
git_clone_options
*
_options
);
extern
int
git_clone__should_clone_local
(
const
char
*
url
,
git_clone_local_t
local
);
#endif
src/submodule.c
View file @
4c0dea5a
...
...
@@ -23,6 +23,7 @@
#include "path.h"
#include "index.h"
#include "worktree.h"
#include "clone.h"
#define GIT_MODULES_FILE ".gitmodules"
...
...
@@ -815,6 +816,64 @@ done:
return
error
;
}
static
int
clone_return_origin
(
git_remote
**
out
,
git_repository
*
repo
,
const
char
*
name
,
const
char
*
url
,
void
*
payload
)
{
GIT_UNUSED
(
url
);
GIT_UNUSED
(
payload
);
return
git_remote_lookup
(
out
,
repo
,
name
);
}
static
int
clone_return_repo
(
git_repository
**
out
,
const
char
*
path
,
int
bare
,
void
*
payload
)
{
git_submodule
*
sm
=
payload
;
GIT_UNUSED
(
path
);
GIT_UNUSED
(
bare
);
return
git_submodule_open
(
out
,
sm
);
}
int
git_submodule_clone
(
git_repository
**
out
,
git_submodule
*
submodule
,
const
git_submodule_update_options
*
given_opts
)
{
int
error
;
git_repository
*
clone
;
git_buf
rel_path
=
GIT_BUF_INIT
;
git_submodule_update_options
sub_opts
=
GIT_SUBMODULE_UPDATE_OPTIONS_INIT
;
git_clone_options
opts
=
GIT_CLONE_OPTIONS_INIT
;
assert
(
submodule
);
if
(
given_opts
)
memcpy
(
&
sub_opts
,
given_opts
,
sizeof
(
sub_opts
));
GIT_ERROR_CHECK_VERSION
(
&
sub_opts
,
GIT_SUBMODULE_UPDATE_OPTIONS_VERSION
,
"git_submodule_update_options"
);
memcpy
(
&
opts
.
checkout_opts
,
&
sub_opts
.
checkout_opts
,
sizeof
(
sub_opts
.
checkout_opts
));
memcpy
(
&
opts
.
fetch_opts
,
&
sub_opts
.
fetch_opts
,
sizeof
(
sub_opts
.
fetch_opts
));
opts
.
repository_cb
=
clone_return_repo
;
opts
.
repository_cb_payload
=
submodule
;
opts
.
remote_cb
=
clone_return_origin
;
opts
.
remote_cb_payload
=
submodule
;
git_buf_puts
(
&
rel_path
,
git_repository_workdir
(
git_submodule_owner
(
submodule
)));
git_buf_joinpath
(
&
rel_path
,
git_buf_cstr
(
&
rel_path
),
git_submodule_path
(
submodule
));
GIT_ERROR_CHECK_ALLOC_BUF
(
&
rel_path
);
error
=
git_clone__submodule
(
&
clone
,
git_submodule_url
(
submodule
),
git_buf_cstr
(
&
rel_path
),
&
opts
);
if
(
error
<
0
)
goto
cleanup
;
if
(
!
out
)
git_repository_free
(
clone
);
else
*
out
=
clone
;
cleanup:
git_buf_dispose
(
&
rel_path
);
return
error
;
}
int
git_submodule_add_finalize
(
git_submodule
*
sm
)
{
int
error
;
...
...
tests/clone/nonetwork.c
View file @
4c0dea5a
#include "clar_libgit2.h"
#include "git2/clone.h"
#include "git2/sys/commit.h"
#include "../submodule/submodule_helpers.h"
#include "remote.h"
#include "futils.h"
...
...
@@ -352,56 +351,3 @@ void test_clone_nonetwork__clone_from_empty_sets_upstream(void)
git_repository_free
(
repo
);
cl_fixture_cleanup
(
"./repowithunborn"
);
}
static
int
just_return_origin
(
git_remote
**
out
,
git_repository
*
repo
,
const
char
*
name
,
const
char
*
url
,
void
*
payload
)
{
GIT_UNUSED
(
url
);
GIT_UNUSED
(
payload
);
return
git_remote_lookup
(
out
,
repo
,
name
);
}
static
int
just_return_repo
(
git_repository
**
out
,
const
char
*
path
,
int
bare
,
void
*
payload
)
{
git_submodule
*
sm
=
payload
;
GIT_UNUSED
(
path
);
GIT_UNUSED
(
bare
);
return
git_submodule_open
(
out
,
sm
);
}
void
test_clone_nonetwork__clone_submodule
(
void
)
{
git_clone_options
clone_opts
=
GIT_CLONE_OPTIONS_INIT
;
git_index
*
index
;
git_oid
tree_id
,
commit_id
;
git_submodule
*
sm
;
git_signature
*
sig
;
git_repository
*
sm_repo
;
cl_git_pass
(
git_repository_init
(
&
g_repo
,
"willaddsubmodule"
,
false
));
/* Create the submodule structure, clone into it and finalize */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
cl_fixture
(
"testrepo.git"
),
"testrepo"
,
true
));
clone_opts
.
repository_cb
=
just_return_repo
;
clone_opts
.
repository_cb_payload
=
sm
;
clone_opts
.
remote_cb
=
just_return_origin
;
clone_opts
.
remote_cb_payload
=
sm
;
cl_git_pass
(
git_clone
(
&
sm_repo
,
cl_fixture
(
"testrepo.git"
),
"testrepo"
,
&
clone_opts
));
cl_git_pass
(
git_submodule_add_finalize
(
sm
));
git_repository_free
(
sm_repo
);
git_submodule_free
(
sm
);
cl_git_pass
(
git_repository_index
(
&
index
,
g_repo
));
cl_git_pass
(
git_index_write_tree
(
&
tree_id
,
index
));
git_index_free
(
index
);
cl_git_pass
(
git_signature_now
(
&
sig
,
"Submoduler"
,
"submoduler@local"
));
cl_git_pass
(
git_commit_create_from_ids
(
&
commit_id
,
g_repo
,
"HEAD"
,
sig
,
sig
,
NULL
,
"A submodule
\n
"
,
&
tree_id
,
0
,
NULL
));
git_signature_free
(
sig
);
assert_submodule_exists
(
g_repo
,
"testrepo"
);
}
tests/submodule/add.c
View file @
4c0dea5a
...
...
@@ -5,6 +5,7 @@
#include "config/config_helpers.h"
#include "futils.h"
#include "repository.h"
#include "git2/sys/commit.h"
static
git_repository
*
g_repo
=
NULL
;
static
const
char
*
valid_blob_id
=
"fa49b077972391ad58037050f2a75f74e3671e92"
;
...
...
@@ -183,3 +184,68 @@ void test_submodule_add__file_exists_in_index(void)
git_submodule_free
(
sm
);
git_buf_dispose
(
&
name
);
}
void
test_submodule_add__submodule_clone
(
void
)
{
git_oid
tree_id
,
commit_id
;
git_signature
*
sig
;
git_submodule
*
sm
;
git_index
*
index
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
/* Create the submodule structure, clone into it and finalize */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
cl_fixture
(
"testrepo.git"
),
"testrepo-add"
,
true
));
cl_git_pass
(
git_submodule_clone
(
NULL
,
sm
,
NULL
));
cl_git_pass
(
git_submodule_add_finalize
(
sm
));
/* Create the submodule commit */
cl_git_pass
(
git_repository_index
(
&
index
,
g_repo
));
cl_git_pass
(
git_index_write_tree
(
&
tree_id
,
index
));
cl_git_pass
(
git_signature_now
(
&
sig
,
"Submoduler"
,
"submoduler@local"
));
cl_git_pass
(
git_commit_create_from_ids
(
&
commit_id
,
g_repo
,
"HEAD"
,
sig
,
sig
,
NULL
,
"A submodule
\n
"
,
&
tree_id
,
0
,
NULL
));
assert_submodule_exists
(
g_repo
,
"testrepo-add"
);
git_signature_free
(
sig
);
git_submodule_free
(
sm
);
git_index_free
(
index
);
}
void
test_submodule_add__submodule_clone_into_nonempty_dir_succeeds
(
void
)
{
git_submodule
*
sm
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
cl_git_pass
(
p_mkdir
(
"empty_standard_repo/sm"
,
0777
));
cl_git_mkfile
(
"empty_standard_repo/sm/foobar"
,
""
);
/* Create the submodule structure, clone into it and finalize */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
cl_fixture
(
"testrepo.git"
),
"sm"
,
true
));
cl_git_pass
(
git_submodule_clone
(
NULL
,
sm
,
NULL
));
cl_git_pass
(
git_submodule_add_finalize
(
sm
));
cl_assert
(
git_path_exists
(
"empty_standard_repo/sm/foobar"
));
assert_submodule_exists
(
g_repo
,
"sm"
);
git_submodule_free
(
sm
);
}
void
test_submodule_add__submodule_clone_twice_fails
(
void
)
{
git_submodule
*
sm
;
g_repo
=
cl_git_sandbox_init
(
"empty_standard_repo"
);
/* Create the submodule structure, clone into it and finalize */
cl_git_pass
(
git_submodule_add_setup
(
&
sm
,
g_repo
,
cl_fixture
(
"testrepo.git"
),
"sm"
,
true
));
cl_git_pass
(
git_submodule_clone
(
NULL
,
sm
,
NULL
));
cl_git_pass
(
git_submodule_add_finalize
(
sm
));
cl_git_fail
(
git_submodule_clone
(
NULL
,
sm
,
NULL
));
git_submodule_free
(
sm
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment