Commit 88aef76635c012ac8dc770e0f97abc37980decf9

Sascha Cunz 2013-01-11T02:45:55

Implement analog for 'git checkout --branch xxx ...'

diff --git a/include/git2/clone.h b/include/git2/clone.h
index e299c15..9bb92eb 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 32ac08b..e9686dc 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;
 					}
 				}