Commit 1cc974ab by Ben Straub

Augment clone API with reflog parameters

parent b31ebfbc
...@@ -45,6 +45,8 @@ GIT_BEGIN_DECL ...@@ -45,6 +45,8 @@ GIT_BEGIN_DECL
* default is "origin". * default is "origin".
* - `checkout_branch` gives the name of the branch to checkout. NULL * - `checkout_branch` gives the name of the branch to checkout. NULL
* means use the remote's HEAD. * means use the remote's HEAD.
* - `signature` is the identity used when updating the reflog. NULL means to
* use the default signature using the config.
*/ */
typedef struct git_clone_options { typedef struct git_clone_options {
...@@ -57,6 +59,7 @@ typedef struct git_clone_options { ...@@ -57,6 +59,7 @@ typedef struct git_clone_options {
int ignore_cert_errors; int ignore_cert_errors;
const char *remote_name; const char *remote_name;
const char* checkout_branch; const char* checkout_branch;
git_signature *signature;
} git_clone_options; } git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1 #define GIT_CLONE_OPTIONS_VERSION 1
...@@ -96,6 +99,7 @@ GIT_EXTERN(int) git_clone( ...@@ -96,6 +99,7 @@ GIT_EXTERN(int) git_clone(
* @param co_opts options to use during checkout * @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the * @param branch the branch to checkout after the clone, pass NULL for the
* remote's default branch * remote's default branch
* @param signature The identity used when updating the reflog.
* @return 0 on success, any non-zero return value from a callback * @return 0 on success, any non-zero return value from a callback
* function, or a negative value to indicate an error (use * function, or a negative value to indicate an error (use
* `giterr_last` for a detailed error message) * `giterr_last` for a detailed error message)
...@@ -104,7 +108,8 @@ GIT_EXTERN(int) git_clone_into( ...@@ -104,7 +108,8 @@ GIT_EXTERN(int) git_clone_into(
git_repository *repo, git_repository *repo,
git_remote *remote, git_remote *remote,
const git_checkout_opts *co_opts, const git_checkout_opts *co_opts,
const char *branch); const char *branch,
const git_signature *signature);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -27,7 +27,9 @@ static int create_branch( ...@@ -27,7 +27,9 @@ static int create_branch(
git_reference **branch, git_reference **branch,
git_repository *repo, git_repository *repo,
const git_oid *target, const git_oid *target,
const char *name) const char *name,
const git_signature *signature,
const char *log_message)
{ {
git_commit *head_obj = NULL; git_commit *head_obj = NULL;
git_reference *branch_ref = NULL; git_reference *branch_ref = NULL;
...@@ -38,7 +40,7 @@ static int create_branch( ...@@ -38,7 +40,7 @@ static int create_branch(
return error; return error;
/* Create the new branch */ /* Create the new branch */
error = git_branch_create(&branch_ref, repo, name, head_obj, 0, NULL, NULL); error = git_branch_create(&branch_ref, repo, name, head_obj, 0, signature, log_message);
git_commit_free(head_obj); git_commit_free(head_obj);
...@@ -87,11 +89,13 @@ static int create_tracking_branch( ...@@ -87,11 +89,13 @@ static int create_tracking_branch(
git_reference **branch, git_reference **branch,
git_repository *repo, git_repository *repo,
const git_oid *target, const git_oid *target,
const char *branch_name) const char *branch_name,
const git_signature *signature,
const char *log_message)
{ {
int error; int error;
if ((error = create_branch(branch, repo, target, branch_name)) < 0) if ((error = create_branch(branch, repo, target, branch_name, signature, log_message)) < 0)
return error; return error;
return setup_tracking_config( return setup_tracking_config(
...@@ -153,15 +157,17 @@ static int update_head_to_new_branch( ...@@ -153,15 +157,17 @@ static int update_head_to_new_branch(
git_repository *repo, git_repository *repo,
const git_oid *target, const git_oid *target,
const char *name, const char *name,
const git_signature *signature,
const char *reflog_message) const char *reflog_message)
{ {
git_reference *tracking_branch = NULL; git_reference *tracking_branch = NULL;
int error = create_tracking_branch(&tracking_branch, repo, target, name); int error = create_tracking_branch(&tracking_branch, repo, target, name,
signature, reflog_message);
if (!error) if (!error)
error = git_repository_set_head( error = git_repository_set_head(
repo, git_reference_name(tracking_branch), repo, git_reference_name(tracking_branch),
NULL, reflog_message); signature, reflog_message);
git_reference_free(tracking_branch); git_reference_free(tracking_branch);
...@@ -171,6 +177,7 @@ static int update_head_to_new_branch( ...@@ -171,6 +177,7 @@ static int update_head_to_new_branch(
static int update_head_to_remote( static int update_head_to_remote(
git_repository *repo, git_repository *repo,
git_remote *remote, git_remote *remote,
const git_signature *signature,
const char *reflog_message) const char *reflog_message)
{ {
int error = 0; int error = 0;
...@@ -221,7 +228,7 @@ static int update_head_to_remote( ...@@ -221,7 +228,7 @@ static int update_head_to_remote(
repo, repo,
&head_info.remote_head_oid, &head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname), git_buf_cstr(&head_info.branchname),
reflog_message); signature, reflog_message);
goto cleanup; goto cleanup;
} }
...@@ -236,7 +243,7 @@ static int update_head_to_remote( ...@@ -236,7 +243,7 @@ static int update_head_to_remote(
repo, repo,
&head_info.remote_head_oid, &head_info.remote_head_oid,
git_buf_cstr(&head_info.branchname), git_buf_cstr(&head_info.branchname),
reflog_message); signature, reflog_message);
} else { } else {
error = git_repository_set_head_detached( error = git_repository_set_head_detached(
repo, &head_info.remote_head_oid, NULL, reflog_message); repo, &head_info.remote_head_oid, NULL, reflog_message);
...@@ -252,6 +259,7 @@ static int update_head_to_branch( ...@@ -252,6 +259,7 @@ static int update_head_to_branch(
git_repository *repo, git_repository *repo,
const char *remote_name, const char *remote_name,
const char *branch, const char *branch,
const git_signature *signature,
const char *reflog_message) const char *reflog_message)
{ {
int retcode; int retcode;
...@@ -267,7 +275,8 @@ static int update_head_to_branch( ...@@ -267,7 +275,8 @@ static int update_head_to_branch(
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0) if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup; goto cleanup;
retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch, reflog_message); retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch,
signature, reflog_message);
cleanup: cleanup:
git_reference_free(remote_ref); git_reference_free(remote_ref);
...@@ -327,7 +336,7 @@ static bool should_checkout( ...@@ -327,7 +336,7 @@ static bool should_checkout(
return !git_repository_head_unborn(repo); return !git_repository_head_unborn(repo);
} }
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch, const git_signature *signature)
{ {
int error = 0, old_fetchhead; int error = 0, old_fetchhead;
git_strarray refspecs; git_strarray refspecs;
...@@ -355,10 +364,11 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ ...@@ -355,10 +364,11 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
goto cleanup; goto cleanup;
if (branch) if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch, git_buf_cstr(&reflog_message)); error = update_head_to_branch(repo, git_remote_name(remote), branch,
signature, git_buf_cstr(&reflog_message));
/* Point HEAD to the same ref as the remote's head */ /* Point HEAD to the same ref as the remote's head */
else else
error = update_head_to_remote(repo, remote, git_buf_cstr(&reflog_message)); error = update_head_to_remote(repo, remote, signature, git_buf_cstr(&reflog_message));
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts); error = git_checkout_head(repo, co_opts);
...@@ -414,7 +424,7 @@ int git_clone( ...@@ -414,7 +424,7 @@ int git_clone(
if (!(error = create_and_configure_origin(&origin, repo, url, &options))) { if (!(error = create_and_configure_origin(&origin, repo, url, &options))) {
error = git_clone_into( error = git_clone_into(
repo, origin, &options.checkout_opts, options.checkout_branch); repo, origin, &options.checkout_opts, options.checkout_branch, options.signature);
git_remote_free(origin); git_remote_free(origin);
} }
......
...@@ -232,3 +232,47 @@ void test_clone_nonetwork__can_detached_head(void) ...@@ -232,3 +232,47 @@ void test_clone_nonetwork__can_detached_head(void)
cl_fixture_cleanup("./foo1"); cl_fixture_cleanup("./foo1");
} }
static void assert_correct_reflog(const char *name)
{
git_reflog *log;
const git_reflog_entry *entry;
char expected_log_message[128] = {0};
sprintf(expected_log_message, "clone: from %s", cl_git_fixture_url("testrepo.git"));
cl_git_pass(git_reflog_read(&log, g_repo, name));
cl_assert_equal_i(1, git_reflog_entrycount(log));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s(expected_log_message, git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
}
void test_clone_nonetwork__clone_updates_reflog_properly(void)
{
cl_git_pass(git_signature_now(&g_options.signature, "Me", "foo@example.com"));
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
assert_correct_reflog("HEAD");
assert_correct_reflog("refs/heads/master");
git_signature_free(g_options.signature);
}
void test_clone_nonetwork__clone_into_updates_reflog_properly(void)
{
git_remote *remote;
git_signature *sig;
cl_git_pass(git_signature_now(&sig, "Me", "foo@example.com"));
cl_git_pass(git_repository_init(&g_repo, "./foo", false));
cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_git_fixture_url("testrepo.git")));
cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, sig));
assert_correct_reflog("HEAD");
assert_correct_reflog("refs/heads/master");
git_remote_free(remote);
git_signature_free(g_options.signature);
}
...@@ -147,7 +147,7 @@ void test_online_clone__clone_into(void) ...@@ -147,7 +147,7 @@ void test_online_clone__clone_into(void)
callbacks.payload = &fetch_progress_cb_was_called; callbacks.payload = &fetch_progress_cb_was_called;
git_remote_set_callbacks(remote, &callbacks); git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL)); cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment