int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_remote *remote = NULL; int error; if ((error = ensure_remote_name_is_valid(name)) < 0) return error; if ((error = ensure_remote_doesnot_exist(repo, name)) < 0) return error; if (create_internal(&remote, repo, name, url, fetch) < 0) goto on_error; if (git_remote_save(remote) < 0) goto on_error; *out = remote; return 0; on_error: git_remote_free(remote); return -1; }
void test_clone_local__git_style_unc_paths(void) { #ifdef GIT_WIN32 git_repository *repo; git_remote *remote; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_buf git_unc = GIT_BUF_INIT; /* we use a fixture path because it needs to exist for us to want to clone */ const char *path = cl_fixture("testrepo.git"); cl_git_pass(git_style_unc_path(&git_unc, "localhost", path)); cl_git_pass(git_clone(&repo, git_unc.ptr, "./clone.git", &opts)); cl_git_pass(git_remote_lookup(&remote, repo, "origin")); cl_assert_equal_s(git_unc.ptr, git_remote_url(remote)); git_remote_free(remote); git_repository_free(repo); git_buf_free(&git_unc); cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES)); #endif }
int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url) { git_buf buf = GIT_BUF_INIT; git_remote *remote = NULL; int error; if ((error = ensure_remote_name_is_valid(name)) < 0) return error; if ((error = ensure_remote_doesnot_exist(repo, name)) < 0) return error; if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) return -1; if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0) goto on_error; git_buf_free(&buf); if (git_remote_save(remote) < 0) goto on_error; *out = remote; return 0; on_error: git_buf_free(&buf); git_remote_free(remote); return -1; }
/** * Fetch new data and update tips * * @param repo S4 class git_repository * @param name The name of the remote to fetch from * @param credentials The credentials for remote repository access. * @param msg The one line long message to be appended to the reflog * @return R_NilValue */ SEXP git2r_remote_fetch( SEXP repo, SEXP name, SEXP credentials, SEXP msg) { int err; SEXP result = R_NilValue; const git_transfer_progress *stats; git_remote *remote = NULL; git_repository *repository = NULL; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (git2r_arg_check_string(name)) git2r_error(git2r_err_string_arg, __func__, "name"); if (git2r_arg_check_credentials(credentials)) git2r_error(git2r_err_credentials_arg, __func__, "credentials"); if (git2r_arg_check_string(msg)) git2r_error(git2r_err_string_arg, __func__, "msg"); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0))); if (GIT_OK != err) goto cleanup; callbacks.credentials = &git2r_cred_acquire_cb; callbacks.payload = credentials; err = git_remote_set_callbacks(remote, &callbacks); if (GIT_OK != err) goto cleanup; err = git_remote_fetch(remote, NULL, CHAR(STRING_ELT(msg, 0))); if (GIT_OK != err) goto cleanup; stats = git_remote_stats(remote); PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_transfer_progress"))); git2r_transfer_progress_init(stats, result); cleanup: if (remote) { if (git_remote_connected(remote)) git_remote_disconnect(remote); git_remote_free(remote); } if (repository) git_repository_free(repository); if (R_NilValue != result) UNPROTECT(1); if (GIT_OK != err) git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message); return result; }
/** * Add a remote with the default fetch refspec to the repository's * configuration. * * @param repo S4 class git_repository * @param name The name of the remote * @param url The url of the remote * @return R_NilValue */ SEXP git2r_remote_add(SEXP repo, SEXP name, SEXP url) { int err; git_repository *repository = NULL; git_remote *remote = NULL; if (git2r_arg_check_string(name)) git2r_error(git2r_err_string_arg, __func__, "name"); if (git2r_arg_check_string(url)) git2r_error(git2r_err_string_arg, __func__, "url"); if (!git_remote_is_valid_name(CHAR(STRING_ELT(name, 0)))) git2r_error("Error in '%s': Invalid remote name", __func__, NULL); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git_remote_create(&remote, repository, CHAR(STRING_ELT(name, 0)), CHAR(STRING_ELT(url, 0))); if (remote) git_remote_free(remote); if (repository) git_repository_free(repository); if (GIT_OK != err) git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message); return R_NilValue; }
void test_network_remotelocal__cleanup(void) { git_remote_free(remote); git_buf_free(&file_path_buf); git_repository_free(repo); cl_fixture_cleanup("remotelocal"); }
void test_network_fetchlocal__clone_into_mirror(void) { git_buf path = GIT_BUF_INIT; git_repository *repo; git_remote *remote; git_reference *head; cl_git_pass(git_repository_init(&repo, "./foo.git", true)); cl_git_pass(git_remote_create(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"))); git_remote_clear_refspecs(remote); cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*")); cl_git_pass(git_clone_into(repo, remote, NULL, NULL, NULL)); cl_git_pass(git_reference_lookup(&head, repo, "HEAD")); cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); git_remote_free(remote); git_reference_free(head); git_repository_free(repo); git_buf_free(&path); cl_fixture_cleanup("./foo.git"); }
/** * Add a remote with the default fetch refspec to the repository's * configuration. * * @param repo S4 class git_repository * @param name The name of the remote * @param url The url of the remote * @return R_NilValue */ SEXP git2r_remote_add(SEXP repo, SEXP name, SEXP url) { int err; git_repository *repository = NULL; git_remote *remote = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_string(url)) git2r_error(__func__, NULL, "'url'", git2r_err_string_arg); if (!git_remote_is_valid_name(CHAR(STRING_ELT(name, 0)))) git2r_error(__func__, NULL, git2r_err_invalid_remote, NULL); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); err = git_remote_create(&remote, repository, CHAR(STRING_ELT(name, 0)), CHAR(STRING_ELT(url, 0))); if (remote) git_remote_free(remote); if (repository) git_repository_free(repository); if (err) git2r_error(__func__, giterr_last(), NULL, NULL); return R_NilValue; }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; git_strarray array, *active_refs = NULL; cl_git_pass(git_remote_load(&remote, g_repo, "origin")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); if(fetchspec != NULL) { array.count = 1; array.strings = (char **) &fetchspec; active_refs = &array; } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote, active_refs)); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); git_buf_free(&fetchhead_buf); cl_assert(equals); }
void test_network_remote_local__update_tips_for_new_remote(void) { git_repository *src_repo; git_repository *dst_repo; git_remote *new_remote; git_reference* branch; /* Copy test repo */ cl_fixture_sandbox("testrepo.git"); cl_git_pass(git_repository_open(&src_repo, "testrepo.git")); /* Set up an empty bare repo to push into */ cl_git_pass(git_repository_init(&dst_repo, "./localbare.git", 1)); /* Push to bare repo */ cl_git_pass(git_remote_create(&new_remote, src_repo, "bare", "./localbare.git")); cl_git_pass(git_remote_push(new_remote, &push_array, NULL)); /* Make sure remote branch has been created */ cl_git_pass(git_branch_lookup(&branch, src_repo, "bare/master", GIT_BRANCH_REMOTE)); git_reference_free(branch); git_remote_free(new_remote); git_repository_free(dst_repo); cl_fixture_cleanup("localbare.git"); git_repository_free(src_repo); cl_fixture_cleanup("testrepo.git"); }
void test_network_remote_local__push_delete(void) { git_repository *src_repo; git_repository *dst_repo; git_remote *remote; git_reference *ref; char *spec_push[] = { "refs/heads/master" }; char *spec_delete[] = { ":refs/heads/master" }; git_strarray specs = { spec_push, 1, }; src_repo = cl_git_sandbox_init("testrepo.git"); cl_git_pass(git_repository_init(&dst_repo, "target.git", 1)); cl_git_pass(git_remote_create(&remote, src_repo, "origin", "./target.git")); /* Push the master branch and verify it's there */ cl_git_pass(git_remote_push(remote, &specs, NULL)); cl_git_pass(git_reference_lookup(&ref, dst_repo, "refs/heads/master")); git_reference_free(ref); specs.strings = spec_delete; cl_git_pass(git_remote_push(remote, &specs, NULL)); cl_git_fail(git_reference_lookup(&ref, dst_repo, "refs/heads/master")); git_remote_free(remote); git_repository_free(dst_repo); cl_fixture_cleanup("target.git"); cl_git_sandbox_cleanup(); }
void test_network_remote_local__push_to_bare_remote(void) { char *refspec_strings[] = { "master:master", }; git_strarray array = { refspec_strings, 1, }; /* Should be able to push to a bare remote */ git_remote *localremote; /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* Set up an empty bare repo to push into */ { git_repository *localbarerepo; cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1)); git_repository_free(localbarerepo); } /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localbare.git")); cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL, NULL)); /* Try to push */ cl_git_pass(git_remote_upload(localremote, &push_array, NULL)); /* Clean up */ git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); }
void test_network_remote_local__push_to_non_bare_remote(void) { char *refspec_strings[] = { "master:master", }; git_strarray array = { refspec_strings, 1, }; /* Shouldn't be able to push to a non-bare remote */ git_remote *localremote; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, &fetch_opts, NULL)); /* Set up an empty non-bare repo to push into */ { git_repository *remoterepo = NULL; cl_git_pass(git_repository_init(&remoterepo, "localnonbare", 0)); git_repository_free(remoterepo); } /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localnonbare")); cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL, NULL)); /* Try to push */ cl_git_fail_with(GIT_EBAREREPO, git_remote_upload(localremote, &push_array, NULL)); /* Clean up */ git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); }
static void Remote_dealloc(Remote *self) { Py_CLEAR(self->repo); git_remote_free(self->remote); PyObject_Del(self); }
void test_online_clone__clone_mirror(void) { git_buf path = GIT_BUF_INIT; git_remote *remote; git_reference *head; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; bool fetch_progress_cb_was_called = false; cl_git_pass(git_repository_init(&g_repo, "./foo.git", true)); cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); callbacks.transfer_progress = &fetch_progress; callbacks.payload = &fetch_progress_cb_was_called; git_remote_set_callbacks(remote, &callbacks); git_remote_clear_refspecs(remote); cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*")); cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, NULL)); cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); cl_assert_equal_i(true, fetch_progress_cb_was_called); git_remote_free(remote); git_reference_free(head); git_buf_free(&path); git_repository_free(g_repo); g_repo = NULL; cl_fixture_cleanup("./foo.git"); }
void test_network_fetchlocal__partial(void) { git_repository *repo = cl_git_sandbox_init("partial-testrepo"); git_remote *origin; int callcount = 0; git_strarray refnames = {0}; const char *url; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; callbacks.transfer_progress = transfer_cb; callbacks.payload = &callcount; cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(1, (int)refnames.count); url = cl_git_fixture_url("testrepo.git"); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin, NULL, NULL)); git_strarray_free(&refnames); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */ cl_assert(callcount > 0); git_strarray_free(&refnames); git_remote_free(origin); }
static int use_remote(git_repository *repo, char *name) { git_remote *remote = NULL; int error; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; // Find the remote by name error = git_remote_load(&remote, repo, name); if (error < 0) { error = git_remote_create_inmemory(&remote, repo, NULL, name); if (error < 0) goto cleanup; } callbacks.credentials = cred_acquire_cb; git_remote_set_callbacks(remote, &callbacks); error = git_remote_connect(remote, GIT_DIRECTION_FETCH); if (error < 0) goto cleanup; error = git_remote_ls(remote, &show_ref__cb, NULL); cleanup: git_remote_free(remote); return error; }
void test_network_remote_rename__cleanup(void) { git_remote_free(_remote); _remote = NULL; cl_git_sandbox_cleanup(); }
void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) { git_repository *_repository; bool invoked = false; git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; opts.bare = true; cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git", "./fetch/lg2", &opts)); git_repository_free(_repository); cl_git_pass(git_repository_open(&_repository, "./fetch/lg2")); cl_git_pass(git_remote_load(&remote, _repository, "origin")); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_assert_equal_i(false, invoked); callbacks.transfer_progress = &transferProgressCallback; callbacks.payload = &invoked; git_remote_set_callbacks(remote, &callbacks); cl_git_pass(git_remote_download(remote)); cl_assert_equal_i(false, invoked); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); git_remote_free(remote); git_repository_free(_repository); }
static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch) { int error; git_buf reflog_message = GIT_BUF_INIT; git_fetch_options fetch_opts; git_remote *remote; assert(repo && _remote); if (!git_repository_is_empty(repo)) { giterr_set(GITERR_INVALID, "the repository is not empty"); return -1; } if ((error = git_remote_dup(&remote, _remote)) < 0) return error; memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_buf_cstr(&reflog_message))) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message)); cleanup: git_remote_free(remote); git_buf_free(&reflog_message); return error; }
static int create_and_configure_origin( git_remote **out, git_repository *repo, const char *url, const git_clone_options *options) { int error; git_remote *origin = NULL; char buf[GIT_PATH_MAX]; git_remote_create_cb remote_create = options->remote_cb; void *payload = options->remote_cb_payload; /* If the path exists and is a dir, the url should be the absolute path */ if (git_path_root(url) < 0 && git_path_exists(url) && git_path_isdir(url)) { if (p_realpath(url, buf) == NULL) return -1; url = buf; } if (!remote_create) { remote_create = default_remote_create; payload = NULL; } if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0) goto on_error; *out = origin; return 0; on_error: git_remote_free(origin); return error; }
void test_network_remote_defaultbranch__cleanup(void) { git_remote_free(g_remote); git_repository_free(g_repo_b); cl_git_sandbox_cleanup(); cl_fixture_cleanup("repo-b.git"); }
void do_update_repo(char *url, char *path) { git_repository *repo; git_remote *remote = NULL; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; const git_transfer_progress *stats; char textfield_final_string[MAXLINE]; memset(textfield_final_string, 0, sizeof(textfield_final_string)); int error = git_repository_open(&repo, path); if (error != 0) git_error_handling(); if (git_remote_lookup(&remote, repo, url) != 0) { error = git_remote_create_anonymous(&remote, repo, url); if (error != 0) git_error_handling(); } fetch_opts.callbacks.update_tips = &update_tips; fetch_opts.callbacks.sideband_progress = sideband_progress; fetch_opts.callbacks.transfer_progress = fetch_progress; error = git_remote_fetch(remote, NULL, &fetch_opts, "fetch"); if (error != 0) git_error_handling(); stats = git_remote_stats(remote); int receive_kbyte = stats->received_bytes / 1024; if (stats->local_objects > 0) { snprintf(textfield_final_string, sizeof(textfield_final_string), _("Fetched: (%d/%d) %d kB (used %d local objects)"), stats->indexed_objects, stats->total_objects, receive_kbyte, stats->local_objects); write_info_msg(textfield_final_string); } else { snprintf(textfield_final_string, sizeof(textfield_final_string), _("Fetched: (%d/%d) %d kB"), stats->indexed_objects, stats->total_objects, receive_kbyte); write_info_msg(textfield_final_string); } out: if (remote) git_remote_free(remote); if (repo) git_repository_free(repo); }
void test_network_remote_rename__cannot_rename_an_inmemory_remote(void) { git_remote *remote; cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "file:///blah")); cl_git_fail(git_remote_rename(remote, "newname", NULL, NULL)); git_remote_free(remote); }
void test_network_remote_remote__git_remote_create_with_fetchspec(void) { git_remote *remote; git_strarray array; cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); git_remote_get_fetch_refspecs(&array, remote); cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); git_remote_free(remote); }
void test_network_remote_delete__cannot_delete_an_anonymous_remote(void) { git_remote *remote; cl_git_pass(git_remote_create_anonymous(&remote, _repo, "git://github.com/libgit2/libgit2", NULL)); cl_git_fail(git_remote_delete(remote)); git_remote_free(remote); }
int sync_with_remote(git_repository *repo, const char *remote, const char *branch, enum remote_transport rt) { int error; git_remote *origin; char *proxy_string; git_config *conf; if (verbose) fprintf(stderr, "sync with remote %s[%s]\n", remote, branch); git_repository_config(&conf, repo); if (rt == RT_HTTPS && getProxyString(&proxy_string)) { git_config_set_string(conf, "http.proxy", proxy_string); free(proxy_string); } else { git_config_set_string(conf, "http.proxy", ""); } /* * NOTE! Remote errors are reported, but are nonfatal: * we still successfully return the local repository. */ error = git_remote_lookup(&origin, repo, "origin"); if (error) { report_error("Repository '%s' origin lookup failed (%s)", remote, giterr_last()->message); return 0; } if (rt == RT_HTTPS && !canReachCloudServer()) { // this is not an error, just a warning message, so return 0 report_error("Cannot connect to cloud server, working with local copy"); return 0; } #if USE_LIBGIT23_API git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; opts.callbacks.transfer_progress = &transfer_progress_cb; if (rt == RT_SSH) opts.callbacks.credentials = credential_ssh_cb; else if (rt == RT_HTTPS) opts.callbacks.credentials = credential_https_cb; opts.callbacks.certificate_check = certificate_check_cb; error = git_remote_fetch(origin, NULL, &opts, NULL); #else error = git_remote_fetch(origin, NULL, NULL, NULL); #endif // NOTE! A fetch error is not fatal, we just report it if (error) { report_error("Unable to fetch remote '%s'", remote); error = 0; } else { error = check_remote_status(repo, origin, branch, rt); } git_remote_free(origin); return error; }
/* * $ git remote add addtest http://github.com/libgit2/libgit2 * * $ cat .git/config * [...] * [remote "addtest"] * url = http://github.com/libgit2/libgit2 * fetch = +refs/heads/\*:refs/remotes/addtest/\* */ void test_network_remote_remotes__add(void) { git_remote_free(_remote); _remote = NULL; cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2")); cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); git_remote_free(_remote); _remote = NULL; cl_git_pass(git_remote_lookup(&_remote, _repo, "addtest")); cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); _refspec = git_vector_get(&_remote->refspecs, 0); cl_assert_equal_s("refs/heads/*", git_refspec_src(_refspec)); cl_assert(git_refspec_force(_refspec) == 1); cl_assert_equal_s("refs/remotes/addtest/*", git_refspec_dst(_refspec)); cl_assert_equal_s(git_remote_url(_remote), "http://github.com/libgit2/libgit2"); }
int git_branch_upstream__name( git_buf *tracking_name, git_repository *repo, const char *canonical_branch_name) { const char *remote_name, *merge_name; git_buf buf = GIT_BUF_INIT; int error = -1; git_remote *remote = NULL; const git_refspec *refspec; assert(tracking_name && canonical_branch_name); if (!git_reference__is_branch(canonical_branch_name)) return not_a_local_branch(canonical_branch_name); if ((error = retrieve_upstream_configuration( &remote_name, repo, canonical_branch_name, "branch.%s.remote")) < 0) goto cleanup; if ((error = retrieve_upstream_configuration( &merge_name, repo, canonical_branch_name, "branch.%s.merge")) < 0) goto cleanup; if (!*remote_name || !*merge_name) { giterr_set(GITERR_REFERENCE, "branch '%s' does not have an upstream", canonical_branch_name); error = GIT_ENOTFOUND; goto cleanup; } if (strcmp(".", remote_name) != 0) { if ((error = git_remote_load(&remote, repo, remote_name)) < 0) goto cleanup; refspec = git_remote__matching_refspec(remote, merge_name); if (!refspec) { error = GIT_ENOTFOUND; goto cleanup; } if (git_refspec_transform_r(&buf, refspec, merge_name) < 0) goto cleanup; } else if (git_buf_sets(&buf, merge_name) < 0) goto cleanup; error = git_buf_set(tracking_name, git_buf_cstr(&buf), git_buf_len(&buf)); cleanup: git_remote_free(remote); git_buf_free(&buf); return error; }
int git_clone( git_repository **out, const char *url, const char *local_path, const git_clone_options *_options) { int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; git_clone_options options = GIT_CLONE_OPTIONS_INIT; int remove_directory_on_failure = 0; assert(out && url && local_path); if (_options) memcpy(&options, _options, sizeof(git_clone_options)); GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", local_path); return GIT_ERROR; } /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); if ((retcode = git_repository_init(&repo, local_path, options.bare)) < 0) return retcode; if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0) goto cleanup; retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch); git_remote_free(origin); if (retcode < 0) goto cleanup; *out = repo; return 0; cleanup: git_repository_free(repo); if (remove_directory_on_failure) git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); else git_futils_cleanupdir_r(local_path); return retcode; }