From 1cc974ab625c2fa0794130eb97ca88c449fc1a06 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 27 Jan 2014 14:40:31 -0800 Subject: [PATCH] Augment clone API with reflog parameters --- include/git2/clone.h | 7 ++++++- src/clone.c | 36 +++++++++++++++++++++------------ tests/clone/nonetwork.c | 44 +++++++++++++++++++++++++++++++++++++++++ tests/online/clone.c | 2 +- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index 59a73aa15..3e885d103 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -45,6 +45,8 @@ GIT_BEGIN_DECL * default is "origin". * - `checkout_branch` gives the name of the branch to checkout. NULL * 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 { @@ -57,6 +59,7 @@ typedef struct git_clone_options { int ignore_cert_errors; const char *remote_name; const char* checkout_branch; + git_signature *signature; } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 @@ -96,6 +99,7 @@ GIT_EXTERN(int) git_clone( * @param co_opts options to use during checkout * @param branch the branch to checkout after the clone, pass NULL for the * 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 * function, or a negative value to indicate an error (use * `giterr_last` for a detailed error message) @@ -104,7 +108,8 @@ GIT_EXTERN(int) git_clone_into( git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, - const char *branch); + const char *branch, + const git_signature *signature); /** @} */ GIT_END_DECL diff --git a/src/clone.c b/src/clone.c index 288e9d2c8..97d25bdcd 100644 --- a/src/clone.c +++ b/src/clone.c @@ -27,7 +27,9 @@ static int create_branch( git_reference **branch, git_repository *repo, const git_oid *target, - const char *name) + const char *name, + const git_signature *signature, + const char *log_message) { git_commit *head_obj = NULL; git_reference *branch_ref = NULL; @@ -38,7 +40,7 @@ static int create_branch( return error; /* 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); @@ -87,11 +89,13 @@ static int create_tracking_branch( git_reference **branch, git_repository *repo, const git_oid *target, - const char *branch_name) + const char *branch_name, + const git_signature *signature, + const char *log_message) { 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 setup_tracking_config( @@ -153,15 +157,17 @@ static int update_head_to_new_branch( git_repository *repo, const git_oid *target, const char *name, + const git_signature *signature, const char *reflog_message) { 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) error = git_repository_set_head( repo, git_reference_name(tracking_branch), - NULL, reflog_message); + signature, reflog_message); git_reference_free(tracking_branch); @@ -171,6 +177,7 @@ static int update_head_to_new_branch( static int update_head_to_remote( git_repository *repo, git_remote *remote, + const git_signature *signature, const char *reflog_message) { int error = 0; @@ -221,7 +228,7 @@ static int update_head_to_remote( repo, &head_info.remote_head_oid, git_buf_cstr(&head_info.branchname), - reflog_message); + signature, reflog_message); goto cleanup; } @@ -236,7 +243,7 @@ static int update_head_to_remote( repo, &head_info.remote_head_oid, git_buf_cstr(&head_info.branchname), - reflog_message); + signature, reflog_message); } else { error = git_repository_set_head_detached( repo, &head_info.remote_head_oid, NULL, reflog_message); @@ -252,6 +259,7 @@ static int update_head_to_branch( git_repository *repo, const char *remote_name, const char *branch, + const git_signature *signature, const char *reflog_message) { int retcode; @@ -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) 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: git_reference_free(remote_ref); @@ -327,7 +336,7 @@ static bool should_checkout( 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; git_strarray refspecs; @@ -355,10 +364,11 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ goto cleanup; 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 */ 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)) error = git_checkout_head(repo, co_opts); @@ -414,7 +424,7 @@ int git_clone( if (!(error = create_and_configure_origin(&origin, repo, url, &options))) { 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); } diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index 863412cdb..14d2bbf59 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -232,3 +232,47 @@ void test_clone_nonetwork__can_detached_head(void) 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); +} diff --git a/tests/online/clone.c b/tests/online/clone.c index be4421ae5..1222d174d 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -147,7 +147,7 @@ void test_online_clone__clone_into(void) callbacks.payload = &fetch_progress_cb_was_called; 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_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));