From 88aef76635c012ac8dc770e0f97abc37980decf9 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Fri, 11 Jan 2013 02:45:55 +0100 Subject: [PATCH] Implement analog for 'git checkout --branch xxx ...' --- include/git2/clone.h | 3 +++ src/clone.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index e299c155d..9bb92ebdd 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -57,6 +57,8 @@ GIT_BEGIN_DECL * the origin remote before the fetch is initiated. * - `remote_autotag` may be used to specify the autotag setting before the * initial fetch. + * - `checkout_branch` gives the name of the branch to checkout. NULL means + * use the remote's HEAD. */ typedef struct git_clone_options { @@ -76,6 +78,7 @@ typedef struct git_clone_options { git_transport *transport; git_remote_callbacks *remote_callbacks; git_remote_autotag_option_t remote_autotag; + const char* checkout_branch; } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 diff --git a/src/clone.c b/src/clone.c index 32ac08bf2..e9686dce4 100644 --- a/src/clone.c +++ b/src/clone.c @@ -260,6 +260,31 @@ cleanup: return retcode; } +static int update_head_to_branch( + git_repository *repo, + const git_clone_options *options) +{ + int retcode; + git_buf remote_branch_name = GIT_BUF_INIT; + git_reference* remote_ref = NULL; + + assert(options->checkout_branch); + + if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s", + options->remote_name, options->checkout_branch)) < 0 ) + goto cleanup; + + 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), + options->checkout_branch); + +cleanup: + git_reference_free(remote_ref); + return retcode; +} + /* * submodules? */ @@ -331,8 +356,13 @@ static int setup_remotes_and_fetch( options->fetch_progress_payload)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { + /* Point HEAD to the requested branch */ + if (options->checkout_branch) { + if (!update_head_to_branch(repo, options)) + retcode = 0; + } /* Point HEAD to the same ref as the remote's head */ - if (!update_head_to_remote(repo, origin)) { + else if (!update_head_to_remote(repo, origin)) { retcode = 0; } }