diff options
-rw-r--r-- | include/git2/push.h | 13 | ||||
-rw-r--r-- | include/git2/remote.h | 157 | ||||
-rw-r--r-- | src/clone.c | 19 | ||||
-rw-r--r-- | src/remote.c | 172 |
4 files changed, 128 insertions, 233 deletions
diff --git a/include/git2/push.h b/include/git2/push.h index ecabff397..77e4d0608 100644 --- a/include/git2/push.h +++ b/include/git2/push.h @@ -34,6 +34,19 @@ typedef struct { * to create. The default value is 1. */ unsigned int pb_parallelism; + /** + * The refspecs to use for this push. Leave empty to use the + * base refspecs. + */ + git_strarray refspecs; + /** + * Identity to use to update the reflog. + */ + git_signature *signature; + /** + * The message to insert into the reflogs. + */ + char *reflog_message; } git_push_options; #define GIT_PUSH_OPTIONS_VERSION 1 diff --git a/include/git2/remote.h b/include/git2/remote.h index 2bfc35f4b..abb892736 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -98,17 +98,6 @@ GIT_EXTERN(int) git_remote_create_anonymous( GIT_EXTERN(int) git_remote_lookup(git_remote **out, git_repository *repo, const char *name); /** - * Save a remote to its repository's configuration - * - * One can't save a in-memory remote. Doing so will - * result in a GIT_EINVALIDSPEC being returned. - * - * @param remote the remote to save to config - * @return 0, GIT_EINVALIDSPEC or an error code - */ -GIT_EXTERN(int) git_remote_save(const git_remote *remote); - -/** * Create a copy of an existing remote. All internal strings are also * duplicated. Callbacks are not duplicated. * @@ -317,7 +306,7 @@ GIT_EXTERN(int) git_remote_ls(const git_remote_head ***out, size_t *size, git_r * download. Use NULL or an empty array to use the base refspecs * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_strarray *refspecs); +GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_remote_callbacks *callbacks, const git_strarray *refspecs); /** * Create a packfile and send it to the server @@ -330,7 +319,7 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_strarray *refs * upload. Use NULL or an empty array to use the base refspecs * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts); +GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_remote_callbacks *callbacks, const git_push_options *opts); /** * Check whether the remote is connected @@ -396,24 +385,77 @@ GIT_EXTERN(int) git_remote_update_tips( GIT_EXTERN(int) git_remote_prune(git_remote *remote); /** + * Automatic tag following option + * + * Lets us select the --tags option to use. + */ +typedef enum { + GIT_REMOTE_DOWNLOAD_TAGS_AUTO = 0, + GIT_REMOTE_DOWNLOAD_TAGS_NONE = 1, + GIT_REMOTE_DOWNLOAD_TAGS_ALL = 2 +} git_remote_autotag_option_t; + +typedef struct { + unsigned int version; + /** + * Whether to update FETCH_HEAD setting. By default, + * FETCH_HEAD will be updated on every fetch. Set to 0 to + * disable. + */ + unsigned int update_fetchhead; + /** + * Set to true to prune stale references after fetching + */ + unsigned int prune; + /** + * The tag auto-follow setting + */ + git_remote_autotag_option_t autotag; + /** + * The refspecs to use for this fetch. Leave empty to use the + * base refspecs. + */ + git_strarray refspecs; + /** + * Identity to use to update the reflog. + */ + const git_signature *signature; + /** + * The message to insert into the reflogs. If NULL, the default is "fetch". + */ + const char *reflog_message; +} git_fetch_options; + +#define GIT_FETCH_OPTIONS_VERSION 1 +#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, 1 } + +/** + * Initializes a `git_fetch_options` with default values. Equivalent to + * creating an instance with GIT_FETCH_OPTIONS_INIT. + * + * @param opts the `git_fetch_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_FETCH_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_fetch_init_options( + git_fetch_options *opts, + unsigned int version); + +/** * Download new data and update tips * * Convenience function to connect to a remote, download the data, * disconnect and update the remote-tracking branches. * * @param remote the remote to fetch from - * @param refspecs the refspecs to use for this fetch. Pass NULL or an - * empty array to use the base refspecs. - * @param signature The identity to use when updating reflogs - * @param reflog_message The message to insert into the reflogs. If NULL, the - * default is "fetch" + * @param opts configuration to use for this fetch * @return 0 or an error code */ GIT_EXTERN(int) git_remote_fetch( - git_remote *remote, - const git_strarray *refspecs, - const git_signature *signature, - const char *reflog_message); + git_remote *remote, + const git_remote_callbacks *callbacks, + const git_fetch_options *opts); /** * Perform a push @@ -421,16 +463,12 @@ GIT_EXTERN(int) git_remote_fetch( * Peform all the steps from a push. * * @param remote the remote to push to - * @param refspecs the refspecs to use for pushing. If none are - * passed, the configured refspecs will be used - * @param opts the options - * @param signature signature to use for the reflog of updated references - * @param reflog_message message to use for the reflog of upated references + * @param opts the options to use for this push */ -GIT_EXTERN(int) git_remote_push(git_remote *remote, - const git_strarray *refspecs, - const git_push_options *opts, - const git_signature *signature, const char *reflog_message); +GIT_EXTERN(int) git_remote_push( + git_remote *remote, + const git_remote_callbacks *callbacks, + const git_push_options *opts); /** * Get a list of the configured remotes for a repo @@ -549,45 +587,11 @@ GIT_EXTERN(int) git_remote_init_callbacks( unsigned int version); /** - * Set the callbacks for a remote - * - * Note that the remote keeps its own copy of the data and you need to - * call this function again if you want to change the callbacks. - * - * @param remote the remote to configure - * @param callbacks a pointer to the user's callback settings - * @return 0 or an error code - */ -GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); - -/** - * Retrieve the current callback structure - * - * This provides read access to the callbacks structure as the remote - * sees it. - * - * @param remote the remote to query - * @return a pointer to the callbacks structure - */ -GIT_EXTERN(const git_remote_callbacks *) git_remote_get_callbacks(git_remote *remote); - -/** * Get the statistics structure that is filled in by the fetch operation. */ GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); /** - * Automatic tag following option - * - * Lets us select the --tags option to use. - */ -typedef enum { - GIT_REMOTE_DOWNLOAD_TAGS_AUTO = 0, - GIT_REMOTE_DOWNLOAD_TAGS_NONE = 1, - GIT_REMOTE_DOWNLOAD_TAGS_ALL = 2 -} git_remote_autotag_option_t; - -/** * Retrieve the tag auto-follow setting * * @param remote the remote to query @@ -596,16 +600,6 @@ typedef enum { GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *remote); /** - * Set the tag auto-follow setting - * - * @param remote the remote to configure - * @param value a GIT_REMOTE_DOWNLOAD_TAGS value - */ -GIT_EXTERN(void) git_remote_set_autotag( - git_remote *remote, - git_remote_autotag_option_t value); - -/** * Retrieve the ref-prune setting * * @param remote the remote to query @@ -624,7 +618,7 @@ GIT_EXTERN(int) git_remote_prune_refs(const git_remote *remote); * * No loaded instances of a the remote with the old name will change * their name or their list of refspecs. - * + *a * @param problems non-default refspecs cannot be renamed and will be * stored here for further processing by the caller. Always free this * strarray on successful return. @@ -646,16 +640,7 @@ GIT_EXTERN(int) git_remote_rename( * @return the update FETCH_HEAD setting */ GIT_EXTERN(int) git_remote_update_fetchhead(git_remote *remote); - -/** - * Sets the update FETCH_HEAD setting. By default, FETCH_HEAD will be - * updated on every fetch. Set to 0 to disable. - * - * @param remote the remote to configure - * @param value 0 to disable updating FETCH_HEAD - */ -GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value); - + /** * Ensure the remote name is well-formed. * diff --git a/src/clone.c b/src/clone.c index f18f07611..651e9e1f5 100644 --- a/src/clone.c +++ b/src/clone.c @@ -250,7 +250,7 @@ static int default_remote_create( if ((error = git_remote_create(out, repo, name, url)) < 0) return error; - return git_remote_set_callbacks(*out, callbacks); + return 0; } /* @@ -335,6 +335,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_check int error; git_buf reflog_message = GIT_BUF_INIT; git_remote *remote; + git_fetch_options fetch_options = GIT_FETCH_OPTIONS_INIT; const git_remote_callbacks *callbacks; assert(repo && _remote); @@ -347,18 +348,15 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_check if ((error = git_remote_dup(&remote, _remote)) < 0) return error; - callbacks = git_remote_get_callbacks(_remote); - if (!giterr__check_version(callbacks, 1, "git_remote_callbacks") && - (error = git_remote_set_callbacks(remote, callbacks)) < 0) - goto cleanup; - if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) goto cleanup; - git_remote_set_update_fetchhead(remote, 0); git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); - if ((error = git_remote_fetch(remote, NULL, signature, git_buf_cstr(&reflog_message))) != 0) + fetch_options.signature = signature; + fetch_options.reflog_message = git_buf_cstr(&reflog_message); + fetch_options.update_fetchhead = 0; + if ((error = git_remote_fetch(remote, &_remote->callbacks, &fetch_options)) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message)); @@ -512,6 +510,7 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_ { int error, flags; git_repository *src; + git_fetch_options fetch_options = GIT_FETCH_OPTIONS_INIT; git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT; git_buf reflog_message = GIT_BUF_INIT; @@ -553,7 +552,9 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_ git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); - if ((error = git_remote_fetch(remote, NULL, signature, git_buf_cstr(&reflog_message))) != 0) + fetch_options.signature = signature; + fetch_options.reflog_message = git_buf_cstr(&reflog_message); + if ((error = git_remote_fetch(remote, NULL, &fetch_options)) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message)); diff --git a/src/remote.c b/src/remote.c index 5ba7735ae..d815d9120 100644 --- a/src/remote.c +++ b/src/remote.c @@ -29,7 +29,7 @@ static int add_refspec_to(git_vector *vector, const char *string, bool is_fetch) spec = git__calloc(1, sizeof(git_refspec)); GITERR_CHECK_ALLOC(spec); - + if (git_refspec__parse(spec, string, is_fetch) < 0) { git__free(spec); return -1; @@ -139,8 +139,8 @@ static int canonicalize_url(git_buf *out, const char *in) static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_remote *remote; - git_config *config = NULL; - git_buf canonical_url = GIT_BUF_INIT, fetchbuf = GIT_BUF_INIT; + git_config *config = NULL, *cfg = NULL; + git_buf canonical_url = GIT_BUF_INIT, fetchbuf = GIT_BUF_INIT, buf = GIT_BUF_INIT; int error = -1; /* name is optional */ @@ -163,6 +163,22 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n GITERR_CHECK_ALLOC(remote->name); } + if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) + goto on_error; + + if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0) + goto on_error; + + if ((error = git_config_set_string(cfg, git_buf_cstr(&buf), url)) < 0) + goto on_error; + + git_buf_clear(&buf); + if ((error = git_buf_printf(&buf, "remote.%s.fetch", name)) < 0) + goto on_error; + + if ((error = git_config_set_string(cfg, git_buf_cstr(&buf), fetch)) < 0) + goto on_error; + if (fetch != NULL) { if (add_refspec(remote, fetch, true) < 0) goto on_error; @@ -190,8 +206,10 @@ on_error: git_remote_free(remote); git_config_free(config); + git_config_free(cfg); git_buf_free(&fetchbuf); git_buf_free(&canonical_url); + git_buf_free(&buf); return error; } @@ -246,9 +264,6 @@ int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, con 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; @@ -543,86 +558,6 @@ cleanup: return error; } -int git_remote_save(const git_remote *remote) -{ - int error; - git_config *cfg; - const char *tagopt = NULL; - git_buf buf = GIT_BUF_INIT; - const git_config_entry *existing; - - assert(remote); - - if (!remote->name) { - giterr_set(GITERR_INVALID, "Can't save an anonymous remote."); - return GIT_EINVALIDSPEC; - } - - if ((error = ensure_remote_name_is_valid(remote->name)) < 0) - return error; - - if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) - return error; - - if ((error = git_buf_printf(&buf, "remote.%s.url", remote->name)) < 0) - return error; - - /* after this point, buffer is allocated so end with cleanup */ - - if ((error = git_config_set_string( - cfg, git_buf_cstr(&buf), remote->url)) < 0) - goto cleanup; - - git_buf_clear(&buf); - if ((error = git_buf_printf(&buf, "remote.%s.pushurl", remote->name)) < 0) - goto cleanup; - - if ((error = git_config__update_entry( - cfg, git_buf_cstr(&buf), remote->pushurl, true, false)) < 0) - goto cleanup; - - if ((error = update_config_refspec(remote, cfg, GIT_DIRECTION_FETCH)) < 0) - goto cleanup; - - if ((error = update_config_refspec(remote, cfg, GIT_DIRECTION_PUSH)) < 0) - goto cleanup; - - /* - * What action to take depends on the old and new values. This - * is describes by the table below. tagopt means whether the - * is already a value set in the config - * - * AUTO ALL or NONE - * +-----------------------+ - * tagopt | remove | set | - * +---------+-------------| - * !tagopt | nothing | set | - * +---------+-------------+ - */ - - git_buf_clear(&buf); - if ((error = git_buf_printf(&buf, "remote.%s.tagopt", remote->name)) < 0) - goto cleanup; - - if ((error = git_config__lookup_entry( - &existing, cfg, git_buf_cstr(&buf), false)) < 0) - goto cleanup; - - if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) - tagopt = "--tags"; - else if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_NONE) - tagopt = "--no-tags"; - else if (existing != NULL) - tagopt = NULL; - - error = git_config__update_entry( - cfg, git_buf_cstr(&buf), tagopt, true, false); - -cleanup: - git_buf_free(&buf); - return error; -} - const char *git_remote_name(const git_remote *remote) { assert(remote); @@ -641,38 +576,12 @@ const char *git_remote_url(const git_remote *remote) return remote->url; } -int git_remote_set_url(git_remote *remote, const char* url) -{ - assert(remote); - assert(url); - - git__free(remote->url); - remote->url = git__strdup(url); - GITERR_CHECK_ALLOC(remote->url); - - return 0; -} - const char *git_remote_pushurl(const git_remote *remote) { assert(remote); return remote->pushurl; } -int git_remote_set_pushurl(git_remote *remote, const char* url) -{ - assert(remote); - - git__free(remote->pushurl); - if (url) { - remote->pushurl = git__strdup(url); - GITERR_CHECK_ALLOC(remote->pushurl); - } else { - remote->pushurl = NULL; - } - return 0; -} - const char* git_remote__urlfordirection(git_remote *remote, int direction) { assert(remote); @@ -864,7 +773,7 @@ static int ls_to_vector(git_vector *out, git_remote *remote) return 0; } -int git_remote_download(git_remote *remote, const git_strarray *refspecs) +int git_remote_download(git_remote *remote, const git_remote_callbacks *callbacks, const git_strarray *refspecs) { int error = -1; size_t i; @@ -924,9 +833,8 @@ on_error: int git_remote_fetch( git_remote *remote, - const git_strarray *refspecs, - const git_signature *signature, - const char *reflog_message) + const git_remote_callbacks *callbacks, + const git_fetch_options *opts) { int error; git_buf reflog_msg_buf = GIT_BUF_INIT; @@ -935,7 +843,7 @@ int git_remote_fetch( if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0) return error; - error = git_remote_download(remote, refspecs); + error = git_remote_download(remote, callbacks, &opts->refspecs); /* We don't need to be connected anymore */ git_remote_disconnect(remote); @@ -945,15 +853,15 @@ int git_remote_fetch( return error; /* Default reflog message */ - if (reflog_message) - git_buf_sets(&reflog_msg_buf, reflog_message); + if (opts->reflog_message) + git_buf_sets(&reflog_msg_buf, opts->reflog_message); else { git_buf_printf(&reflog_msg_buf, "fetch %s", remote->name ? remote->name : remote->url); } /* Create "remote/foo" branches for all remote branches */ - error = git_remote_update_tips(remote, signature, git_buf_cstr(&reflog_msg_buf)); + error = git_remote_update_tips(remote, opts->signature, git_buf_cstr(&reflog_msg_buf)); git_buf_free(&reflog_msg_buf); if (error < 0) return error; @@ -1619,13 +1527,6 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal return 0; } -const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote) -{ - assert(remote); - - return &remote->callbacks; -} - int git_remote_set_transport( git_remote *remote, git_transport_cb transport_cb, @@ -1654,11 +1555,6 @@ git_remote_autotag_option_t git_remote_autotag(const git_remote *remote) return remote->download_tags; } -void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t value) -{ - remote->download_tags = value; -} - int git_remote_prune_refs(const git_remote *remote) { return remote->prune_refs; @@ -2316,12 +2212,13 @@ int git_remote_default_branch(git_buf *out, git_remote *remote) return git_buf_puts(out, guess->name); } -int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts) +int git_remote_upload(git_remote *remote, const git_remote_callbacks *callbacks, const git_push_options *opts) { size_t i; int error; git_push *push; git_refspec *spec; + const git_strarray *refspecs = &opts->refspecs; git_remote_callbacks *cbs; assert(remote); @@ -2374,20 +2271,19 @@ cleanup: return error; } -int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts, - const git_signature *signature, const char *reflog_message) +int git_remote_push(git_remote *remote, const git_remote_callbacks *callbacks, const git_push_options *opts) { int error; - assert(remote && refspecs); + assert(remote); if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0) return error; - if ((error = git_remote_upload(remote, refspecs, opts)) < 0) + if ((error = git_remote_upload(remote, callbacks, opts)) < 0) return error; - error = git_remote_update_tips(remote, signature, reflog_message); + error = git_remote_update_tips(remote, opts->signature, opts->reflog_message); git_remote_disconnect(remote); return error; |