diff options
| author | Ben Straub <bstraub@github.com> | 2012-06-20 20:51:32 -0700 |
|---|---|---|
| committer | Ben Straub <bstraub@github.com> | 2012-06-21 09:53:45 -0700 |
| commit | 4fbc899acfea62cc049f8cbc2db803b375888c3d (patch) | |
| tree | ea2a641f153c8e4d3440fd4b07888fd322969d05 /src/clone.c | |
| parent | 8340dd5d5f0daf3ffda0c7ecb1791b21a152ecd2 (diff) | |
| download | libgit2-4fbc899acfea62cc049f8cbc2db803b375888c3d.tar.gz | |
Clone: local branch for remote HEAD.
Now creating a local branch that tracks to the
origin's HEAD branch, and setting HEAD to that.
Diffstat (limited to 'src/clone.c')
| -rw-r--r-- | src/clone.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/src/clone.c b/src/clone.c index a737d972c..bc26b9d3c 100644 --- a/src/clone.c +++ b/src/clone.c @@ -10,37 +10,121 @@ #include "git2/clone.h" #include "git2/remote.h" #include "git2/revparse.h" +#include "git2/branch.h" +#include "git2/config.h" #include "common.h" #include "remote.h" #include "fileops.h" +#include "refs.h" // TODO #include "checkout.h" GIT_BEGIN_DECL +struct HeadInfo { + git_repository *repo; + git_oid remote_head_oid; + git_buf branchname; +}; static int git_checkout_force(git_repository *repo) { - /* TODO */ + /* TODO + * -> Line endings + */ + return 0; +} + +static int create_tracking_branch(struct HeadInfo *info) +{ + git_object *head_obj = NULL; + git_oid branch_oid; + int retcode = GIT_ERROR; + const char *branchname = git_buf_cstr(&info->branchname); + + /* Find the target commit */ + if (git_object_lookup(&head_obj, info->repo, &info->remote_head_oid, GIT_OBJ_ANY) < 0) + return GIT_ERROR; + + /* Create the new branch */ + if (!git_branch_create(&branch_oid, info->repo, branchname, head_obj, 0)) { + /* Set up tracking */ + git_config *cfg; + if (!git_repository_config(&cfg, info->repo)) { + git_buf remote = GIT_BUF_INIT; + git_buf merge = GIT_BUF_INIT; + git_buf merge_target = GIT_BUF_INIT; + if (!git_buf_printf(&remote, "branch.%s.remote", branchname) && + !git_buf_printf(&merge, "branch.%s.merge", branchname) && + !git_buf_printf(&merge_target, "refs/heads/%s", branchname) && + !git_config_set_string(cfg, git_buf_cstr(&remote), "origin") && + !git_config_set_string(cfg, git_buf_cstr(&merge), git_buf_cstr(&merge_target))) { + retcode = 0; + } + git_buf_free(&remote); + git_buf_free(&merge); + git_buf_free(&merge_target); + git_config_free(cfg); + } + } + + return retcode; +} + +static int reference_matches_remote_head(const char *head_name, void *payload) +{ + struct HeadInfo *head_info = (struct HeadInfo *)payload; + git_oid oid; + + /* Stop looking if we've already found a match */ + if (git_buf_len(&head_info->branchname) > 0) return 0; + + if (!git_reference_name_to_oid(&oid, head_info->repo, head_name) && + !git_oid_cmp(&head_info->remote_head_oid, &oid)) { + /* strlen("refs/remotes/origin/") == 20 */ + git_buf_puts(&head_info->branchname, head_name+20); + } return 0; } static int update_head_to_remote(git_repository *repo, git_remote *remote) { int retcode = 0; + git_remote_head *remote_head; + struct HeadInfo head_info; /* Get the remote's HEAD. This is always the first ref in remote->refs. */ - git_buf remote_default_branch = GIT_BUF_INIT; - /* TODO */ - - git_buf_free(&remote_default_branch); + remote_head = remote->refs.contents[0]; + git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid); + git_buf_init(&head_info.branchname, 16); + head_info.repo = repo; + + /* Find the branch the remote head belongs to. */ + if (!git_reference_foreach(repo, GIT_REF_LISTALL, reference_matches_remote_head, &head_info) && + git_buf_len(&head_info.branchname) > 0) { + if (!create_tracking_branch(&head_info)) { + /* Update HEAD to point to the new branch */ + git_reference *head; + if (!git_reference_lookup(&head, repo, "HEAD")) { + git_buf target = GIT_BUF_INIT; + if (!git_buf_printf(&target, "refs/heads/%s", git_buf_cstr(&head_info.branchname)) && + !git_reference_set_target(head, git_buf_cstr(&target))) { + retcode = 0; + } + git_buf_free(&target); + git_reference_free(head); + } + } + } + git_buf_free(&head_info.branchname); return retcode; } /* * submodules? * filemodes? + * Line endings */ |
