diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/clone.c | 131 | ||||
| -rw-r--r-- | src/path.c | 2 | ||||
| -rw-r--r-- | src/remote.c | 166 | ||||
| -rw-r--r-- | src/repository.c | 3 |
4 files changed, 172 insertions, 130 deletions
diff --git a/src/clone.c b/src/clone.c index 865521bce..39c0ba26c 100644 --- a/src/clone.c +++ b/src/clone.c @@ -258,27 +258,71 @@ cleanup: * submodules? */ +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; + + if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) + goto on_error; + + git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb, + options->cred_acquire_payload); + git_remote_set_autotag(origin, options->remote_autotag); + /* + * Don't write FETCH_HEAD, we'll check out the remote tracking + * branch ourselves based on the server's default. + */ + git_remote_set_update_fetchhead(origin, 0); + + if (options->remote_callbacks && + (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) + goto on_error; + + if (options->fetch_spec && + (error = git_remote_set_fetchspec(origin, options->fetch_spec)) < 0) + goto on_error; + + if (options->push_spec && + (error = git_remote_set_pushspec(origin, options->push_spec)) < 0) + goto on_error; + + if (options->pushurl && + (error = git_remote_set_pushurl(origin, options->pushurl)) < 0) + goto on_error; + + if ((error = git_remote_save(origin)) < 0) + goto on_error; + + *out = origin; + return 0; + +on_error: + git_remote_free(origin); + return error; +} static int setup_remotes_and_fetch( git_repository *repo, - git_remote *origin, - git_transfer_progress_callback progress_cb, - void *progress_payload) + const char *url, + const git_clone_options *options) { int retcode = GIT_ERROR; + git_remote *origin; - /* Add the origin remote */ - if (!git_remote_set_repository(origin, repo) && !git_remote_save(origin)) { - /* - * Don't write FETCH_HEAD, we'll check out the remote tracking - * branch ourselves based on the server's default. - */ + /* Construct an origin remote */ + if (!create_and_configure_origin(&origin, repo, url, options)) { git_remote_set_update_fetchhead(origin, 0); /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIRECTION_FETCH)) { - if (!git_remote_download(origin, progress_cb, progress_payload)) { + if (!git_remote_download(origin, options->fetch_progress_cb, + options->fetch_progress_payload)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ @@ -318,62 +362,55 @@ static bool should_checkout( if (!opts) return false; + if (opts->checkout_strategy == GIT_CHECKOUT_DEFAULT) + return false; + return !git_repository_head_orphan(repo); } -static int clone_internal( +static void normalize_options(git_clone_options *dst, const git_clone_options *src) +{ + git_clone_options default_options = GIT_CLONE_OPTIONS_INIT; + if (!src) src = &default_options; + + *dst = *src; + + /* Provide defaults for null pointers */ + if (!dst->remote_name) dst->remote_name = "origin"; +} + +int git_clone( git_repository **out, - git_remote *origin_remote, - const char *path, - git_transfer_progress_callback fetch_progress_cb, - void *fetch_progress_payload, - git_checkout_opts *checkout_opts, - bool is_bare) + const char *url, + const char *local_path, + const git_clone_options *options) { int retcode = GIT_ERROR; git_repository *repo = NULL; + git_clone_options normOptions; + + assert(out && url && local_path); - if (!path_is_okay(path)) { + normalize_options(&normOptions, options); + GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); + + if (!path_is_okay(local_path)) { return GIT_ERROR; } - if (!(retcode = git_repository_init(&repo, path, is_bare))) { - if ((retcode = setup_remotes_and_fetch(repo, origin_remote, - fetch_progress_cb, fetch_progress_payload)) < 0) { + if (!(retcode = git_repository_init(&repo, local_path, normOptions.bare))) { + if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); - git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES); + git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); } else { *out = repo; retcode = 0; } } - if (!retcode && should_checkout(repo, is_bare, checkout_opts)) - retcode = git_checkout_head(*out, checkout_opts); + if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts)) + retcode = git_checkout_head(*out, &normOptions.checkout_opts); return retcode; } - -int git_clone( - git_repository **out, - git_remote *origin, - const char *local_path, - const git_clone_options *options) -{ - git_clone_options dummy_options = GIT_CLONE_OPTIONS_INIT; - - assert(out && origin && local_path); - if (!options) options = &dummy_options; - - GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); - - return clone_internal( - out, - origin, - local_path, - options->fetch_progress_cb, - options->fetch_progress_payload, - options->checkout_opts, - options->bare ? 1 : 0); -} diff --git a/src/path.c b/src/path.c index dd6bb70ad..1b1f554c7 100644 --- a/src/path.c +++ b/src/path.c @@ -19,6 +19,7 @@ #define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':') +#ifdef GIT_WIN32 static bool looks_like_network_computer_name(const char *path, int pos) { if (pos < 3) @@ -34,6 +35,7 @@ static bool looks_like_network_computer_name(const char *path, int pos) return true; } +#endif /* * Based on the Android implementation, BSD licensed. diff --git a/src/remote.c b/src/remote.c index 28ce88a93..29734cc1a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -83,14 +83,14 @@ cleanup: return error; } -int git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) +static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_remote *remote; git_buf fetchbuf = GIT_BUF_INIT; int error = -1; /* name is optional */ - assert(out && url); + assert(out && repo && url); remote = git__calloc(1, sizeof(git_remote)); GITERR_CHECK_ALLOC(remote); @@ -106,20 +106,8 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con GITERR_CHECK_ALLOC(remote->url); if (name != NULL) { - if ((error = ensure_remote_name_is_valid(name)) < 0) { - error = GIT_EINVALIDSPEC; - goto on_error; - } - remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); - - /* An empty name indicates to use a sensible default for the fetchspec. */ - if (fetch && !(*fetch)) { - if (git_buf_printf(&fetchbuf, "+refs/heads/*:refs/remotes/%s/*", remote->name) < 0) - goto on_error; - fetch = git_buf_cstr(&fetchbuf); - } } if (fetch != NULL) { @@ -142,6 +130,71 @@ on_error: return error; } +static int ensure_remote_doesnot_exist(git_repository *repo, const char *name) +{ + int error; + git_remote *remote; + + error = git_remote_load(&remote, repo, name); + + if (error == GIT_ENOTFOUND) + return 0; + + if (error < 0) + return error; + + git_remote_free(remote); + + giterr_set( + GITERR_CONFIG, + "Remote '%s' already exists.", name); + + return GIT_EEXISTS; +} + + +int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url) +{ + git_buf buf = GIT_BUF_INIT; + 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(out, repo, name, url, git_buf_cstr(&buf)) < 0) + goto on_error; + + git_buf_free(&buf); + + if (git_remote_save(*out) < 0) + goto on_error; + + return 0; + +on_error: + git_buf_free(&buf); + git_remote_free(*out); + return -1; +} + +int git_remote_create_inmemory(git_remote **out, git_repository *repo, const char *fetch, const char *url) +{ + int error; + git_remote *remote; + + if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0) + return error; + + *out = remote; + return 0; +} + int git_remote_set_repository(git_remote *remote, git_repository *repo) { assert(repo); @@ -312,9 +365,9 @@ int git_remote_save(const git_remote *remote) assert(remote); - if (!remote->repo) { - giterr_set(GITERR_INVALID, "Can't save a dangling remote."); - return GIT_ERROR; + if (!remote->name) { + giterr_set(GITERR_INVALID, "Can't save an in-memory remote."); + return GIT_EINVALIDSPEC; } if ((error = ensure_remote_name_is_valid(remote->name)) < 0) @@ -461,8 +514,7 @@ int git_remote_set_fetchspec(git_remote *remote, const char *spec) return -1; git_refspec__free(&remote->fetch); - remote->fetch.src = refspec.src; - remote->fetch.dst = refspec.dst; + memcpy(&remote->fetch, &refspec, sizeof(git_refspec)); return 0; } @@ -641,7 +693,7 @@ static int update_tips_callback(git_remote_head *head, void *payload) git_vector *refs = (git_vector *)payload; git_vector_insert(refs, head); - return 0; + return 0; } static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) @@ -652,11 +704,11 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda assert(update_heads && fetchspec_src); *out = NULL; - - git_vector_foreach(update_heads, i, remote_ref) { - if (strcmp(remote_ref->name, fetchspec_src) == 0) { - *out = remote_ref; - break; + + git_vector_foreach(update_heads, i, remote_ref) { + if (strcmp(remote_ref->name, fetchspec_src) == 0) { + *out = remote_ref; + break; } } @@ -727,7 +779,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_vector *update_hea } /* Create the FETCH_HEAD file */ - git_vector_foreach(update_heads, i, remote_ref) { + git_vector_foreach(update_heads, i, remote_ref) { int merge_this_fetchhead = (merge_remote_ref == remote_ref); if (!include_all_fetchheads && @@ -773,11 +825,6 @@ int git_remote_update_tips(git_remote *remote) assert(remote); - if (!remote->repo) { - giterr_set(GITERR_INVALID, "Can't update tips on a dangling remote."); - return GIT_ERROR; - } - spec = &remote->fetch; if (git_repository_odb__weakptr(&odb, remote->repo) < 0) @@ -788,7 +835,7 @@ int git_remote_update_tips(git_remote *remote) /* Make a copy of the transport's refs */ if (git_vector_init(&refs, 16, NULL) < 0 || - git_vector_init(&update_heads, 16, NULL) < 0) + git_vector_init(&update_heads, 16, NULL) < 0) return -1; if (git_remote_ls(remote, update_tips_callback, &refs) < 0) @@ -998,33 +1045,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) return 0; } -int git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url) -{ - git_buf buf = GIT_BUF_INIT; - int error; - - if ((error = ensure_remote_name_is_valid(name)) < 0) - return error; - - if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) - return -1; - - if (git_remote_new(out, repo, name, url, git_buf_cstr(&buf)) < 0) - goto on_error; - - git_buf_free(&buf); - - if (git_remote_save(*out) < 0) - goto on_error; - - return 0; - -on_error: - git_buf_free(&buf); - git_remote_free(*out); - return -1; -} - void git_remote_check_cert(git_remote *remote, int check) { assert(remote); @@ -1091,28 +1111,6 @@ void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t valu remote->download_tags = value; } -static int ensure_remote_doesnot_exist(git_repository *repo, const char *name) -{ - int error; - git_remote *remote; - - error = git_remote_load(&remote, repo, name); - - if (error == GIT_ENOTFOUND) - return 0; - - if (error < 0) - return error; - - git_remote_free(remote); - - giterr_set( - GITERR_CONFIG, - "Remote '%s' already exists.", name); - - return GIT_EEXISTS; -} - static int rename_remote_config_section( git_repository *repo, const char *old_name, @@ -1326,6 +1324,11 @@ int git_remote_rename( assert(remote && new_name); + if (!remote->name) { + giterr_set(GITERR_INVALID, "Can't rename an in-memory remote."); + return GIT_EINVALIDSPEC; + } + if ((error = ensure_remote_name_is_valid(new_name)) < 0) return error; @@ -1343,6 +1346,7 @@ int git_remote_rename( remote->name = git__strdup(new_name); + if (!remote->name) return 0; return git_remote_save(remote); } diff --git a/src/repository.c b/src/repository.c index 10ed12b64..33aaee841 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1140,8 +1140,7 @@ static int repo_init_create_origin(git_repository *repo, const char *url) int error; git_remote *remote; - if (!(error = git_remote_add(&remote, repo, GIT_REMOTE_ORIGIN, url))) { - error = git_remote_save(remote); + if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url))) { git_remote_free(remote); } |
