From 05259114427234831cf4915cbe40a5bb8ea021b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 21 Apr 2015 20:16:48 +0200 Subject: [PATCH 01/13] push: remove own copy of callbacks The push object knows which remote it's associated with, and therefore does not need to keep its own copy of the callbacks stored in the remote. Remove the copy and simply access the callbacks struct within the remote. --- src/push.c | 36 ++++++--------------------------- src/push.h | 32 ----------------------------- src/remote.c | 8 +------- src/transports/smart_protocol.c | 13 ++++++------ 4 files changed, 14 insertions(+), 75 deletions(-) diff --git a/src/push.c b/src/push.c index 3ac6fbf63..a4b61cd35 100644 --- a/src/push.c +++ b/src/push.c @@ -77,30 +77,6 @@ int git_push_set_options(git_push *push, const git_push_options *opts) return 0; } -int git_push_set_callbacks( - git_push *push, - git_packbuilder_progress pack_progress_cb, - void *pack_progress_cb_payload, - git_push_transfer_progress transfer_progress_cb, - void *transfer_progress_cb_payload, - git_push_negotiation negotiation_cb, - void *negotiation_cb_payload) -{ - if (!push) - return -1; - - push->pack_progress_cb = pack_progress_cb; - push->pack_progress_cb_payload = pack_progress_cb_payload; - - push->transfer_progress_cb = transfer_progress_cb; - push->transfer_progress_cb_payload = transfer_progress_cb_payload; - - push->negotiation_cb = negotiation_cb; - push->negotiation_cb_payload = negotiation_cb_payload; - - return 0; -} - static void free_refspec(push_spec *spec) { if (spec == NULL) @@ -599,6 +575,7 @@ static int do_push(git_push *push) { int error = 0; git_transport *transport = push->remote->transport; + git_remote_callbacks *cbs = &push->remote->callbacks; if (!transport->push) { giterr_set(GITERR_NET, "Remote transport doesn't support push"); @@ -617,17 +594,16 @@ static int do_push(git_push *push) git_packbuilder_set_threads(push->pb, push->pb_parallelism); - if (push->pack_progress_cb) - if ((error = git_packbuilder_set_callbacks(push->pb, push->pack_progress_cb, push->pack_progress_cb_payload)) < 0) + if (cbs->pack_progress) + if ((error = git_packbuilder_set_callbacks(push->pb, cbs->pack_progress, cbs->payload)) < 0) goto on_error; if ((error = calculate_work(push)) < 0) goto on_error; - if (push->negotiation_cb && - (error = push->negotiation_cb((const git_push_update **) push->updates.contents, - push->updates.length, - push->negotiation_cb_payload))) + if (cbs->push_negotiation && + (error = cbs->push_negotiation((const git_push_update **) push->updates.contents, + push->updates.length, cbs->payload)) < 0) goto on_error; if ((error = queue_objects(push)) < 0 || diff --git a/src/push.h b/src/push.h index fb5f01480..fcba45c8e 100644 --- a/src/push.h +++ b/src/push.h @@ -38,13 +38,6 @@ struct git_push { /* options */ unsigned pb_parallelism; - - git_packbuilder_progress pack_progress_cb; - void *pack_progress_cb_payload; - git_push_transfer_progress transfer_progress_cb; - void *transfer_progress_cb_payload; - git_push_negotiation negotiation_cb; - void *negotiation_cb_payload; }; /** @@ -76,31 +69,6 @@ int git_push_set_options( git_push *push, const git_push_options *opts); -/** - * Set the callbacks for a push - * - * @param push The push object - * @param pack_progress_cb Function to call with progress information during - * pack building. Be aware that this is called inline with pack building - * operations, so performance may be affected. - * @param pack_progress_cb_payload Payload for the pack progress callback. - * @param transfer_progress_cb Function to call with progress information during - * the upload portion of a push. Be aware that this is called inline with - * pack building operations, so performance may be affected. - * @param transfer_progress_cb_payload Payload for the network progress callback. - * @param push_negotiation_cb Function to call before sending the commands to the remote. - * @param push_negotiation_cb_payload Payload for the negotiation callback - * @return 0 or an error code - */ -int git_push_set_callbacks( - git_push *push, - git_packbuilder_progress pack_progress_cb, - void *pack_progress_cb_payload, - git_push_transfer_progress transfer_progress_cb, - void *transfer_progress_cb_payload, - git_push_negotiation negotiation_cb, - void *negotiation_cb_payload); - /** * Add a refspec to be pushed * diff --git a/src/remote.c b/src/remote.c index 5257e85f3..91ebdd53c 100644 --- a/src/remote.c +++ b/src/remote.c @@ -2360,16 +2360,10 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi } } - cbs = &remote->callbacks; - if ((error = git_push_set_callbacks(push, - cbs->pack_progress, cbs->payload, - cbs->push_transfer_progress, cbs->payload, - cbs->push_negotiation, cbs->payload)) < 0) - goto cleanup; - if ((error = git_push_finish(push)) < 0) goto cleanup; + cbs = &remote->callbacks; if (cbs->push_update_reference && (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0) goto cleanup; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index f023db4df..9e7b0a72b 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -950,6 +950,7 @@ int git_smart__push(git_transport *transport, git_push *push) { transport_smart *t = (transport_smart *)transport; struct push_packbuilder_payload packbuilder_payload = {0}; + git_remote_callbacks *cbs = &push->remote->callbacks; git_buf pktline = GIT_BUF_INIT; int error = 0, need_pack = 0; push_spec *spec; @@ -957,9 +958,9 @@ int git_smart__push(git_transport *transport, git_push *push) packbuilder_payload.pb = push->pb; - if (push->transfer_progress_cb) { - packbuilder_payload.cb = push->transfer_progress_cb; - packbuilder_payload.cb_payload = push->transfer_progress_cb_payload; + if (cbs->transfer_progress) { + packbuilder_payload.cb = cbs->push_transfer_progress; + packbuilder_payload.cb_payload = cbs->payload; } #ifdef PUSH_DEBUG @@ -1010,12 +1011,12 @@ int git_smart__push(git_transport *transport, git_push *push) goto done; /* If progress is being reported write the final report */ - if (push->transfer_progress_cb) { - error = push->transfer_progress_cb( + if (cbs->push_transfer_progress) { + error = cbs->push_transfer_progress( push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, - push->transfer_progress_cb_payload); + cbs->payload); if (error < 0) goto done; From 8f0104ecc54db00a075310ab744a19eb60e3d740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 21 Apr 2015 22:10:36 +0200 Subject: [PATCH 02/13] Remove the callbacks struct from the remote Having the setting be different from calling its actions was not a great idea and made for the sake of the wrong convenience. Instead of that, accept either fetch options, push options or the callbacks when dealing with the remote. The fetch options are currently only the callbacks, but more options will be moved from setters and getters on the remote to the options. This does mean passing the same struct along the different functions but the typical use-case will only call git_remote_fetch() or git_remote_push() and so won't notice much difference. --- include/git2.h | 1 - include/git2/clone.h | 13 +- include/git2/push.h | 94 --------- include/git2/remote.h | 293 +++++++++++++++++---------- include/git2/submodule.h | 8 +- include/git2/sys/transport.h | 2 +- src/clone.c | 30 +-- src/fetch.c | 19 +- src/fetch.h | 2 +- src/push.c | 29 ++- src/push.h | 4 +- src/remote.c | 123 ++++++----- src/remote.h | 1 - src/submodule.c | 2 +- src/transports/local.c | 8 +- src/transports/smart.h | 2 +- src/transports/smart_protocol.c | 7 +- tests/checkout/index.c | 4 +- tests/clone/empty.c | 4 +- tests/clone/nonetwork.c | 6 +- tests/fetchhead/nonetwork.c | 2 +- tests/network/fetchlocal.c | 117 ++++------- tests/network/remote/defaultbranch.c | 6 +- tests/network/remote/local.c | 47 ++--- tests/network/remote/remotes.c | 10 +- tests/online/clone.c | 61 +++--- tests/online/fetch.c | 54 +++-- tests/online/fetchhead.c | 9 +- tests/online/push.c | 20 +- tests/submodule/update.c | 4 +- 30 files changed, 465 insertions(+), 517 deletions(-) delete mode 100644 include/git2/push.h diff --git a/include/git2.h b/include/git2.h index cf6b5cb89..a1e78376f 100644 --- a/include/git2.h +++ b/include/git2.h @@ -40,7 +40,6 @@ #include "git2/pack.h" #include "git2/patch.h" #include "git2/pathspec.h" -#include "git2/push.h" #include "git2/rebase.h" #include "git2/refdb.h" #include "git2/reflog.h" diff --git a/include/git2/clone.h b/include/git2/clone.h index d3bd42485..9e23aaccb 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -111,13 +111,12 @@ typedef struct git_clone_options { git_checkout_options checkout_opts; /** - * Callbacks to use for reporting fetch progress, and for acquiring - * credentials in the event they are needed. This parameter is ignored if - * the remote_cb parameter is set; if you provide a remote creation - * callback, then you have the opportunity to configure remote callbacks in - * provided function. + * Options which control the fetch, including callbacks. + * + * The callbacks are used for reporting fetch progress, and for acquiring + * credentials in the event they are needed. */ - git_remote_callbacks remote_callbacks; + git_fetch_options fetch_opts; /** * Set to zero (false) to create a standard repo, or non-zero @@ -167,7 +166,7 @@ typedef struct git_clone_options { #define GIT_CLONE_OPTIONS_VERSION 1 #define GIT_CLONE_OPTIONS_INIT { GIT_CLONE_OPTIONS_VERSION, \ { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \ - GIT_REMOTE_CALLBACKS_INIT } + GIT_FETCH_OPTIONS_INIT } /** * Initializes a `git_clone_options` with default values. Equivalent to diff --git a/include/git2/push.h b/include/git2/push.h deleted file mode 100644 index 3f850453d..000000000 --- a/include/git2/push.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) the libgit2 contributors. All rights reserved. - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#ifndef INCLUDE_git_push_h__ -#define INCLUDE_git_push_h__ - -#include "common.h" -#include "pack.h" - -/** - * @file git2/push.h - * @brief Git push management functions - * @defgroup git_push push management functions - * @ingroup Git - * @{ - */ -GIT_BEGIN_DECL - -/** - * Controls the behavior of a git_push object. - */ -typedef struct { - unsigned int version; - - /** - * If the transport being used to push to the remote requires the creation - * of a pack file, this controls the number of worker threads used by - * the packbuilder when creating that pack file to be sent to the remote. - * - * If set to 0, the packbuilder will auto-detect the number of threads - * to create. The default value is 1. - */ - unsigned int pb_parallelism; -} git_push_options; - -#define GIT_PUSH_OPTIONS_VERSION 1 -#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION } - -/** - * Initializes a `git_push_options` with default values. Equivalent to - * creating an instance with GIT_PUSH_OPTIONS_INIT. - * - * @param opts the `git_push_options` instance to initialize. - * @param version the version of the struct; you should pass - * `GIT_PUSH_OPTIONS_VERSION` here. - * @return Zero on success; -1 on failure. - */ -GIT_EXTERN(int) git_push_init_options( - git_push_options *opts, - unsigned int version); - -/** Push network progress notification function */ -typedef int (*git_push_transfer_progress)( - unsigned int current, - unsigned int total, - size_t bytes, - void* payload); - -/** - * Represents an update which will be performed on the remote during push - */ -typedef struct { - /** - * The source name of the reference - */ - char *src_refname; - /** - * The name of the reference to update on the server - */ - char *dst_refname; - /** - * The current target of the reference - */ - git_oid src; - /** - * The new target for the reference - */ - git_oid dst; -} git_push_update; - -/** - * @param updates an array containing the updates which will be sent - * as commands to the destination. - * @param len number of elements in `updates` - * @param payload Payload provided by the caller - */ -typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload); - -/** @} */ -GIT_END_DECL -#endif diff --git a/include/git2/remote.h b/include/git2/remote.h index 6e88a4680..5aea777c1 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -14,7 +14,7 @@ #include "indexer.h" #include "strarray.h" #include "transport.h" -#include "push.h" +#include "pack.h" /** * @file git2/remote.h @@ -276,9 +276,10 @@ GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote, * @param remote the remote to connect to * @param direction GIT_DIRECTION_FETCH if you want to fetch or * GIT_DIRECTION_PUSH if you want to push + * @param callbacks the callbacks to use for this connection * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction); +GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks); /** * Get the remote repository's reference advertisement list @@ -302,36 +303,6 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction); */ GIT_EXTERN(int) git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote); -/** - * Download and index the packfile - * - * Connect to the remote if it hasn't been done yet, negotiate with - * the remote git which objects are missing, download and index the - * packfile. - * - * The .idx file will be created and both it and the packfile with be - * renamed to their final name. - * - * @param remote the remote - * @param refspecs the refspecs to use for this negotiation and - * 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); - -/** - * Create a packfile and send it to the server - * - * Connect to the remote if it hasn't been done yet, negotiate with - * the remote git which objects are missing, create a packfile with the missing objects and send it. - * - * @param remote the remote - * @param refspecs the refspecs to use for this negotiation and - * 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); - /** * Check whether the remote is connected * @@ -372,60 +343,6 @@ GIT_EXTERN(void) git_remote_disconnect(git_remote *remote); */ GIT_EXTERN(void) git_remote_free(git_remote *remote); -/** - * Update the tips to the new state - * - * @param remote the remote to update - * @param reflog_message The message to insert into the reflogs. If - * NULL and fetching, the default is "fetch ", where is - * the name of the remote (or its url, for in-memory remotes). This - * parameter is ignored when pushing. - * @return 0 or an error code - */ -GIT_EXTERN(int) git_remote_update_tips( - git_remote *remote, - const char *reflog_message); - -/** - * Prune tracking refs that are no longer present on remote - * - * @param remote the remote to prune - * @return 0 or an error code - */ -GIT_EXTERN(int) git_remote_prune(git_remote *remote); - -/** - * 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 reflog_message The message to insert into the reflogs. If NULL, the - * default is "fetch" - * @return 0 or an error code - */ -GIT_EXTERN(int) git_remote_fetch( - git_remote *remote, - const git_strarray *refspecs, - const char *reflog_message); - -/** - * Perform a push - * - * 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 - */ -GIT_EXTERN(int) git_remote_push(git_remote *remote, - const git_strarray *refspecs, - const git_push_options *opts); - /** * Get a list of the configured remotes for a repo * @@ -447,6 +364,42 @@ typedef enum git_remote_completion_type { GIT_REMOTE_COMPLETION_ERROR, } git_remote_completion_type; +/** Push network progress notification function */ +typedef int (*git_push_transfer_progress)( + unsigned int current, + unsigned int total, + size_t bytes, + void* payload); +/** + * Represents an update which will be performed on the remote during push + */ +typedef struct { + /** + * The source name of the reference + */ + char *src_refname; + /** + * The name of the reference to update on the server + */ + char *dst_refname; + /** + * The current target of the reference + */ + git_oid src; + /** + * The new target for the reference + */ + git_oid dst; +} git_push_update; + +/** + * @param updates an array containing the updates which will be sent + * as commands to the destination. + * @param len number of elements in `updates` + * @param payload Payload provided by the caller + */ +typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload); + /** * The callback settings structure * @@ -548,28 +501,160 @@ GIT_EXTERN(int) git_remote_init_callbacks( git_remote_callbacks *opts, 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); +typedef struct { + int version; + + /** + * Callbacks to use for this fetch operation + */ + git_remote_callbacks callbacks; +} git_fetch_options; + +#define GIT_FETCH_OPTIONS_VERSION 1 +#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT } /** - * Retrieve the current callback structure + * Initializes a `git_fetch_options` with default values. Equivalent to + * creating an instance with GIT_FETCH_OPTIONS_INIT. * - * 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 + * @param opts the `git_push_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(const git_remote_callbacks *) git_remote_get_callbacks(git_remote *remote); +GIT_EXTERN(int) git_fetch_init_options( + git_fetch_options *opts, + unsigned int version); + + +/** + * Controls the behavior of a git_push object. + */ +typedef struct { + unsigned int version; + + /** + * If the transport being used to push to the remote requires the creation + * of a pack file, this controls the number of worker threads used by + * the packbuilder when creating that pack file to be sent to the remote. + * + * If set to 0, the packbuilder will auto-detect the number of threads + * to create. The default value is 1. + */ + unsigned int pb_parallelism; + + /** + * Callbacks to use for this push operation + */ + git_remote_callbacks callbacks; +} git_push_options; + +#define GIT_PUSH_OPTIONS_VERSION 1 +#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION, 0, GIT_REMOTE_CALLBACKS_INIT } + +/** + * Initializes a `git_push_options` with default values. Equivalent to + * creating an instance with GIT_PUSH_OPTIONS_INIT. + * + * @param opts the `git_push_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_PUSH_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_push_init_options( + git_push_options *opts, + unsigned int version); + +/** + * Download and index the packfile + * + * Connect to the remote if it hasn't been done yet, negotiate with + * the remote git which objects are missing, download and index the + * packfile. + * + * The .idx file will be created and both it and the packfile with be + * renamed to their final name. + * + * @param remote the remote + * @param refspecs the refspecs to use for this negotiation and + * download. Use NULL or an empty array to use the base refspecs + * @param opts the options to use for this fetch + * @return 0 or an error code + */ + GIT_EXTERN(int) git_remote_download(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts); + +/** + * Create a packfile and send it to the server + * + * Connect to the remote if it hasn't been done yet, negotiate with + * the remote git which objects are missing, create a packfile with the missing objects and send it. + * + * @param remote the remote + * @param refspecs the refspecs to use for this negotiation and + * upload. Use NULL or an empty array to use the base refspecs + * @param opts the options to use for this push + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts); + +/** + * Update the tips to the new state + * + * @param remote the remote to update + * @param reflog_message The message to insert into the reflogs. If + * NULL and fetching, the default is "fetch ", where is + * the name of the remote (or its url, for in-memory remotes). This + * parameter is ignored when pushing. + * @param callbacks pointer to the callback structure to use + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_update_tips( + git_remote *remote, + const git_remote_callbacks *callbacks, + const char *reflog_message); + +/** + * 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 opts options to use for this fetch + * @param reflog_message The message to insert into the reflogs. If NULL, the + * default is "fetch" + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_fetch( + git_remote *remote, + const git_strarray *refspecs, + const git_fetch_options *opts, + const char *reflog_message); + +/** + * Prune tracking refs that are no longer present on remote + * + * @param remote the remote to prune + * @param callbacks callbacks to use for this prune + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks); + +/** + * Perform a push + * + * 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 options to use for this push + */ +GIT_EXTERN(int) git_remote_push(git_remote *remote, + const git_strarray *refspecs, + const git_push_options *opts); /** * Get the statistics structure that is filled in by the fetch operation. diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 86f5fef22..48faf8a49 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -130,10 +130,12 @@ typedef struct git_submodule_update_options { git_checkout_options checkout_opts; /** - * Callbacks to use for reporting fetch progress, and for acquiring + * Options which control the fetch, including callbacks. + * + * The callbacks to use for reporting fetch progress, and for acquiring * credentials in the event they are needed. */ - git_remote_callbacks remote_callbacks; + git_fetch_options fetch_opts; /** * The checkout strategy to use when the sub repository needs to @@ -147,7 +149,7 @@ typedef struct git_submodule_update_options { #define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \ { GIT_CHECKOUT_OPTIONS_VERSION, \ { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \ - GIT_REMOTE_CALLBACKS_INIT, GIT_CHECKOUT_SAFE } + GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE } /** * Initializes a `git_submodule_update_options` with default values. diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index 2cb1a97eb..d6ca8ff05 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -61,7 +61,7 @@ struct git_transport { git_transport *transport); /* Executes the push whose context is in the git_push object. */ - int (*push)(git_transport *transport, git_push *push); + int (*push)(git_transport *transport, git_push *push, const git_remote_callbacks *callbacks); /* This function may be called after a successful call to connect(), when * the direction is FETCH. The function performs a negotiation to calculate diff --git a/src/clone.c b/src/clone.c index 7e5d3302e..53cdae673 100644 --- a/src/clone.c +++ b/src/clone.c @@ -24,7 +24,7 @@ #include "repository.h" #include "odb.h" -static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link); +static int clone_local_into(git_repository *repo, git_remote *remote, const git_fetch_options *fetch_opts, const git_checkout_options *co_opts, const char *branch, int link); static int create_branch( git_reference **branch, @@ -242,13 +242,9 @@ static int default_remote_create( const char *url, void *payload) { - int error; - git_remote_callbacks *callbacks = payload; + GIT_UNUSED(payload); - if ((error = git_remote_create(out, repo, name, url)) < 0) - return error; - - return git_remote_set_callbacks(*out, callbacks); + return git_remote_create(out, repo, name, url); } /* @@ -277,7 +273,7 @@ static int create_and_configure_origin( if (!remote_create) { remote_create = default_remote_create; - payload = (void *)&options->remote_callbacks; + payload = NULL; } if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0) @@ -328,12 +324,11 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c return error; } -static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch) +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_remote *remote; - const git_remote_callbacks *callbacks; assert(repo && _remote); @@ -345,18 +340,13 @@ 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, git_buf_cstr(&reflog_message))) != 0) + if ((error = git_remote_fetch(remote, NULL, opts, git_buf_cstr(&reflog_message))) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message)); @@ -439,11 +429,11 @@ int git_clone( if (clone_local == 1) error = clone_local_into( - repo, origin, &options.checkout_opts, + repo, origin, &options.fetch_opts, &options.checkout_opts, options.checkout_branch, link); else if (clone_local == 0) error = clone_into( - repo, origin, &options.checkout_opts, + repo, origin, &options.fetch_opts, &options.checkout_opts, options.checkout_branch); else error = -1; @@ -506,7 +496,7 @@ static bool can_link(const char *src, const char *dst, int link) #endif } -static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link) +static int clone_local_into(git_repository *repo, git_remote *remote, const git_fetch_options *fetch_opts, const git_checkout_options *co_opts, const char *branch, int link) { int error, flags; git_repository *src; @@ -551,7 +541,7 @@ 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, git_buf_cstr(&reflog_message))) != 0) + 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)); diff --git a/src/fetch.c b/src/fetch.c index f61685619..e59ae8621 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -127,13 +127,26 @@ int git_fetch_negotiate(git_remote *remote) remote->refs.length); } -int git_fetch_download_pack(git_remote *remote) +int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks) { git_transport *t = remote->transport; + git_transfer_progress_cb progress = NULL; + void *payload = NULL; if (!remote->need_pack) return 0; - return t->download_pack(t, remote->repo, &remote->stats, - remote->callbacks.transfer_progress, remote->callbacks.payload); + if (callbacks) { + progress = callbacks->transfer_progress; + payload = callbacks->payload; + } + + return t->download_pack(t, remote->repo, &remote->stats, progress, payload); +} + +int git_fetch_init_options(git_fetch_options *opts, unsigned int version) +{ + GIT_INIT_STRUCTURE_FROM_TEMPLATE( + opts, version, git_fetch_options, GIT_FETCH_OPTIONS_INIT); + return 0; } diff --git a/src/fetch.h b/src/fetch.h index f66e44663..26d8a6b9d 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -11,7 +11,7 @@ int git_fetch_negotiate(git_remote *remote); -int git_fetch_download_pack(git_remote *remote); +int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks); int git_fetch__download_pack( git_transport *t, diff --git a/src/push.c b/src/push.c index a4b61cd35..cd219e905 100644 --- a/src/push.c +++ b/src/push.c @@ -155,7 +155,7 @@ int git_push_add_refspec(git_push *push, const char *refspec) return 0; } -int git_push_update_tips(git_push *push) +int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks) { git_buf remote_ref_name = GIT_BUF_INIT; size_t i, j; @@ -212,9 +212,9 @@ int git_push_update_tips(git_push *push) fire_callback = 0; } - if (fire_callback && push->remote->callbacks.update_tips) { - error = push->remote->callbacks.update_tips(git_buf_cstr(&remote_ref_name), - &push_spec->roid, &push_spec->loid, push->remote->callbacks.payload); + if (fire_callback && callbacks && callbacks->update_tips) { + error = callbacks->update_tips(git_buf_cstr(&remote_ref_name), + &push_spec->roid, &push_spec->loid, callbacks->payload); if (error < 0) goto on_error; @@ -571,11 +571,10 @@ static int calculate_work(git_push *push) return 0; } -static int do_push(git_push *push) +static int do_push(git_push *push, const git_remote_callbacks *callbacks) { int error = 0; git_transport *transport = push->remote->transport; - git_remote_callbacks *cbs = &push->remote->callbacks; if (!transport->push) { giterr_set(GITERR_NET, "Remote transport doesn't support push"); @@ -594,20 +593,20 @@ static int do_push(git_push *push) git_packbuilder_set_threads(push->pb, push->pb_parallelism); - if (cbs->pack_progress) - if ((error = git_packbuilder_set_callbacks(push->pb, cbs->pack_progress, cbs->payload)) < 0) + if (callbacks && callbacks->pack_progress) + if ((error = git_packbuilder_set_callbacks(push->pb, callbacks->pack_progress, callbacks->payload)) < 0) goto on_error; if ((error = calculate_work(push)) < 0) goto on_error; - if (cbs->push_negotiation && - (error = cbs->push_negotiation((const git_push_update **) push->updates.contents, - push->updates.length, cbs->payload)) < 0) + if (callbacks && callbacks->push_negotiation && + (error = callbacks->push_negotiation((const git_push_update **) push->updates.contents, + push->updates.length, callbacks->payload)) < 0) goto on_error; if ((error = queue_objects(push)) < 0 || - (error = transport->push(transport, push)) < 0) + (error = transport->push(transport, push, callbacks)) < 0) goto on_error; on_error: @@ -633,16 +632,16 @@ static int filter_refs(git_remote *remote) return 0; } -int git_push_finish(git_push *push) +int git_push_finish(git_push *push, const git_remote_callbacks *callbacks) { int error; if (!git_remote_connected(push->remote) && - (error = git_remote_connect(push->remote, GIT_DIRECTION_PUSH)) < 0) + (error = git_remote_connect(push->remote, GIT_DIRECTION_PUSH, callbacks)) < 0) return error; if ((error = filter_refs(push->remote)) < 0 || - (error = do_push(push)) < 0) + (error = do_push(push, callbacks)) < 0) return error; if (!push->unpack_ok) { diff --git a/src/push.h b/src/push.h index fcba45c8e..094f96ca9 100644 --- a/src/push.h +++ b/src/push.h @@ -87,7 +87,7 @@ int git_push_add_refspec(git_push *push, const char *refspec); * * @return 0 or an error code */ -int git_push_update_tips(git_push *push); +int git_push_update_tips(git_push *push, const git_remote_callbacks *callbacks); /** * Perform the push @@ -103,7 +103,7 @@ int git_push_update_tips(git_push *push); * * @return 0 or an error code */ -int git_push_finish(git_push *push); +int git_push_finish(git_push *push, const git_remote_callbacks *callbacks); /** * Invoke callback `cb' on each status entry diff --git a/src/remote.c b/src/remote.c index 91ebdd53c..85da2dc1b 100644 --- a/src/remote.c +++ b/src/remote.c @@ -691,15 +691,32 @@ const char* git_remote__urlfordirection(git_remote *remote, int direction) return NULL; } -int git_remote_connect(git_remote *remote, git_direction direction) +int set_transport_callbacks(git_transport *t, const git_remote_callbacks *cbs) +{ + if (!t->set_callbacks || !cbs) + return 0; + + return t->set_callbacks(t, cbs->sideband_progress, NULL, + cbs->certificate_check, cbs->payload); +} + +int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks) { git_transport *t; const char *url; int flags = GIT_TRANSPORTFLAGS_NONE; int error; + void *payload = NULL; + git_cred_acquire_cb credentials; assert(remote); + if (callbacks) { + GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); + credentials = callbacks->credentials; + payload = callbacks->payload; + } + t = remote->transport; url = git_remote__urlfordirection(remote, direction); @@ -720,11 +737,8 @@ int git_remote_connect(git_remote *remote, git_direction direction) if (!t && (error = git_transport_new(&t, remote, url)) < 0) return error; - if (t->set_callbacks && - (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.certificate_check, remote->callbacks.payload)) < 0) - goto on_error; - - if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0) + if ((error = set_transport_callbacks(t, callbacks)) < 0 || + (error = t->connect(t, url, credentials, payload, direction, flags)) != 0) goto on_error; remote->transport = t; @@ -866,14 +880,24 @@ 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_strarray *refspecs, const git_fetch_options *opts) { int error = -1; size_t i; git_vector refs, specs, *to_active; + const git_remote_callbacks *cbs = NULL; assert(remote); + if (opts) { + GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); + cbs = &opts->callbacks; + } + + if (!git_remote_connected(remote) && + (error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs)) < 0) + goto on_error; + if (ls_to_vector(&refs, remote) < 0) return -1; @@ -915,7 +939,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs) if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote); + return git_fetch_download_pack(remote, cbs); on_error: git_vector_free(&refs); @@ -927,16 +951,23 @@ on_error: int git_remote_fetch( git_remote *remote, const git_strarray *refspecs, + const git_fetch_options *opts, const char *reflog_message) { int error; git_buf reflog_msg_buf = GIT_BUF_INIT; + const git_remote_callbacks *cbs = NULL; + + if (opts) { + GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); + cbs = &opts->callbacks; + } /* Connect and download everything */ - if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0) + if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs)) != 0) return error; - error = git_remote_download(remote, refspecs); + error = git_remote_download(remote, refspecs, opts); /* We don't need to be connected anymore */ git_remote_disconnect(remote); @@ -954,13 +985,13 @@ int git_remote_fetch( } /* Create "remote/foo" branches for all remote branches */ - error = git_remote_update_tips(remote, git_buf_cstr(&reflog_msg_buf)); + error = git_remote_update_tips(remote, cbs, git_buf_cstr(&reflog_msg_buf)); git_buf_free(&reflog_msg_buf); if (error < 0) return error; if (remote->prune_refs) - error = git_remote_prune(remote); + error = git_remote_prune(remote, cbs); return error; } @@ -1156,7 +1187,7 @@ static int find_head(const void *_a, const void *_b) return strcmp(a->name, b->name); } -int git_remote_prune(git_remote *remote) +int git_remote_prune(git_remote *remote, const git_remote_callbacks *callbacks) { size_t i, j; git_vector remote_refs = GIT_VECTOR_INIT; @@ -1166,6 +1197,9 @@ int git_remote_prune(git_remote *remote) int error; git_oid zero_id = {{ 0 }}; + if (callbacks) + GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); + if ((error = ls_to_vector(&remote_refs, remote)) < 0) goto cleanup; @@ -1242,8 +1276,8 @@ int git_remote_prune(git_remote *remote) if (error < 0) goto cleanup; - if (remote->callbacks.update_tips) - error = remote->callbacks.update_tips(refname, &id, &zero_id, remote->callbacks.payload); + if (callbacks && callbacks->update_tips) + error = callbacks->update_tips(refname, &id, &zero_id, callbacks->payload); if (error < 0) goto cleanup; @@ -1257,6 +1291,7 @@ cleanup: static int update_tips_for_spec( git_remote *remote, + const git_remote_callbacks *callbacks, git_refspec *spec, git_vector *refs, const char *log_message) @@ -1339,8 +1374,8 @@ static int update_tips_for_spec( git_reference_free(ref); - if (remote->callbacks.update_tips != NULL) { - if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.payload) < 0) + if (callbacks && callbacks->update_tips != NULL) { + if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0) goto on_error; } } @@ -1455,6 +1490,7 @@ static int opportunistic_updates(const git_remote *remote, git_vector *refs, con int git_remote_update_tips( git_remote *remote, + const git_remote_callbacks *callbacks, const char *reflog_message) { git_refspec *spec, tagspec; @@ -1464,7 +1500,7 @@ int git_remote_update_tips( /* push has its own logic hidden away in the push object */ if (remote->push) { - return git_push_update_tips(remote->push); + return git_push_update_tips(remote->push, callbacks); } if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) @@ -1475,7 +1511,7 @@ int git_remote_update_tips( goto out; if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { - if ((error = update_tips_for_spec(remote, &tagspec, &refs, reflog_message)) < 0) + if ((error = update_tips_for_spec(remote, callbacks, &tagspec, &refs, reflog_message)) < 0) goto out; } @@ -1483,7 +1519,7 @@ int git_remote_update_tips( if (spec->push) continue; - if ((error = update_tips_for_spec(remote, spec, &refs, reflog_message)) < 0) + if ((error = update_tips_for_spec(remote, callbacks, spec, &refs, reflog_message)) < 0) goto out; } @@ -1600,31 +1636,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) return 0; } -int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks) -{ - assert(remote && callbacks); - - GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); - - memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks)); - - if (remote->transport && remote->transport->set_callbacks) - return remote->transport->set_callbacks(remote->transport, - remote->callbacks.sideband_progress, - NULL, - remote->callbacks.certificate_check, - remote->callbacks.payload); - - 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, @@ -2321,12 +2332,15 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi int error; git_push *push; git_refspec *spec; - git_remote_callbacks *cbs; + const git_remote_callbacks *cbs = NULL; assert(remote); + if (opts) + cbs = &opts->callbacks; + if (!git_remote_connected(remote) && - (error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0) + (error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs)) < 0) goto cleanup; free_refspecs(&remote->active_refspecs); @@ -2360,11 +2374,10 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi } } - if ((error = git_push_finish(push)) < 0) + if ((error = git_push_finish(push, cbs)) < 0) goto cleanup; - cbs = &remote->callbacks; - if (cbs->push_update_reference && + if (cbs && cbs->push_update_reference && (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0) goto cleanup; @@ -2375,16 +2388,22 @@ cleanup: int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts) { int error; + const git_remote_callbacks *cbs = NULL; + + if (opts) { + GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); + cbs = &opts->callbacks; + } assert(remote && refspecs); - if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0) + if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs)) < 0) return error; if ((error = git_remote_upload(remote, refspecs, opts)) < 0) return error; - error = git_remote_update_tips(remote, NULL); + error = git_remote_update_tips(remote, cbs, NULL); git_remote_disconnect(remote); return error; diff --git a/src/remote.h b/src/remote.h index a28b565ce..4fb2351d9 100644 --- a/src/remote.h +++ b/src/remote.h @@ -29,7 +29,6 @@ struct git_remote { git_transport *transport; git_repository *repo; git_push *push; - git_remote_callbacks callbacks; git_transfer_progress stats; unsigned int need_pack; git_remote_autotag_option_t download_tags; diff --git a/src/submodule.c b/src/submodule.c index d24a7773a..1139df973 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -950,7 +950,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio GITERR_CHECK_VERSION(&update_options, GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, "git_submodule_update_options"); /* Copy over the remote callbacks */ - clone_options.remote_callbacks = update_options.remote_callbacks; + memcpy(&clone_options.fetch_opts, &update_options.fetch_opts, sizeof(git_fetch_options)); /* Get the status of the submodule to determine if it is already initialized */ if ((error = git_submodule_status(&submodule_status, sm)) < 0) diff --git a/src/transports/local.c b/src/transports/local.c index def8ac037..305c71bf0 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -16,7 +16,6 @@ #include "git2/pack.h" #include "git2/commit.h" #include "git2/revparse.h" -#include "git2/push.h" #include "pack-objects.h" #include "refs.h" #include "posix.h" @@ -366,7 +365,8 @@ static int local_push_update_remote_ref( static int local_push( git_transport *transport, - git_push *push) + git_push *push, + const git_remote_callbacks *cbs) { transport_local *t = (transport_local *)transport; git_odb *remote_odb = NULL; @@ -380,6 +380,8 @@ static int local_push( unsigned int i; size_t j; + GIT_UNUSED(cbs); + /* 'push->remote->url' may be a url or path; convert to a path */ if ((error = git_path_from_url_or_path(&buf, push->remote->url)) < 0) { git_buf_free(&buf); @@ -471,7 +473,7 @@ static int local_push( if (!url || t->parent.close(&t->parent) < 0 || t->parent.connect(&t->parent, url, - push->remote->callbacks.credentials, NULL, GIT_DIRECTION_PUSH, flags)) + NULL, NULL, GIT_DIRECTION_PUSH, flags)) goto on_error; } diff --git a/src/transports/smart.h b/src/transports/smart.h index 44e241adc..4c728c7cc 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -158,7 +158,7 @@ typedef struct { /* smart_protocol.c */ int git_smart__store_refs(transport_smart *t, int flushes); int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vector *symrefs); -int git_smart__push(git_transport *transport, git_push *push); +int git_smart__push(git_transport *transport, git_push *push, const git_remote_callbacks *cbs); int git_smart__negotiate_fetch( git_transport *transport, diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 9e7b0a72b..7f6b74ca7 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -946,11 +946,10 @@ static int stream_thunk(void *buf, size_t size, void *data) return error; } -int git_smart__push(git_transport *transport, git_push *push) +int git_smart__push(git_transport *transport, git_push *push, const git_remote_callbacks *cbs) { transport_smart *t = (transport_smart *)transport; struct push_packbuilder_payload packbuilder_payload = {0}; - git_remote_callbacks *cbs = &push->remote->callbacks; git_buf pktline = GIT_BUF_INIT; int error = 0, need_pack = 0; push_spec *spec; @@ -958,7 +957,7 @@ int git_smart__push(git_transport *transport, git_push *push) packbuilder_payload.pb = push->pb; - if (cbs->transfer_progress) { + if (cbs && cbs->transfer_progress) { packbuilder_payload.cb = cbs->push_transfer_progress; packbuilder_payload.cb_payload = cbs->payload; } @@ -1011,7 +1010,7 @@ int git_smart__push(git_transport *transport, git_push *push) goto done; /* If progress is being reported write the final report */ - if (cbs->push_transfer_progress) { + if (cbs && cbs->push_transfer_progress) { error = cbs->push_transfer_progress( push->pb->nr_written, push->pb->nr_objects, diff --git a/tests/checkout/index.c b/tests/checkout/index.c index b759db206..de0770dba 100644 --- a/tests/checkout/index.c +++ b/tests/checkout/index.c @@ -154,9 +154,7 @@ void test_checkout_index__honor_coresymlinks_default(void) cl_git_pass(git_repository_set_workdir(repo, "symlink", 1)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, NULL)); - cl_git_pass(git_remote_update_tips(origin, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, NULL, NULL)); git_remote_free(origin); cl_git_pass(git_revparse_single(&target, repo, "remotes/origin/master")); diff --git a/tests/clone/empty.c b/tests/clone/empty.c index 8f6071096..2a6217580 100644 --- a/tests/clone/empty.c +++ b/tests/clone/empty.c @@ -10,14 +10,14 @@ static git_repository *g_repo_cloned; void test_clone_empty__initialize(void) { git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options dummy_options = GIT_FETCH_OPTIONS_INIT; cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.remote_callbacks = dummy_callbacks; + g_options.fetch_opts = dummy_options; } void test_clone_empty__cleanup(void) diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index e4794fc14..fec6aff2e 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -15,7 +15,7 @@ static git_remote* g_remote; void test_clone_nonetwork__initialize(void) { git_checkout_options dummy_opts = GIT_CHECKOUT_OPTIONS_INIT; - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options dummy_fetch = GIT_FETCH_OPTIONS_INIT; g_repo = NULL; @@ -23,7 +23,7 @@ void test_clone_nonetwork__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - g_options.remote_callbacks = dummy_callbacks; + g_options.fetch_opts = dummy_fetch; } void test_clone_nonetwork__cleanup(void) @@ -179,7 +179,7 @@ void test_clone_nonetwork__can_cancel_clone_in_fetch(void) { g_options.checkout_branch = "test"; - g_options.remote_callbacks.transfer_progress = + g_options.fetch_opts.callbacks.transfer_progress = clone_cancel_fetch_transfer_progress_cb; cl_git_fail_with(git_clone( diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index 2d6d53eb6..489481826 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -335,7 +335,7 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void) cl_git_pass(git_remote_set_url(remote, cl_fixture("testrepo.git"))); cl_git_pass(git_remote_save(remote)); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); git_remote_free(remote); cl_git_pass(git_repository_fetchhead_foreach(repo, assert_master_for_merge, NULL)); diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c index 13b3cf07c..a191b7b6b 100644 --- a/tests/network/fetchlocal.c +++ b/tests/network/fetchlocal.c @@ -34,19 +34,16 @@ void test_network_fetchlocal__complete(void) git_strarray refnames = {0}; const char *url = cl_git_fixture_url("testrepo.git"); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); 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, NULL)); - cl_git_pass(git_remote_update_tips(origin, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); @@ -66,17 +63,16 @@ void test_network_fetchlocal__prune(void) git_reference *ref; git_repository *remote_repo = cl_git_sandbox_init("testrepo.git"); const char *url = cl_git_path_url(git_repository_path(remote_repo)); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); @@ -89,11 +85,8 @@ void test_network_fetchlocal__prune(void) git_reference_free(ref); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, NULL)); - cl_git_pass(git_remote_prune(origin)); - cl_git_pass(git_remote_update_tips(origin, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); + cl_git_pass(git_remote_prune(origin, &options.callbacks)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(18, (int)refnames.count); @@ -105,11 +98,8 @@ void test_network_fetchlocal__prune(void) git_reference_free(ref); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, NULL)); - cl_git_pass(git_remote_prune(origin)); - cl_git_pass(git_remote_update_tips(origin, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); + cl_git_pass(git_remote_prune(origin, &options.callbacks)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(17, (int)refnames.count); @@ -151,9 +141,9 @@ void test_network_fetchlocal__prune_overlapping(void) git_repository *remote_repo = cl_git_sandbox_init("testrepo.git"); const char *url = cl_git_path_url(git_repository_path(remote_repo)); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/master")); git_oid_cpy(&target, git_reference_target(ref)); @@ -165,7 +155,6 @@ void test_network_fetchlocal__prune_overlapping(void) cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_repository_config(&config, repo)); cl_git_pass(git_config_set_bool(config, "remote.origin.prune", true)); @@ -173,8 +162,7 @@ void test_network_fetchlocal__prune_overlapping(void) git_remote_free(origin); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); assert_ref_exists(repo, "refs/remotes/origin/master"); assert_ref_exists(repo, "refs/remotes/origin/pr/42"); @@ -188,9 +176,8 @@ void test_network_fetchlocal__prune_overlapping(void) git_remote_free(origin); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - callbacks.update_tips = update_tips_fail_on_call; - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + options.callbacks.update_tips = update_tips_fail_on_call; + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); assert_ref_exists(repo, "refs/remotes/origin/master"); assert_ref_exists(repo, "refs/remotes/origin/pr/42"); @@ -204,9 +191,8 @@ void test_network_fetchlocal__prune_overlapping(void) git_remote_free(origin); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - callbacks.update_tips = update_tips_fail_on_call; - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + options.callbacks.update_tips = update_tips_fail_on_call; + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); git_config_free(config); git_strarray_free(&refnames); @@ -224,17 +210,16 @@ void test_network_fetchlocal__fetchprune(void) git_config *config; git_repository *remote_repo = cl_git_sandbox_init("testrepo.git"); const char *url = cl_git_path_url(git_repository_path(remote_repo)); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); @@ -247,9 +232,8 @@ void test_network_fetchlocal__fetchprune(void) git_reference_free(ref); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); - cl_git_pass(git_remote_prune(origin)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); + cl_git_pass(git_remote_prune(origin, &options.callbacks)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(18, (int)refnames.count); @@ -265,8 +249,7 @@ void test_network_fetchlocal__fetchprune(void) git_config_free(config); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); cl_assert_equal_i(1, git_remote_prune_refs(origin)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(17, (int)refnames.count); @@ -289,17 +272,16 @@ void test_network_fetchlocal__prune_tag(void) git_repository *remote_repo = cl_git_sandbox_init("testrepo.git"); const char *url = cl_git_path_url(git_repository_path(remote_repo)); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); git_remote_free(origin); cl_git_pass(git_revparse_single(&obj, repo, "origin/master")); @@ -321,8 +303,7 @@ void test_network_fetchlocal__prune_tag(void) git_config_free(config); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); cl_assert_equal_i(1, git_remote_prune_refs(origin)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_fetch(origin, NULL, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); assert_ref_exists(repo, "refs/tags/some-tag"); cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, repo, "refs/remotes/origin/fake-remote")); @@ -346,10 +327,10 @@ void test_network_fetchlocal__partial(void) int callcount = 0; git_strarray refnames = {0}; const char *url; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; + options.callbacks.transfer_progress = transfer_cb; + options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo)); @@ -357,10 +338,7 @@ void test_network_fetchlocal__partial(void) 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, NULL)); - cl_git_pass(git_remote_update_tips(origin, NULL)); + cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); git_strarray_free(&refnames); @@ -418,16 +396,13 @@ void test_network_fetchlocal__multi_remotes(void) git_repository *repo = cl_git_sandbox_init("testrepo.git"); git_remote *test, *test2; git_strarray refnames = {0}; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; cl_set_cleanup(&cleanup_sandbox, NULL); - callbacks.transfer_progress = transfer_cb; + options.callbacks.transfer_progress = transfer_cb; cl_git_pass(git_remote_lookup(&test, repo, "test")); cl_git_pass(git_remote_set_url(test, cl_git_fixture_url("testrepo.git"))); - git_remote_set_callbacks(test, &callbacks); - cl_git_pass(git_remote_connect(test, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(test, NULL)); - cl_git_pass(git_remote_update_tips(test, NULL)); + cl_git_pass(git_remote_fetch(test, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(32, (int)refnames.count); @@ -435,10 +410,7 @@ void test_network_fetchlocal__multi_remotes(void) cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl")); cl_git_pass(git_remote_set_url(test2, cl_git_fixture_url("testrepo.git"))); - git_remote_set_callbacks(test2, &callbacks); - cl_git_pass(git_remote_connect(test2, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(test2, NULL)); - cl_git_pass(git_remote_update_tips(test2, NULL)); + cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(44, (int)refnames.count); @@ -463,7 +435,7 @@ void test_network_fetchlocal__call_progress(void) { git_repository *repo; git_remote *remote; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; int callcount = 0; cl_git_pass(git_repository_init(&repo, "foo.git", true)); @@ -471,11 +443,10 @@ void test_network_fetchlocal__call_progress(void) cl_git_pass(git_remote_create_with_fetchspec(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"), "+refs/heads/*:refs/heads/*")); - callbacks.sideband_progress = sideband_cb; - callbacks.payload = &callcount; - cl_git_pass(git_remote_set_callbacks(remote, &callbacks)); + options.callbacks.sideband_progress = sideband_cb; + options.callbacks.payload = &callcount; - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, &options, NULL)); cl_assert(callcount != 0); git_remote_free(remote); diff --git a/tests/network/remote/defaultbranch.c b/tests/network/remote/defaultbranch.c index c83d5c8b0..e83755ef6 100644 --- a/tests/network/remote/defaultbranch.c +++ b/tests/network/remote/defaultbranch.c @@ -26,7 +26,7 @@ static void assert_default_branch(const char *should) { git_buf name = GIT_BUF_INIT; - cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL)); cl_git_pass(git_remote_default_branch(&name, g_remote)); cl_assert_equal_s(should, name.ptr); git_buf_free(&name); @@ -57,7 +57,7 @@ void test_network_remote_defaultbranch__no_default_branch(void) git_buf buf = GIT_BUF_INIT; cl_git_pass(git_remote_create(&remote_b, g_repo_b, "self", git_repository_path(g_repo_b))); - cl_git_pass(git_remote_connect(remote_b, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(remote_b, GIT_DIRECTION_FETCH, NULL)); cl_git_pass(git_remote_ls(&heads, &len, remote_b)); cl_assert_equal_i(0, len); @@ -80,7 +80,7 @@ void test_network_remote_defaultbranch__detached_sharing_nonbranch_id(void) cl_git_pass(git_reference_create(&ref, g_repo_a, "refs/foo/bar", &id, 1, NULL)); git_reference_free(ref); - cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL)); cl_git_fail_with(GIT_ENOTFOUND, git_remote_default_branch(&buf, g_remote)); cl_git_pass(git_clone(&cloned_repo, git_repository_path(g_repo_a), "./local-detached", NULL)); diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c index ba54de6af..1e03371f0 100644 --- a/tests/network/remote/local.c +++ b/tests/network/remote/local.c @@ -40,7 +40,7 @@ static void connect_to_local_repository(const char *local_repository) git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); cl_git_pass(git_remote_create_anonymous(&remote, repo, git_buf_cstr(&file_path_buf), NULL)); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); } void test_network_remote_local__connected(void) @@ -138,8 +138,7 @@ void test_network_remote_local__shorthand_fetch_refspec0(void) connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, NULL)); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); git_reference_free(ref); @@ -164,8 +163,7 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) connect_to_local_repository(cl_fixture("testrepo.git")); git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, NULL)); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); @@ -178,7 +176,7 @@ void test_network_remote_local__tagopt(void) cl_git_pass(git_remote_create(&remote, repo, "tagopt", cl_git_path_url(cl_fixture("testrepo.git")))); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); @@ -186,7 +184,7 @@ void test_network_remote_local__tagopt(void) git_reference_free(ref); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); } @@ -206,9 +204,7 @@ void test_network_remote_local__push_to_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, NULL)); - git_remote_disconnect(remote); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* Set up an empty bare repo to push into */ { @@ -219,7 +215,7 @@ void test_network_remote_local__push_to_bare_remote(void) /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localbare.git", NULL)); - cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL)); /* Try to push */ cl_git_pass(git_remote_upload(remote, &push_array, NULL)); @@ -244,8 +240,8 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, NULL)); + cl_git_pass(git_remote_download(remote, &array, NULL)); + cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); /* Set up an empty bare repo to push into */ @@ -260,7 +256,7 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void) /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, url, NULL)); - cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL)); /* Try to push */ cl_git_pass(git_remote_upload(remote, &push_array, NULL)); @@ -285,8 +281,8 @@ void test_network_remote_local__push_to_non_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, NULL)); + cl_git_pass(git_remote_download(remote, &array, NULL)); + cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); /* Set up an empty non-bare repo to push into */ @@ -298,7 +294,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localnonbare", NULL)); - cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL)); /* Try to push */ cl_git_fail_with(GIT_EBAREREPO, git_remote_upload(localremote, &push_array, NULL)); @@ -324,7 +320,7 @@ void test_network_remote_local__fetch(void) connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_fetch(remote, &array, "UPDAAAAAATE!!")); + cl_git_pass(git_remote_fetch(remote, &array, NULL, "UPDAAAAAATE!!")); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); git_reference_free(ref); @@ -353,8 +349,8 @@ void test_network_remote_local__reflog(void) connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array)); - cl_git_pass(git_remote_update_tips(remote, "UPDAAAAAATE!!")); + cl_git_pass(git_remote_download(remote, &array, NULL)); + cl_git_pass(git_remote_update_tips(remote, NULL, "UPDAAAAAATE!!")); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); @@ -381,7 +377,7 @@ void test_network_remote_local__fetch_default_reflog_message(void) connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_fetch(remote, &array, NULL)); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); @@ -408,7 +404,7 @@ void test_network_remote_local__opportunistic_update(void) /* this remote has a passive refspec of "refs/heads/:refs/remotes/origin/" */ cl_git_pass(git_remote_create(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"))); /* and we pass the active refspec "master" */ - cl_git_pass(git_remote_fetch(remote, &array, NULL)); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* and we expect that to update our copy of origin's master */ cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/origin/master")); @@ -430,11 +426,8 @@ void test_network_remote_local__update_tips_for_new_remote(void) { /* Push to bare repo */ cl_git_pass(git_remote_create(&new_remote, src_repo, "bare", "./localbare.git")); - cl_git_pass(git_remote_connect(new_remote, GIT_DIRECTION_PUSH)); - cl_git_pass(git_remote_upload(new_remote, &push_array, NULL)); - - /* Update tips and make sure remote branch has been created */ - cl_git_pass(git_remote_update_tips(new_remote, NULL)); + 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); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 3e6e438cc..456fb39fe 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -86,7 +86,7 @@ void test_network_remote_remotes__error_when_no_push_available(void) cl_git_pass(git_remote_set_transport(r, git_transport_local, NULL)); - cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH)); + cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH, NULL)); /* Make sure that push is really not available */ r->transport->push = NULL; @@ -273,7 +273,7 @@ void test_network_remote_remotes__nonmatch_upstream_refspec(void) cl_git_pass(git_config_set_string(config, "branch.master.remote", "taggy")); cl_git_pass(git_config_set_string(config, "branch.master.merge", "refs/heads/foo")); - cl_git_pass(git_remote_fetch(remote, &specs, NULL)); + cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL)); git_remote_free(remote); } @@ -408,7 +408,7 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void) cl_assert(remote->url == NULL); cl_assert(remote->pushurl == NULL); - cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); cl_assert(giterr_last() != NULL); cl_assert(giterr_last()->klass == GITERR_INVALID); @@ -425,7 +425,7 @@ void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void) cl_assert(remote->url == NULL); cl_assert(remote->pushurl == NULL); - cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); git_remote_free(remote); } @@ -519,6 +519,6 @@ void test_network_remote_remotes__fetch_from_anonymous(void) cl_git_pass(git_remote_create_anonymous(&remote, _repo, cl_fixture("testrepo.git"), "refs/heads/*:refs/other/*")); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); git_remote_free(remote); } diff --git a/tests/online/clone.c b/tests/online/clone.c index 4fdeee1d2..35ddbe9af 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -20,7 +20,7 @@ static git_clone_options g_options; void test_online_clone__initialize(void) { git_checkout_options dummy_opts = GIT_CHECKOUT_OPTIONS_INIT; - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options dummy_fetch = GIT_FETCH_OPTIONS_INIT; g_repo = NULL; @@ -28,7 +28,7 @@ void test_online_clone__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - g_options.remote_callbacks = dummy_callbacks; + g_options.fetch_opts = dummy_fetch; } void test_online_clone__cleanup(void) @@ -107,8 +107,8 @@ void test_online_clone__can_checkout_a_cloned_repo(void) g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - g_options.remote_callbacks.transfer_progress = &fetch_progress; - g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; + g_options.fetch_opts.callbacks.transfer_progress = &fetch_progress; + g_options.fetch_opts.callbacks.payload = &fetch_progress_cb_was_called; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); @@ -131,17 +131,12 @@ static int remote_mirror_cb(git_remote **out, git_repository *repo, { int error; git_remote *remote; - git_remote_callbacks *callbacks = (git_remote_callbacks *) payload; + GIT_UNUSED(payload); if ((error = git_remote_create(&remote, repo, name, url)) < 0) return error; - if ((error = git_remote_set_callbacks(remote, callbacks)) < 0) { - git_remote_free(remote); - return error; - } - git_remote_clear_refspecs(remote); if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) { @@ -157,16 +152,14 @@ void test_online_clone__clone_mirror(void) { git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_reference *head; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; bool fetch_progress_cb_was_called = false; - callbacks.transfer_progress = &fetch_progress; - callbacks.payload = &fetch_progress_cb_was_called; + opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; + opts.fetch_opts.callbacks.payload = &fetch_progress_cb_was_called; opts.bare = true; opts.remote_cb = remote_mirror_cb; - opts.remote_cb_payload = &callbacks; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo.git", &opts)); @@ -195,8 +188,8 @@ void test_online_clone__custom_remote_callbacks(void) { int callcount = 0; - g_options.remote_callbacks.update_tips = update_tips; - g_options.remote_callbacks.payload = &callcount; + g_options.fetch_opts.callbacks.update_tips = update_tips; + g_options.fetch_opts.callbacks.payload = &callcount; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_assert(callcount > 0); @@ -222,7 +215,7 @@ void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void) if (!remote_url || !remote_user) clar__skip(); - g_options.remote_callbacks.credentials = cred_failure_cb; + g_options.fetch_opts.callbacks.credentials = cred_failure_cb; cl_git_fail_with(-172, git_clone(&g_repo, remote_url, "./foo", &g_options)); } @@ -254,8 +247,8 @@ void test_online_clone__cred_callback_called_again_on_auth_failure(void) if (!remote_url || !remote_user) clar__skip(); - g_options.remote_callbacks.credentials = cred_count_calls_cb; - g_options.remote_callbacks.payload = &counter; + g_options.fetch_opts.callbacks.credentials = cred_count_calls_cb; + g_options.fetch_opts.callbacks.payload = &counter; cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, remote_url, "./foo", &g_options)); cl_assert_equal_i(3, counter); @@ -292,10 +285,10 @@ void test_online_clone__credentials(void) if (!remote_url) return; if (cl_getenv("GITTEST_REMOTE_DEFAULT")) { - g_options.remote_callbacks.credentials = cred_default; + g_options.fetch_opts.callbacks.credentials = cred_default; } else { - g_options.remote_callbacks.credentials = git_cred_userpass; - g_options.remote_callbacks.payload = &user_pass; + g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.payload = &user_pass; } cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); @@ -309,8 +302,8 @@ void test_online_clone__bitbucket_style(void) "libgit2", "libgit2" }; - g_options.remote_callbacks.credentials = git_cred_userpass; - g_options.remote_callbacks.payload = &user_pass; + g_options.fetch_opts.callbacks.credentials = git_cred_userpass; + g_options.fetch_opts.callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -340,7 +333,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) void test_online_clone__can_cancel(void) { - g_options.remote_callbacks.transfer_progress = cancel_at_half; + g_options.fetch_opts.callbacks.transfer_progress = cancel_at_half; cl_git_fail_with( git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321); @@ -387,8 +380,8 @@ void test_online_clone__ssh_auth_methods(void) #ifndef GIT_SSH clar__skip(); #endif - g_options.remote_callbacks.credentials = check_ssh_auth_methods; - g_options.remote_callbacks.payload = &with_user; + g_options.fetch_opts.callbacks.credentials = check_ssh_auth_methods; + g_options.fetch_opts.callbacks.payload = &with_user; with_user = 0; cl_git_fail_with(GIT_EUSER, @@ -407,7 +400,6 @@ static int custom_remote_ssh_with_paths( void *payload) { int error; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if ((error = git_remote_create(out, repo, name, url)) < 0) return error; @@ -415,9 +407,6 @@ static int custom_remote_ssh_with_paths( if ((error = git_remote_set_transport(*out, git_transport_ssh_with_paths, payload)) < 0) return error; - callbacks.credentials = cred_cb; - git_remote_set_callbacks(*out, &callbacks); - return 0; } @@ -468,7 +457,7 @@ void test_online_clone__ssh_cannot_change_username(void) #ifndef GIT_SSH clar__skip(); #endif - g_options.remote_callbacks.credentials = cred_foo_bar; + g_options.fetch_opts.callbacks.credentials = cred_foo_bar; cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options)); } @@ -511,7 +500,7 @@ int ssh_certificate_check(git_cert *cert, int valid, const char *host, void *pay void test_online_clone__ssh_cert(void) { - g_options.remote_callbacks.certificate_check = ssh_certificate_check; + g_options.fetch_opts.callbacks.certificate_check = ssh_certificate_check; if (!cl_getenv("GITTEST_REMOTE_SSH_FINGERPRINT")) cl_skip(); @@ -537,7 +526,7 @@ static int fail_certificate_check(git_cert *cert, int valid, const char *host, v void test_online_clone__certificate_invalid(void) { - g_options.remote_callbacks.certificate_check = fail_certificate_check; + g_options.fetch_opts.callbacks.certificate_check = fail_certificate_check; cl_git_fail_with(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options), GIT_ECERTIFICATE); @@ -561,14 +550,14 @@ static int succeed_certificate_check(git_cert *cert, int valid, const char *host void test_online_clone__certificate_valid(void) { - g_options.remote_callbacks.certificate_check = succeed_certificate_check; + g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check; cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options)); } void test_online_clone__start_with_http(void) { - g_options.remote_callbacks.certificate_check = succeed_certificate_check; + g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check; cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options)); } diff --git a/tests/online/fetch.c b/tests/online/fetch.c index 22f32ba1a..1a0f05039 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -35,21 +35,17 @@ static int progress(const git_transfer_progress *stats, void *payload) static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) { git_remote *remote; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; size_t bytes_received = 0; - callbacks.transfer_progress = progress; - callbacks.update_tips = update_tips; - callbacks.payload = &bytes_received; + options.callbacks.transfer_progress = progress; + options.callbacks.update_tips = update_tips; + options.callbacks.payload = &bytes_received; counter = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", url)); - git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL)); - git_remote_disconnect(remote); + cl_git_pass(git_remote_fetch(remote, NULL, &options, NULL)); cl_assert_equal_i(counter, n); cl_assert(bytes_received > 0); @@ -85,12 +81,12 @@ void test_online_fetch__fetch_twice(void) { git_remote *remote; cl_git_pass(git_remote_create(&remote, _repo, "test", "git://github.com/libgit2/TestGitRepository.git")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, NULL)); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); + cl_git_pass(git_remote_download(remote, NULL, NULL)); git_remote_disconnect(remote); - git_remote_connect(remote, GIT_DIRECTION_FETCH); - cl_git_pass(git_remote_download(remote, NULL)); + git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL); + cl_git_pass(git_remote_download(remote, NULL, NULL)); git_remote_disconnect(remote); git_remote_free(remote); @@ -110,7 +106,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date git_repository *_repository; bool invoked = false; git_remote *remote; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; opts.bare = true; @@ -121,18 +117,17 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date cl_git_pass(git_repository_open(&_repository, "./fetch/lg2")); cl_git_pass(git_remote_lookup(&remote, _repository, "origin")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); 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, NULL)); + options.callbacks.transfer_progress = &transferProgressCallback; + options.callbacks.payload = &invoked; + cl_git_pass(git_remote_download(remote, NULL, &options)); cl_assert_equal_i(false, invoked); - cl_git_pass(git_remote_update_tips(remote, NULL)); + cl_git_pass(git_remote_update_tips(remote, &options.callbacks, NULL)); git_remote_disconnect(remote); git_remote_free(remote); @@ -152,17 +147,16 @@ void test_online_fetch__can_cancel(void) { git_remote *remote; size_t bytes_received = 0; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options options = GIT_FETCH_OPTIONS_INIT; cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); - callbacks.transfer_progress = cancel_at_half; - callbacks.payload = &bytes_received; - git_remote_set_callbacks(remote, &callbacks); + options.callbacks.transfer_progress = cancel_at_half; + options.callbacks.payload = &bytes_received; - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_fail_with(git_remote_download(remote, NULL), -4321); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); + cl_git_fail_with(git_remote_download(remote, NULL, &options), -4321); git_remote_disconnect(remote); git_remote_free(remote); } @@ -175,7 +169,7 @@ void test_online_fetch__ls_disconnected(void) cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote)); git_remote_disconnect(remote); cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote)); @@ -193,7 +187,7 @@ void test_online_fetch__remote_symrefs(void) cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL)); git_remote_disconnect(remote); cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); @@ -208,8 +202,8 @@ void test_online_fetch__twice(void) git_remote *remote; cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); - cl_git_pass(git_remote_fetch(remote, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); git_remote_free(remote); } diff --git a/tests/online/fetchhead.c b/tests/online/fetchhead.c index 9a97abef3..b24b1b511 100644 --- a/tests/online/fetchhead.c +++ b/tests/online/fetchhead.c @@ -12,12 +12,12 @@ static git_clone_options g_options; void test_online_fetchhead__initialize(void) { - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options dummy_fetch = GIT_FETCH_OPTIONS_INIT; g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.remote_callbacks = dummy_callbacks; + g_options.fetch_opts = dummy_fetch; } void test_online_fetchhead__cleanup(void) @@ -51,10 +51,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet 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)); - git_remote_disconnect(remote); + cl_git_pass(git_remote_fetch(remote, active_refs, NULL, NULL)); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); diff --git a/tests/online/push.c b/tests/online/push.c index 9b98bc77a..b35632755 100644 --- a/tests/online/push.c +++ b/tests/online/push.c @@ -369,9 +369,8 @@ void test_online_push__initialize(void) cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); record_callbacks_data_clear(&_record_cbs_data); - git_remote_set_callbacks(_remote, &_record_cbs); - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); + cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH, NULL)); /* Clean up previously pushed branches. Fails if receive.denyDeletes is * set on the remote. Also, on Git 1.7.0 and newer, you must run @@ -394,10 +393,7 @@ void test_online_push__initialize(void) git_vector_free(&delete_specs); /* Now that we've deleted everything, fetch from the remote */ - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(_remote, NULL)); - cl_git_pass(git_remote_update_tips(_remote, NULL)); - git_remote_disconnect(_remote); + cl_git_pass(git_remote_fetch(_remote, NULL, NULL, NULL)); } void test_online_push__cleanup(void) @@ -459,20 +455,18 @@ static void do_push( size_t i; int error; git_strarray specs = {0}; - git_remote_callbacks callbacks; record_callbacks_data *data; if (_remote) { /* Auto-detect the number of threads to use */ opts.pb_parallelism = 0; - memcpy(&callbacks, git_remote_get_callbacks(_remote), sizeof(callbacks)); - data = callbacks.payload; + memcpy(&opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks)); + data = opts.callbacks.payload; - callbacks.pack_progress = push_pack_progress_cb; - callbacks.push_transfer_progress = push_transfer_progress_cb; - callbacks.push_update_reference = record_push_status_cb; - cl_git_pass(git_remote_set_callbacks(_remote, &callbacks)); + opts.callbacks.pack_progress = push_pack_progress_cb; + opts.callbacks.push_transfer_progress = push_transfer_progress_cb; + opts.callbacks.push_update_reference = record_push_status_cb; if (refspecs_len) { specs.count = refspecs_len; diff --git a/tests/submodule/update.c b/tests/submodule/update.c index 533e64efc..e7f1b76b8 100644 --- a/tests/submodule/update.c +++ b/tests/submodule/update.c @@ -96,8 +96,8 @@ void test_submodule_update__update_submodule(void) update_options.checkout_opts.progress_cb = checkout_progress_cb; update_options.checkout_opts.progress_payload = &update_payload; - update_options.remote_callbacks.update_tips = update_tips; - update_options.remote_callbacks.payload = &update_payload; + update_options.fetch_opts.callbacks.update_tips = update_tips; + update_options.fetch_opts.callbacks.payload = &update_payload; /* get the submodule */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); From 22261344de18b3cc60ee6937468d66a6a6a28875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 22 Apr 2015 04:38:08 +0200 Subject: [PATCH 03/13] remote: remove url and pushurl from the save logic As a first step in removing the repository-saving logic, don't allow chaning the url or push url from a remote object, but change the configuration on the configuration immediately. --- include/git2/remote.h | 24 ++++++---- src/remote.c | 88 ++++++++++++++++++++-------------- tests/fetchhead/nonetwork.c | 3 +- tests/network/fetchlocal.c | 4 +- tests/network/remote/remotes.c | 25 ++++++---- 5 files changed, 87 insertions(+), 57 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 5aea777c1..19b2fdf13 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -153,26 +153,30 @@ GIT_EXTERN(const char *) git_remote_url(const git_remote *remote); GIT_EXTERN(const char *) git_remote_pushurl(const git_remote *remote); /** - * Set the remote's url + * Set the remote's url in the configuration * - * Existing connections will not be updated. + * Remote objects already in memory will not be affected. This assumes + * the common case of a single-url remote and will otherwise return an error. * - * @param remote the remote + * @param repo the repository in which to perform the change + * @param remote the remote's name * @param url the url to set * @return 0 or an error value */ -GIT_EXTERN(int) git_remote_set_url(git_remote *remote, const char* url); +GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, const char* url); /** - * Set the remote's url for pushing + * Set the remote's url for pushing in the configuration. * - * Existing connections will not be updated. + * Remote objects already in memory will not be affected. This assumes + * the common case of a single-url remote and will otherwise return an error. * - * @param remote the remote - * @param url the url to set or NULL to clear the pushurl - * @return 0 or an error value + * + * @param repo the repository in which to perform the change + * @param remote the remote's name + * @param url the url to set */ -GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url); +GIT_EXTERN(int) git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url); /** * Add a fetch refspec to the remote diff --git a/src/remote.c b/src/remote.c index 85da2dc1b..9c044f7ad 100644 --- a/src/remote.c +++ b/src/remote.c @@ -20,6 +20,10 @@ #include "fetchhead.h" #include "push.h" +#define CONFIG_URL_FMT "remote.%s.url" +#define CONFIG_PUSHURL_FMT "remote.%s.pushurl" +#define CONFIG_FETCH_FMT "remote.%s.fetch" + static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name); @@ -141,12 +145,16 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n { git_remote *remote; git_config *config = NULL; - git_buf canonical_url = GIT_BUF_INIT, fetchbuf = GIT_BUF_INIT; + git_buf canonical_url = GIT_BUF_INIT; + git_buf var = GIT_BUF_INIT; int error = -1; /* name is optional */ assert(out && repo && url); + if ((error = git_repository_config__weakptr(&config, repo)) < 0) + return error; + remote = git__calloc(1, sizeof(git_remote)); GITERR_CHECK_ALLOC(remote); @@ -162,6 +170,12 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n if (name != NULL) { remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); + + if ((error = git_buf_printf(&var, CONFIG_URL_FMT, name)) < 0) + goto on_error; + + if ((error = git_config_set_string(config, var.ptr, remote->url)) < 0) + goto on_error; } if (fetch != NULL) { @@ -183,6 +197,8 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n /* A remote without a name doesn't download tags */ remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE; + git_buf_free(&var); + *out = remote; error = 0; @@ -191,8 +207,8 @@ on_error: git_remote_free(remote); git_config_free(config); - git_buf_free(&fetchbuf); git_buf_free(&canonical_url); + git_buf_free(&var); return error; } @@ -564,23 +580,8 @@ int git_remote_save(const git_remote *remote) 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; @@ -642,16 +643,42 @@ const char *git_remote_url(const git_remote *remote) return remote->url; } -int git_remote_set_url(git_remote *remote, const char* url) +static int set_url(git_repository *repo, const char *remote, const char *pattern, const char *url) { - assert(remote); - assert(url); + git_config *cfg; + git_buf buf = GIT_BUF_INIT, canonical_url = GIT_BUF_INIT; + int error; - git__free(remote->url); - remote->url = git__strdup(url); - GITERR_CHECK_ALLOC(remote->url); + assert(repo && remote); - return 0; + if ((error = ensure_remote_name_is_valid(remote)) < 0) + return error; + + if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) + return error; + + if ((error = git_buf_printf(&buf, pattern, remote)) < 0) + return error; + + if (url) { + if ((error = canonicalize_url(&canonical_url, url)) < 0) + goto cleanup; + + error = git_config_set_string(cfg, buf.ptr, url); + } else { + error = git_config_delete_entry(cfg, buf.ptr); + } + +cleanup: + git_buf_free(&canonical_url); + git_buf_free(&buf); + + return error; +} + +int git_remote_set_url(git_repository *repo, const char *remote, const char *url) +{ + return set_url(repo, remote, CONFIG_URL_FMT, url); } const char *git_remote_pushurl(const git_remote *remote) @@ -660,18 +687,9 @@ const char *git_remote_pushurl(const git_remote *remote) return remote->pushurl; } -int git_remote_set_pushurl(git_remote *remote, const char* url) +int git_remote_set_pushurl(git_repository *repo, const char *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; + return set_url(repo, remote, CONFIG_PUSHURL_FMT, url); } const char* git_remote__urlfordirection(git_remote *remote, int direction) diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index 489481826..24e87a618 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -331,9 +331,8 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void) cl_git_pass(git_clone(&repo, "./test1", "./repowithunborn", NULL)); /* Simulate someone pushing to it by changing to one that has stuff */ + cl_git_pass(git_remote_set_url(repo, "origin", cl_fixture("testrepo.git"))); cl_git_pass(git_remote_lookup(&remote, repo, "origin")); - cl_git_pass(git_remote_set_url(remote, cl_fixture("testrepo.git"))); - cl_git_pass(git_remote_save(remote)); cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); git_remote_free(remote); diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c index a191b7b6b..73ccec031 100644 --- a/tests/network/fetchlocal.c +++ b/tests/network/fetchlocal.c @@ -400,16 +400,16 @@ void test_network_fetchlocal__multi_remotes(void) cl_set_cleanup(&cleanup_sandbox, NULL); options.callbacks.transfer_progress = transfer_cb; + cl_git_pass(git_remote_set_url(repo, "test", cl_git_fixture_url("testrepo.git"))); cl_git_pass(git_remote_lookup(&test, repo, "test")); - cl_git_pass(git_remote_set_url(test, cl_git_fixture_url("testrepo.git"))); cl_git_pass(git_remote_fetch(test, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(32, (int)refnames.count); git_strarray_free(&refnames); + cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git"))); cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl")); - cl_git_pass(git_remote_set_url(test2, cl_git_fixture_url("testrepo.git"))); cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 456fb39fe..8dbd68f2d 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -54,11 +54,18 @@ void test_network_remote_remotes__parsing(void) void test_network_remote_remotes__pushurl(void) { - cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/notlibgit2")); - cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/notlibgit2"); + const char *name = git_remote_name(_remote); + git_remote *mod; - cl_git_pass(git_remote_set_pushurl(_remote, NULL)); - cl_assert(git_remote_pushurl(_remote) == NULL); + cl_git_pass(git_remote_set_pushurl(_repo, name, "git://github.com/libgit2/notlibgit2")); + cl_git_pass(git_remote_lookup(&mod, _repo, name)); + cl_assert_equal_s(git_remote_pushurl(mod), "git://github.com/libgit2/notlibgit2"); + git_remote_free(mod); + + cl_git_pass(git_remote_set_pushurl(_repo, name, NULL)); + cl_git_pass(git_remote_lookup(&mod, _repo, name)); + cl_assert(git_remote_pushurl(mod) == NULL); + git_remote_free(mod); } void test_network_remote_remotes__error_when_not_found(void) @@ -174,13 +181,16 @@ void test_network_remote_remotes__save(void) /* Set up the remote and save it to config */ cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); + git_remote_free(_remote); + cl_git_pass(git_remote_set_pushurl(_repo, "upstream", "git://github.com/libgit2/libgit2_push")); + cl_git_pass(git_remote_lookup(&_remote, _repo, "upstream")); + git_remote_clear_refspecs(_remote); cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); cl_git_pass(git_remote_add_push(_remote, push_refspec1)); cl_git_pass(git_remote_add_push(_remote, push_refspec2)); - cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); cl_git_pass(git_remote_save(_remote)); git_remote_free(_remote); _remote = NULL; @@ -203,12 +213,11 @@ void test_network_remote_remotes__save(void) cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); - /* remove the pushurl again and see if we can save that too */ - cl_git_pass(git_remote_set_pushurl(_remote, NULL)); - cl_git_pass(git_remote_save(_remote)); git_remote_free(_remote); _remote = NULL; + /* remove the pushurl again and see if we can save that too */ + cl_git_pass(git_remote_set_pushurl(_repo, "upstream", NULL)); cl_git_pass(git_remote_lookup(&_remote, _repo, "upstream")); cl_assert(git_remote_pushurl(_remote) == NULL); } From 6fb373a0e8eeff3c94853ff0ac55ca6b561c44a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 22 Apr 2015 04:54:00 +0200 Subject: [PATCH 04/13] remote: add prune option to fetch Add a prune setting in the fetch options to allow to fall back to the configuration (the default) or to set it on or off. --- include/git2/remote.h | 20 ++++++++++++++++++++ src/remote.c | 12 +++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 19b2fdf13..41cf8512f 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -505,6 +505,21 @@ GIT_EXTERN(int) git_remote_init_callbacks( git_remote_callbacks *opts, unsigned int version); +typedef enum { + /** + * Use the setting from the configuration + */ + GIT_FETCH_PRUNE_FALLBACK, + /** + * Force pruning on + */ + GIT_FETCH_PRUNE, + /** + * Force pruning off + */ + GIT_FETCH_NO_PRUNE, +} git_fetch_prune_t; + typedef struct { int version; @@ -512,6 +527,11 @@ typedef struct { * Callbacks to use for this fetch operation */ git_remote_callbacks callbacks; + + /** + * Whether to perform a prune after the fetch + */ + git_fetch_prune_t prune; } git_fetch_options; #define GIT_FETCH_OPTIONS_VERSION 1 diff --git a/src/remote.c b/src/remote.c index 9c044f7ad..a29b8aad9 100644 --- a/src/remote.c +++ b/src/remote.c @@ -973,6 +973,7 @@ int git_remote_fetch( const char *reflog_message) { int error; + bool prune = false; git_buf reflog_msg_buf = GIT_BUF_INIT; const git_remote_callbacks *cbs = NULL; @@ -1008,7 +1009,16 @@ int git_remote_fetch( if (error < 0) return error; - if (remote->prune_refs) + if (opts && opts->prune == GIT_FETCH_PRUNE) + prune = true; + else if (opts && opts->prune == GIT_FETCH_PRUNE_FALLBACK && remote->prune_refs) + prune = true; + else if (opts && opts->prune == GIT_FETCH_NO_PRUNE) + prune = false; + else + prune = remote->prune_refs; + + if (prune) error = git_remote_prune(remote, cbs); return error; From 058b753ceb8f6b25b77e57106b3a87997bc6362a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 22 Apr 2015 15:45:21 +0200 Subject: [PATCH 05/13] remote: move the transport ctor to the callbacks Instead of having it set in a different place from every other callback, put it the main structure. This removes some state from the remote and makes it behave more like clone, where the constructors are passed via the options. --- include/git2/remote.h | 6 ++++++ include/git2/sys/transport.h | 20 -------------------- include/git2/transport.h | 3 +++ include/git2/types.h | 6 ++++++ src/remote.c | 27 +++++---------------------- src/remote.h | 2 -- tests/clone/transport.c | 8 ++++---- tests/network/remote/remotes.c | 6 +++--- tests/online/clone.c | 8 ++++---- tests/online/push_util.h | 2 +- 10 files changed, 32 insertions(+), 56 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 41cf8512f..22aad5ad4 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -483,6 +483,12 @@ struct git_remote_callbacks { */ git_push_negotiation push_negotiation; + /** + * Create the transport to use for this operation. Leave NULL + * to auto-detect. + */ + git_transport_cb transport; + /** * This will be passed to each of the callbacks in this struct * as the last parameter. diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index d6ca8ff05..867fbcbce 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -30,8 +30,6 @@ typedef enum { GIT_TRANSPORTFLAGS_NONE = 0, } git_transport_flags_t; -typedef struct git_transport git_transport; - struct git_transport { unsigned int version; /* Set progress and error callbacks */ @@ -142,9 +140,6 @@ GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const */ GIT_EXTERN(int) git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *payload); -/* Signature of a function which creates a transport */ -typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param); - /** * Add a custom transport definition, to be used in addition to the built-in * set of transports that come with libgit2. @@ -353,21 +348,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh( git_transport* owner, void *param); -/** - * Sets a custom transport factory for the remote. The caller can use this - * function to override the transport used for this remote when performing - * network operations. - * - * @param remote the remote to configure - * @param transport_cb the function to use to create a transport - * @param payload opaque parameter passed to transport_cb - * @return 0 or an error code - */ -GIT_EXTERN(int) git_remote_set_transport( - git_remote *remote, - git_transport_cb transport_cb, - void *payload); - /** @} */ GIT_END_DECL #endif diff --git a/include/git2/transport.h b/include/git2/transport.h index c10907f5f..99fd09a1b 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -20,6 +20,9 @@ */ GIT_BEGIN_DECL +/** Signature of a function which creates a transport */ +typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param); + /** * Type of SSH host fingerprint */ diff --git a/include/git2/types.h b/include/git2/types.h index fdb5f2b09..d1e7cd92c 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -223,6 +223,12 @@ typedef struct git_refspec git_refspec; */ typedef struct git_remote git_remote; +/** + * Interface which represents a transport to communicate with a + * remote. + */ +typedef struct git_transport git_transport; + /** * Preparation for a push operation. Can be used to configure what to * push and the level of parallelism of the packfile builder. diff --git a/src/remote.c b/src/remote.c index a29b8aad9..95c316f54 100644 --- a/src/remote.c +++ b/src/remote.c @@ -309,8 +309,6 @@ int git_remote_dup(git_remote **dest, git_remote *source) GITERR_CHECK_ALLOC(remote->pushurl); } - remote->transport_cb = source->transport_cb; - remote->transport_cb_payload = source->transport_cb_payload; remote->repo = source->repo; remote->download_tags = source->download_tags; remote->update_fetchhead = source->update_fetchhead; @@ -725,13 +723,15 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re int flags = GIT_TRANSPORTFLAGS_NONE; int error; void *payload = NULL; - git_cred_acquire_cb credentials; + git_cred_acquire_cb credentials = NULL; + git_transport_cb transport = NULL; assert(remote); if (callbacks) { GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); credentials = callbacks->credentials; + transport = callbacks->transport; payload = callbacks->payload; } @@ -746,8 +746,8 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re /* If we don't have a transport object yet, and the caller specified a * custom transport factory, use that */ - if (!t && remote->transport_cb && - (error = remote->transport_cb(&t, remote, remote->transport_cb_payload)) < 0) + if (!t && transport && + (error = transport(&t, remote, payload)) < 0) return error; /* If we still don't have a transport, then use the global @@ -1664,23 +1664,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) return 0; } -int git_remote_set_transport( - git_remote *remote, - git_transport_cb transport_cb, - void *payload) -{ - assert(remote); - - if (remote->transport) { - giterr_set(GITERR_NET, "A transport is already bound to this remote"); - return -1; - } - - remote->transport_cb = transport_cb; - remote->transport_cb_payload = payload; - return 0; -} - const git_transfer_progress* git_remote_stats(git_remote *remote) { assert(remote); diff --git a/src/remote.h b/src/remote.h index 4fb2351d9..3a5c0dee4 100644 --- a/src/remote.h +++ b/src/remote.h @@ -24,8 +24,6 @@ struct git_remote { git_vector refspecs; git_vector active_refspecs; git_vector passive_refspecs; - git_transport_cb transport_cb; - void *transport_cb_payload; git_transport *transport; git_repository *repo; git_push *push; diff --git a/tests/clone/transport.c b/tests/clone/transport.c index 46c16a241..cccaae219 100644 --- a/tests/clone/transport.c +++ b/tests/clone/transport.c @@ -24,10 +24,9 @@ static int custom_transport_remote_create( { int error; - if ((error = git_remote_create(out, repo, name, url)) < 0) - return error; + GIT_UNUSED(payload); - if ((error = git_remote_set_transport(*out, custom_transport, payload)) < 0) + if ((error = git_remote_create(out, repo, name, url)) < 0) return error; return 0; @@ -40,7 +39,8 @@ void test_clone_transport__custom_transport(void) int custom_transport_used = 0; clone_opts.remote_cb = custom_transport_remote_create; - clone_opts.remote_cb_payload = &custom_transport_used; + clone_opts.fetch_opts.callbacks.transport = custom_transport; + clone_opts.fetch_opts.callbacks.payload = &custom_transport_used; cl_git_pass(git_clone(&repo, cl_fixture("testrepo.git"), "./custom_transport.git", &clone_opts)); git_repository_free(repo); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 8dbd68f2d..f31993710 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -80,6 +80,7 @@ void test_network_remote_remotes__error_when_not_found(void) void test_network_remote_remotes__error_when_no_push_available(void) { git_remote *r; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; char *specs = { "refs/heads/master", }; @@ -91,9 +92,8 @@ void test_network_remote_remotes__error_when_no_push_available(void) cl_git_pass(git_remote_create_anonymous(&r, _repo, cl_fixture("testrepo.git"), NULL)); - cl_git_pass(git_remote_set_transport(r, git_transport_local, NULL)); - - cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH, NULL)); + callbacks.transport = git_transport_local; + cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH, &callbacks)); /* Make sure that push is really not available */ r->transport->push = NULL; diff --git a/tests/online/clone.c b/tests/online/clone.c index 35ddbe9af..1d4196948 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -401,10 +401,9 @@ static int custom_remote_ssh_with_paths( { int error; - if ((error = git_remote_create(out, repo, name, url)) < 0) - return error; + GIT_UNUSED(payload); - if ((error = git_remote_set_transport(*out, git_transport_ssh_with_paths, payload)) < 0) + if ((error = git_remote_create(out, repo, name, url)) < 0) return error; return 0; @@ -435,7 +434,8 @@ void test_online_clone__ssh_with_paths(void) clar__skip(); g_options.remote_cb = custom_remote_ssh_with_paths; - g_options.remote_cb_payload = &arr; + g_options.fetch_opts.callbacks.transport = git_transport_ssh_with_paths; + g_options.fetch_opts.callbacks.payload = &arr; cl_git_fail(git_clone(&g_repo, remote_url, "./foo", &g_options)); diff --git a/tests/online/push_util.h b/tests/online/push_util.h index 83d46b506..822341bd2 100644 --- a/tests/online/push_util.h +++ b/tests/online/push_util.h @@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, NULL, data } typedef struct { char *name; From 3eff2a57289ec19b1a805dd938299d1dcae47097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 22 Apr 2015 16:11:10 +0200 Subject: [PATCH 06/13] remote: move the update_fetchhead setting to the options While this will rarely be different from the default, having it in the remote adds yet another setting it has to keep around and can affect its behaviour. Move it to the options. --- include/git2/remote.h | 27 +++++++++------------------ src/clone.c | 6 ++++-- src/remote.c | 28 +++++++++------------------- src/remote.h | 1 - tests/network/remote/local.c | 6 +++--- tests/online/fetch.c | 2 +- 6 files changed, 26 insertions(+), 44 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 22aad5ad4..5b42a9899 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -538,10 +538,16 @@ typedef struct { * Whether to perform a prune after the fetch */ git_fetch_prune_t prune; + + /** + * Whether to write the results to FETCH_HEAD. Defaults to + * on. Leave this default in order to behave like git. + */ + int update_fetchhead; } git_fetch_options; #define GIT_FETCH_OPTIONS_VERSION 1 -#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT } +#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, 0, 1 } /** * Initializes a `git_fetch_options` with default values. Equivalent to @@ -636,11 +642,13 @@ GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_strarray *refspe * the name of the remote (or its url, for in-memory remotes). This * parameter is ignored when pushing. * @param callbacks pointer to the callback structure to use + * @param update_fetchhead whether to write to FETCH_HEAD. Pass 1 to behave like git. * @return 0 or an error code */ GIT_EXTERN(int) git_remote_update_tips( git_remote *remote, const git_remote_callbacks *callbacks, + int update_fetchhead, const char *reflog_message); /** @@ -754,23 +762,6 @@ GIT_EXTERN(int) git_remote_rename( const char *name, const char *new_name); -/** - * Retrieve the update FETCH_HEAD setting. - * - * @param remote the remote to query - * @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 53cdae673..7dcbb8a1d 100644 --- a/src/clone.c +++ b/src/clone.c @@ -328,6 +328,7 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch { int error; git_buf reflog_message = GIT_BUF_INIT; + git_fetch_options fetch_opts; git_remote *remote; assert(repo && _remote); @@ -343,10 +344,11 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) goto cleanup; - git_remote_set_update_fetchhead(remote, 0); + memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); + fetch_opts.update_fetchhead = 0; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); - if ((error = git_remote_fetch(remote, NULL, opts, git_buf_cstr(&reflog_message))) != 0) + 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)); diff --git a/src/remote.c b/src/remote.c index 95c316f54..c4f5e0ff9 100644 --- a/src/remote.c +++ b/src/remote.c @@ -159,7 +159,6 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n GITERR_CHECK_ALLOC(remote); remote->repo = repo; - remote->update_fetchhead = 1; if (git_vector_init(&remote->refs, 32, NULL) < 0 || canonicalize_url(&canonical_url, url) < 0) @@ -311,7 +310,6 @@ int git_remote_dup(git_remote **dest, git_remote *source) remote->repo = source->repo; remote->download_tags = source->download_tags; - remote->update_fetchhead = source->update_fetchhead; remote->prune_refs = source->prune_refs; if (git_vector_init(&remote->refs, 32, NULL) < 0 || @@ -401,7 +399,6 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) remote = git__calloc(1, sizeof(git_remote)); GITERR_CHECK_ALLOC(remote); - remote->update_fetchhead = 1; remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); @@ -972,7 +969,7 @@ int git_remote_fetch( const git_fetch_options *opts, const char *reflog_message) { - int error; + int error, update_fetchhead = 1; bool prune = false; git_buf reflog_msg_buf = GIT_BUF_INIT; const git_remote_callbacks *cbs = NULL; @@ -980,6 +977,7 @@ int git_remote_fetch( if (opts) { GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); cbs = &opts->callbacks; + update_fetchhead = opts->update_fetchhead; } /* Connect and download everything */ @@ -1004,7 +1002,7 @@ int git_remote_fetch( } /* Create "remote/foo" branches for all remote branches */ - error = git_remote_update_tips(remote, cbs, git_buf_cstr(&reflog_msg_buf)); + error = git_remote_update_tips(remote, cbs, update_fetchhead, git_buf_cstr(&reflog_msg_buf)); git_buf_free(&reflog_msg_buf); if (error < 0) return error; @@ -1320,6 +1318,7 @@ cleanup: static int update_tips_for_spec( git_remote *remote, const git_remote_callbacks *callbacks, + int update_fetchhead, git_refspec *spec, git_vector *refs, const char *log_message) @@ -1408,7 +1407,7 @@ static int update_tips_for_spec( } } - if (git_remote_update_fetchhead(remote) && + if (update_fetchhead && (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0) goto on_error; @@ -1519,6 +1518,7 @@ static int opportunistic_updates(const git_remote *remote, git_vector *refs, con int git_remote_update_tips( git_remote *remote, const git_remote_callbacks *callbacks, + int update_fetchhead, const char *reflog_message) { git_refspec *spec, tagspec; @@ -1539,7 +1539,7 @@ int git_remote_update_tips( goto out; if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { - if ((error = update_tips_for_spec(remote, callbacks, &tagspec, &refs, reflog_message)) < 0) + if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, &tagspec, &refs, reflog_message)) < 0) goto out; } @@ -1547,7 +1547,7 @@ int git_remote_update_tips( if (spec->push) continue; - if ((error = update_tips_for_spec(remote, callbacks, spec, &refs, reflog_message)) < 0) + if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, spec, &refs, reflog_message)) < 0) goto out; } @@ -1948,16 +1948,6 @@ cleanup: return error; } -int git_remote_update_fetchhead(git_remote *remote) -{ - return (remote->update_fetchhead != 0); -} - -void git_remote_set_update_fetchhead(git_remote *remote, int value) -{ - remote->update_fetchhead = (value != 0); -} - int git_remote_is_valid_name( const char *remote_name) { @@ -2414,7 +2404,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_ if ((error = git_remote_upload(remote, refspecs, opts)) < 0) return error; - error = git_remote_update_tips(remote, cbs, NULL); + error = git_remote_update_tips(remote, cbs, 0, NULL); git_remote_disconnect(remote); return error; diff --git a/src/remote.h b/src/remote.h index 3a5c0dee4..e696997f4 100644 --- a/src/remote.h +++ b/src/remote.h @@ -30,7 +30,6 @@ struct git_remote { git_transfer_progress stats; unsigned int need_pack; git_remote_autotag_option_t download_tags; - int update_fetchhead; int prune_refs; int passed_refspecs; }; diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c index 1e03371f0..9134b60b1 100644 --- a/tests/network/remote/local.c +++ b/tests/network/remote/local.c @@ -241,7 +241,7 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); + cl_git_pass(git_remote_update_tips(remote, NULL, 1, NULL)); git_remote_disconnect(remote); /* Set up an empty bare repo to push into */ @@ -282,7 +282,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); + cl_git_pass(git_remote_update_tips(remote, NULL, 1, NULL)); git_remote_disconnect(remote); /* Set up an empty non-bare repo to push into */ @@ -350,7 +350,7 @@ void test_network_remote_local__reflog(void) connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, "UPDAAAAAATE!!")); + cl_git_pass(git_remote_update_tips(remote, NULL, 1, "UPDAAAAAATE!!")); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); diff --git a/tests/online/fetch.c b/tests/online/fetch.c index 1a0f05039..da0df0ad5 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -127,7 +127,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date cl_assert_equal_i(false, invoked); - cl_git_pass(git_remote_update_tips(remote, &options.callbacks, NULL)); + cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, NULL)); git_remote_disconnect(remote); git_remote_free(remote); From 35a8a8c546fe3d0a5bc7df7cf418244133ccf238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 22 Apr 2015 17:29:20 +0200 Subject: [PATCH 07/13] remote: move the tagopt setting to the fetch options This is another option which we should not be keeping in the remote, but is specific to each particular operation. --- include/git2/remote.h | 63 ++++++++++++++------ src/fetch.c | 18 +++--- src/fetch.h | 2 +- src/remote.c | 103 +++++++++++++++++++-------------- tests/network/remote/local.c | 24 ++++---- tests/network/remote/remotes.c | 11 ++-- tests/online/fetch.c | 4 +- tests/online/fetchhead.c | 5 +- 8 files changed, 136 insertions(+), 94 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 5b42a9899..e2350f4f5 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -526,6 +526,31 @@ typedef enum { GIT_FETCH_NO_PRUNE, } git_fetch_prune_t; +/** + * Automatic tag following option + * + * Lets us select the --tags option to use. + */ +typedef enum { + /** + * Use the setting from the configuration. + */ + GIT_REMOTE_DOWNLOAD_TAGS_FALLBACK = 0, + /** + * Ask the server for tags pointing to objects we're already + * downloading. + */ + GIT_REMOTE_DOWNLOAD_TAGS_AUTO, + /** + * Don't ask for any tags beyond the refspecs. + */ + GIT_REMOTE_DOWNLOAD_TAGS_NONE, + /** + * Ask for the all the tags. + */ + GIT_REMOTE_DOWNLOAD_TAGS_ALL, +} git_remote_autotag_option_t; + typedef struct { int version; @@ -544,6 +569,15 @@ typedef struct { * on. Leave this default in order to behave like git. */ int update_fetchhead; + + /** + * Determines how to behave regarding tags on the remote, such + * as auto-downloading tags for objects we're downloading or + * downloading all of them. + * + * The default is to auto-follow tags. + */ + git_remote_autotag_option_t download_tags; } git_fetch_options; #define GIT_FETCH_OPTIONS_VERSION 1 @@ -643,12 +677,15 @@ GIT_EXTERN(int) git_remote_upload(git_remote *remote, const git_strarray *refspe * parameter is ignored when pushing. * @param callbacks pointer to the callback structure to use * @param update_fetchhead whether to write to FETCH_HEAD. Pass 1 to behave like git. + * @param download_tags what the behaviour for downloading tags is for this fetch. This is + * ignored for push. This must be the same value passed to `git_remote_download()`. * @return 0 or an error code */ GIT_EXTERN(int) git_remote_update_tips( git_remote *remote, const git_remote_callbacks *callbacks, int update_fetchhead, + git_remote_autotag_option_t download_tags, const char *reflog_message); /** @@ -699,17 +736,6 @@ GIT_EXTERN(int) git_remote_push(git_remote *remote, */ 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 * @@ -719,15 +745,16 @@ typedef enum { GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *remote); /** - * Set the tag auto-follow setting + * Set the remote's tag following setting. * - * @param remote the remote to configure - * @param value a GIT_REMOTE_DOWNLOAD_TAGS value + * The change will be made in the configuration. No loaded remotes + * will be affected. + * + * @param repo the repository in which to make the change + * @param remote the name of the remote + * @param value the new value to take. */ -GIT_EXTERN(void) git_remote_set_autotag( - git_remote *remote, - git_remote_autotag_option_t value); - +GIT_EXTERN(int) git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value); /** * Retrieve the ref-prune setting * diff --git a/src/fetch.c b/src/fetch.c index e59ae8621..82d86bbce 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -19,14 +19,14 @@ #include "repository.h" #include "refs.h" -static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec) +static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec, git_remote_autotag_option_t tagopt) { int match = 0; if (!git_reference_is_valid_name(head->name)) return 0; - if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { + if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { /* * If tagopt is --tags, always request tags * in addition to the remote's refspecs @@ -51,13 +51,17 @@ static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, g return git_vector_insert(&remote->refs, head); } -static int filter_wants(git_remote *remote) +static int filter_wants(git_remote *remote, const git_fetch_options *opts) { git_remote_head **heads; git_refspec tagspec, head; int error = 0; git_odb *odb; size_t i, heads_len; + git_remote_autotag_option_t tagopt = remote->download_tags; + + if (opts && opts->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_FALLBACK) + tagopt = opts->download_tags; git_vector_clear(&remote->refs); if ((error = git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true)) < 0) @@ -87,7 +91,7 @@ static int filter_wants(git_remote *remote) goto cleanup; for (i = 0; i < heads_len; i++) { - if ((error = maybe_want(remote, heads[i], odb, &tagspec)) < 0) + if ((error = maybe_want(remote, heads[i], odb, &tagspec, tagopt)) < 0) break; } @@ -102,13 +106,13 @@ cleanup: * them out. When we get an ACK we hide that commit and continue * traversing until we're done */ -int git_fetch_negotiate(git_remote *remote) +int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) { git_transport *t = remote->transport; - remote->need_pack = 0; + remote->need_pack = 0; - if (filter_wants(remote) < 0) { + if (filter_wants(remote, opts) < 0) { giterr_set(GITERR_NET, "Failed to filter the reference list for wants"); return -1; } diff --git a/src/fetch.h b/src/fetch.h index 26d8a6b9d..aa2a87715 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -9,7 +9,7 @@ #include "netops.h" -int git_fetch_negotiate(git_remote *remote); +int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts); int git_fetch_download_pack(git_remote *remote, const git_remote_callbacks *callbacks); diff --git a/src/remote.c b/src/remote.c index c4f5e0ff9..ccbc46bbb 100644 --- a/src/remote.c +++ b/src/remote.c @@ -23,6 +23,7 @@ #define CONFIG_URL_FMT "remote.%s.url" #define CONFIG_PUSHURL_FMT "remote.%s.pushurl" #define CONFIG_FETCH_FMT "remote.%s.fetch" +#define CONFIG_TAGOPT_FMT "remote.%s.tagopt" static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); static int lookup_remote_prune_config(git_remote *remote, git_config *config, const char *name); @@ -60,7 +61,6 @@ static int download_tags_value(git_remote *remote, git_config *cfg) git_buf buf = GIT_BUF_INIT; int error; - /* The 0 value is the default (auto), let's see if we need to change it */ if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0) return -1; @@ -192,9 +192,12 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n goto on_error; } + /* A remote without a name doesn't download tags */ if (!name) - /* A remote without a name doesn't download tags */ remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE; + else + remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; + git_buf_free(&var); @@ -419,6 +422,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) optional_setting_found |= found; remote->repo = repo; + remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if (found && strlen(val) > 0) { remote->url = git__strdup(val); @@ -558,7 +562,6 @@ int git_remote_save(const git_remote *remote) { int error; git_config *cfg; - const char *tagopt = NULL; git_buf buf = GIT_BUF_INIT; git_config_entry *existing = NULL; @@ -583,37 +586,6 @@ int git_remote_save(const git_remote *remote) 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_config_entry_free(existing); git_buf_free(&buf); @@ -951,7 +923,7 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const remote->push = NULL; } - if ((error = git_fetch_negotiate(remote)) < 0) + if ((error = git_fetch_negotiate(remote, opts)) < 0) return error; return git_fetch_download_pack(remote, cbs); @@ -970,6 +942,7 @@ int git_remote_fetch( const char *reflog_message) { int error, update_fetchhead = 1; + git_remote_autotag_option_t tagopt = remote->download_tags; bool prune = false; git_buf reflog_msg_buf = GIT_BUF_INIT; const git_remote_callbacks *cbs = NULL; @@ -978,6 +951,7 @@ int git_remote_fetch( GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks"); cbs = &opts->callbacks; update_fetchhead = opts->update_fetchhead; + tagopt = opts->download_tags; } /* Connect and download everything */ @@ -1002,7 +976,7 @@ int git_remote_fetch( } /* Create "remote/foo" branches for all remote branches */ - error = git_remote_update_tips(remote, cbs, update_fetchhead, git_buf_cstr(&reflog_msg_buf)); + error = git_remote_update_tips(remote, cbs, update_fetchhead, tagopt, git_buf_cstr(&reflog_msg_buf)); git_buf_free(&reflog_msg_buf); if (error < 0) return error; @@ -1319,6 +1293,7 @@ static int update_tips_for_spec( git_remote *remote, const git_remote_callbacks *callbacks, int update_fetchhead, + git_remote_autotag_option_t tagopt, git_refspec *spec, git_vector *refs, const char *log_message) @@ -1354,9 +1329,9 @@ static int update_tips_for_spec( continue; if (git_refspec_src_matches(&tagspec, head->name)) { - if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { + if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { - if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) + if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) autotag = 1; git_buf_clear(&refname); @@ -1519,10 +1494,12 @@ int git_remote_update_tips( git_remote *remote, const git_remote_callbacks *callbacks, int update_fetchhead, + git_remote_autotag_option_t download_tags, const char *reflog_message) { git_refspec *spec, tagspec; git_vector refs = GIT_VECTOR_INIT; + git_remote_autotag_option_t tagopt; int error; size_t i; @@ -1538,8 +1515,13 @@ int git_remote_update_tips( if ((error = ls_to_vector(&refs, remote)) < 0) goto out; - if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { - if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, &tagspec, &refs, reflog_message)) < 0) + if (download_tags == GIT_REMOTE_DOWNLOAD_TAGS_FALLBACK) + tagopt = remote->download_tags; + else + tagopt = download_tags; + + if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { + if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0) goto out; } @@ -1547,7 +1529,7 @@ int git_remote_update_tips( if (spec->push) continue; - if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, spec, &refs, reflog_message)) < 0) + if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, spec, &refs, reflog_message)) < 0) goto out; } @@ -1675,9 +1657,42 @@ 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) +int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_autotag_option_t value) { - remote->download_tags = value; + git_buf var = GIT_BUF_INIT; + git_config *config; + int error; + + assert(repo && remote); + + if ((error = ensure_remote_name_is_valid(remote)) < 0) + return error; + + if ((error = git_repository_config__weakptr(&config, repo)) < 0) + return error; + + if ((error = git_buf_printf(&var, CONFIG_TAGOPT_FMT, remote))) + return error; + + switch (value) { + case GIT_REMOTE_DOWNLOAD_TAGS_NONE: + error = git_config_set_string(config, var.ptr, "--no-tags"); + break; + case GIT_REMOTE_DOWNLOAD_TAGS_ALL: + error = git_config_set_string(config, var.ptr, "--tags"); + break; + case GIT_REMOTE_DOWNLOAD_TAGS_AUTO: + error = git_config_delete_entry(config, var.ptr); + if (error == GIT_ENOTFOUND) + error = 0; + break; + default: + giterr_set(GITERR_INVALID, "Invalid value for the tagopt setting"); + error = -1; + } + + git_buf_free(&var); + return error; } int git_remote_prune_refs(const git_remote *remote) @@ -2404,7 +2419,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_ if ((error = git_remote_upload(remote, refspecs, opts)) < 0) return error; - error = git_remote_update_tips(remote, cbs, 0, NULL); + error = git_remote_update_tips(remote, cbs, 0, 0, NULL); git_remote_disconnect(remote); return error; diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c index 9134b60b1..bcde50cbb 100644 --- a/tests/network/remote/local.c +++ b/tests/network/remote/local.c @@ -165,26 +165,26 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); - cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); - + cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/origin/master")); cl_git_fail(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); } void test_network_remote_local__tagopt(void) { git_reference *ref; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; cl_git_pass(git_remote_create(&remote, repo, "tagopt", cl_git_path_url(cl_fixture("testrepo.git")))); - git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); + fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; + cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); git_reference_free(ref); - git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); - cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL)); + fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; + cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); } @@ -240,9 +240,7 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, 1, NULL)); - git_remote_disconnect(remote); + cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* Set up an empty bare repo to push into */ { @@ -278,12 +276,11 @@ void test_network_remote_local__push_to_non_bare_remote(void) }; /* 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_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, 1, NULL)); - git_remote_disconnect(remote); + cl_git_pass(git_remote_fetch(remote, &array, &fetch_opts, NULL)); /* Set up an empty non-bare repo to push into */ { @@ -349,8 +346,7 @@ void test_network_remote_local__reflog(void) connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_download(remote, &array, NULL)); - cl_git_pass(git_remote_update_tips(remote, NULL, 1, "UPDAAAAAATE!!")); + cl_git_pass(git_remote_fetch(remote, &array, NULL, "UPDAAAAAATE!!")); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index f31993710..819a22601 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -395,16 +395,15 @@ void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) void test_network_remote_remotes__tagopt(void) { - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_save(_remote)); + const char *name = git_remote_name(_remote); + + git_remote_set_autotag(_repo, name, GIT_REMOTE_DOWNLOAD_TAGS_ALL); assert_config_entry_value(_repo, "remote.test.tagopt", "--tags"); - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_NONE); - cl_git_pass(git_remote_save(_remote)); + git_remote_set_autotag(_repo, name, GIT_REMOTE_DOWNLOAD_TAGS_NONE); assert_config_entry_value(_repo, "remote.test.tagopt", "--no-tags"); - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); - cl_git_pass(git_remote_save(_remote)); + git_remote_set_autotag(_repo, name, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); assert_config_entry_existence(_repo, "remote.test.tagopt", false); } diff --git a/tests/online/fetch.c b/tests/online/fetch.c index da0df0ad5..72e7c24e3 100644 --- a/tests/online/fetch.c +++ b/tests/online/fetch.c @@ -41,10 +41,10 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) options.callbacks.transfer_progress = progress; options.callbacks.update_tips = update_tips; options.callbacks.payload = &bytes_received; + options.download_tags = flag; counter = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", url)); - git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_fetch(remote, NULL, &options, NULL)); cl_assert_equal_i(counter, n); cl_assert(bytes_received > 0); @@ -127,7 +127,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date cl_assert_equal_i(false, invoked); - cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, NULL)); + cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, options.download_tags, NULL)); git_remote_disconnect(remote); git_remote_free(remote); diff --git a/tests/online/fetchhead.c b/tests/online/fetchhead.c index b24b1b511..200edacfd 100644 --- a/tests/online/fetchhead.c +++ b/tests/online/fetchhead.c @@ -38,12 +38,13 @@ static void fetchhead_test_clone(void) static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; git_strarray array, *active_refs = NULL; cl_git_pass(git_remote_lookup(&remote, g_repo, "origin")); - git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); + fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if(fetchspec != NULL) { array.count = 1; @@ -51,7 +52,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet active_refs = &array; } - cl_git_pass(git_remote_fetch(remote, active_refs, NULL, NULL)); + cl_git_pass(git_remote_fetch(remote, active_refs, &fetch_opts, NULL)); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); From 3fec548a989b09fc7a2c30f42b1d4fa123a8867e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 23 Apr 2015 06:01:13 +0200 Subject: [PATCH 08/13] examples: adjust to the new remote API --- examples/network/clone.c | 6 +++--- examples/network/fetch.c | 17 +++++++++-------- examples/network/ls-remote.c | 3 +-- examples/remote.c | 14 +++----------- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 270bb68be..37e373d5a 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -86,9 +86,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; - clone_opts.remote_callbacks.transfer_progress = &fetch_progress; - clone_opts.remote_callbacks.credentials = cred_acquire_cb; - clone_opts.remote_callbacks.payload = &pd; + clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; + clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb; + clone_opts.fetch_opts.callbacks.payload = &pd; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/examples/network/fetch.c b/examples/network/fetch.c index a4bec032e..e47f5be4f 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -10,6 +10,7 @@ struct dl_data { git_remote *remote; + git_fetch_options *fetch_opts; int ret; int finished; }; @@ -28,7 +29,7 @@ static void *download(void *ptr) // Connect to the remote end specifying that we want to fetch // information from it. - if (git_remote_connect(data->remote, GIT_DIRECTION_FETCH) < 0) { + if (git_remote_connect(data->remote, GIT_DIRECTION_FETCH, &data->fetch_opts->callbacks) < 0) { data->ret = -1; goto exit; } @@ -36,7 +37,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, NULL) < 0) { + if (git_remote_download(data->remote, NULL, data->fetch_opts) < 0) { data->ret = -1; goto exit; } @@ -78,7 +79,7 @@ int fetch(git_repository *repo, int argc, char **argv) git_remote *remote = NULL; const git_transfer_progress *stats; struct dl_data data; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; #ifndef _WIN32 pthread_t worker; #endif @@ -96,13 +97,13 @@ int fetch(git_repository *repo, int argc, char **argv) } // Set up the callbacks (only update_tips for now) - callbacks.update_tips = &update_cb; - callbacks.sideband_progress = &progress_cb; - callbacks.credentials = cred_acquire_cb; - git_remote_set_callbacks(remote, &callbacks); + fetch_opts.callbacks.update_tips = &update_cb; + fetch_opts.callbacks.sideband_progress = &progress_cb; + fetch_opts.callbacks.credentials = cred_acquire_cb; // Set up the information for the background worker thread data.remote = remote; + data.fetch_opts = &fetch_opts; data.ret = 0; data.finished = 0; @@ -156,7 +157,7 @@ int fetch(git_repository *repo, int argc, char **argv) // right commits. This may be needed even if there was no packfile // to download, which can happen e.g. when the branches have been // changed but all the needed objects are available locally. - if (git_remote_update_tips(remote, NULL) < 0) + if (git_remote_update_tips(remote, &fetch_opts.callbacks, 1, fetch_opts.download_tags, NULL) < 0) return -1; git_remote_free(remote); diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index 5e3ade94f..a26092265 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -25,9 +25,8 @@ static int use_remote(git_repository *repo, char *name) * each of the remote references. */ callbacks.credentials = cred_acquire_cb; - git_remote_set_callbacks(remote, &callbacks); - error = git_remote_connect(remote, GIT_DIRECTION_FETCH); + error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks); if (error < 0) goto cleanup; diff --git a/examples/remote.c b/examples/remote.c index b756b5642..e0d5a1406 100644 --- a/examples/remote.c +++ b/examples/remote.c @@ -151,7 +151,6 @@ static int cmd_seturl(git_repository *repo, struct opts *o) { int i, retval, push = 0; char *name = NULL, *url = NULL; - git_remote *remote; for (i = 0; i < o->argc; i++) { char *arg = o->argv[i]; @@ -170,20 +169,13 @@ static int cmd_seturl(git_repository *repo, struct opts *o) if (name == NULL || url == NULL) usage("you need to specify remote and the new URL", NULL); - check_lg2(git_remote_lookup(&remote, repo, name), - "could not look up remote", name); - if (push) - retval = git_remote_set_pushurl(remote, url); + retval = git_remote_set_pushurl(repo, name, url); else - retval = git_remote_set_url(remote, url); + retval = git_remote_set_url(repo, name, url); + check_lg2(retval, "could not set URL", url); - check_lg2(git_remote_save(remote), - "could not save remote", NULL); - - git_remote_free(remote); - return 0; } From 7725499072aaf4d9093c615fee5a65d8477100bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 23 Apr 2015 06:51:34 +0200 Subject: [PATCH 09/13] remote: remove live changing of refspecs The base refspecs changing can be a cause of confusion as to what is the current base refspec set and complicate saving the remote's configuration. Change `git_remote_add_{fetch,push}()` to update the configuration instead of an instance. This finally makes `git_remote_save()` a no-op, it will be removed in a later commit. --- include/git2/remote.h | 31 ++++++-------- src/clone.c | 4 +- src/remote.c | 72 ++++++++++++++++++------------- tests/network/fetchlocal.c | 9 +--- tests/network/remote/local.c | 1 - tests/network/remote/remotes.c | 77 ++++++++-------------------------- tests/online/clone.c | 9 +--- tests/online/push.c | 6 ++- tests/refs/branches/remote.c | 7 +--- 9 files changed, 80 insertions(+), 136 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index e2350f4f5..73440a966 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -179,16 +179,17 @@ GIT_EXTERN(int) git_remote_set_url(git_repository *repo, const char *remote, con GIT_EXTERN(int) git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url); /** - * Add a fetch refspec to the remote + * Add a fetch refspec to the remote's configuration * - * Convenience function for adding a single fetch refspec to the - * current list in the remote. + * Add the given refspec to the fetch list in the configuration. No + * loaded remote instances will be affected. * - * @param remote the remote + * @param repo the repository in which to change the configuration + * @param remote the name of the remote to change * @param refspec the new fetch refspec * @return 0 or an error value */ -GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); +GIT_EXTERN(int) git_remote_add_fetch(git_repository *repo, const char *remote, const char *refspec); /** * Get the remote's list of fetch refspecs @@ -212,16 +213,17 @@ GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, const git_rem GIT_EXTERN(int) git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array); /** - * Add a push refspec to the remote + * Add a push refspec to the remote's configuration * - * Convenience function for adding a single push refspec to the - * current list in the remote. + * Add the given refspec to the push list in the configuration. No + * loaded remote instances will be affected. * - * @param remote the remote + * @param repo the repository in which to change the configuration + * @param remote the name of the remote to change * @param refspec the new push refspec * @return 0 or an error value */ -GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec); +GIT_EXTERN(int) git_remote_add_push(git_repository *repo, const char *remote, const char *refspec); /** * Get the remote's list of push refspecs @@ -244,15 +246,6 @@ GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, const git_remo */ GIT_EXTERN(int) git_remote_set_push_refspecs(git_remote *remote, git_strarray *array); -/** - * Clear the refspecs - * - * Remove all configured fetch and push refspecs from the remote. - * - * @param remote the remote - */ -GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote); - /** * Get the number of refspecs for a remote * diff --git a/src/clone.c b/src/clone.c index 7dcbb8a1d..c44cf599f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -341,11 +341,9 @@ static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch if ((error = git_remote_dup(&remote, _remote)) < 0) return error; - if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) - goto cleanup; - 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) diff --git a/src/remote.c b/src/remote.c index ccbc46bbb..f4a2f0452 100644 --- a/src/remote.c +++ b/src/remote.c @@ -23,6 +23,7 @@ #define CONFIG_URL_FMT "remote.%s.url" #define CONFIG_PUSHURL_FMT "remote.%s.pushurl" #define CONFIG_FETCH_FMT "remote.%s.fetch" +#define CONFIG_PUSH_FMT "remote.%s.push" #define CONFIG_TAGOPT_FMT "remote.%s.tagopt" static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); @@ -92,6 +93,38 @@ static int ensure_remote_name_is_valid(const char *name) return error; } +static int write_add_refspec(git_repository *repo, const char *name, const char *refspec, bool fetch) +{ + git_config *cfg; + git_buf var = GIT_BUF_INIT; + const char *fmt; + int error; + + if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) + return error; + + fmt = fetch ? CONFIG_FETCH_FMT : CONFIG_PUSH_FMT; + + if ((error = ensure_remote_name_is_valid(name)) < 0) + return error; + + if ((error = git_buf_printf(&var, fmt, name)) < 0) + return error; + + /* + * "$^" is a unmatcheable regexp: it will not match anything at all, so + * all values will be considered new and we will not replace any + * present value. + */ + if ((error = git_config_set_multivar(cfg, var.ptr, "$^", refspec)) < 0) { + goto cleanup; + } + +cleanup: + git_buf_free(&var); + return 0; +} + #if 0 /* We could export this as a helper */ static int get_check_cert(int *out, git_repository *repo) @@ -178,7 +211,11 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n } if (fetch != NULL) { - if (add_refspec(remote, fetch, true) < 0) + if ((error = add_refspec(remote, fetch, true)) < 0) + goto on_error; + + /* only write for non-anonymous remotes */ + if (name && (error = write_add_refspec(repo, name, fetch, true)) < 0) goto on_error; if ((error = git_repository_config_snapshot(&config, repo)) < 0) @@ -562,8 +599,6 @@ int git_remote_save(const git_remote *remote) { int error; git_config *cfg; - git_buf buf = GIT_BUF_INIT; - git_config_entry *existing = NULL; assert(remote); @@ -578,17 +613,6 @@ int git_remote_save(const git_remote *remote) if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) return error; - /* after this point, buffer is allocated so end with 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; - -cleanup: - git_config_entry_free(existing); - git_buf_free(&buf); return error; } @@ -2015,26 +2039,14 @@ git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *re return NULL; } -void git_remote_clear_refspecs(git_remote *remote) +int git_remote_add_fetch(git_repository *repo, const char *remote, const char *refspec) { - git_refspec *spec; - size_t i; - - git_vector_foreach(&remote->refspecs, i, spec) { - git_refspec__free(spec); - git__free(spec); - } - git_vector_clear(&remote->refspecs); + return write_add_refspec(repo, remote, refspec, true); } -int git_remote_add_fetch(git_remote *remote, const char *refspec) +int git_remote_add_push(git_repository *repo, const char *remote, const char *refspec) { - return add_refspec(remote, refspec, true); -} - -int git_remote_add_push(git_remote *remote, const char *refspec) -{ - return add_refspec(remote, refspec, false); + return write_add_refspec(repo, remote, refspec, false); } static int set_refspecs(git_remote *remote, git_strarray *array, int push) diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c index 73ccec031..06ee3dd36 100644 --- a/tests/network/fetchlocal.c +++ b/tests/network/fetchlocal.c @@ -358,16 +358,9 @@ static int remote_mirror_cb(git_remote **out, git_repository *repo, GIT_UNUSED(payload); - if ((error = git_remote_create(&remote, repo, name, url)) < 0) + if ((error = git_remote_create_with_fetchspec(&remote, repo, name, url, "+refs/*:refs/*")) < 0) return error; - git_remote_clear_refspecs(remote); - - if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) { - git_remote_free(remote); - return error; - } - *out = remote; return 0; } diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c index bcde50cbb..21cb93c57 100644 --- a/tests/network/remote/local.c +++ b/tests/network/remote/local.c @@ -161,7 +161,6 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) git_reference *ref; connect_to_local_repository(cl_fixture("testrepo.git")); - git_remote_clear_refspecs(remote); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 819a22601..0da76da6c 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -115,9 +115,12 @@ void test_network_remote_remotes__add_fetchspec(void) size = git_remote_refspec_count(_remote); - cl_git_pass(git_remote_add_fetch(_remote, "refs/*:refs/*")); - + cl_git_pass(git_remote_add_fetch(_repo, "test", "refs/*:refs/*")); size++; + + git_remote_free(_remote); + cl_git_pass(git_remote_lookup(&_remote, _repo, "test")); + cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); _refspec = git_remote_get_refspec(_remote, size - 1); @@ -156,8 +159,12 @@ void test_network_remote_remotes__add_pushspec(void) size = git_remote_refspec_count(_remote); - cl_git_pass(git_remote_add_push(_remote, "refs/*:refs/*")); + cl_git_pass(git_remote_add_push(_repo, "test", "refs/*:refs/*")); size++; + + git_remote_free(_remote); + cl_git_pass(git_remote_lookup(&_remote, _repo, "test")); + cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); _refspec = git_remote_get_refspec(_remote, size - 1); @@ -168,60 +175,6 @@ void test_network_remote_remotes__add_pushspec(void) cl_assert_equal_b(_refspec->push, true); } -void test_network_remote_remotes__save(void) -{ - git_strarray array; - const char *fetch_refspec1 = "refs/heads/ns1/*:refs/remotes/upstream/ns1/*"; - const char *fetch_refspec2 = "refs/heads/ns2/*:refs/remotes/upstream/ns2/*"; - const char *push_refspec1 = "refs/heads/ns1/*:refs/heads/ns1/*"; - const char *push_refspec2 = "refs/heads/ns2/*:refs/heads/ns2/*"; - - git_remote_free(_remote); - _remote = NULL; - - /* Set up the remote and save it to config */ - cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); - git_remote_free(_remote); - cl_git_pass(git_remote_set_pushurl(_repo, "upstream", "git://github.com/libgit2/libgit2_push")); - cl_git_pass(git_remote_lookup(&_remote, _repo, "upstream")); - - git_remote_clear_refspecs(_remote); - - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); - cl_git_pass(git_remote_add_push(_remote, push_refspec1)); - cl_git_pass(git_remote_add_push(_remote, push_refspec2)); - cl_git_pass(git_remote_save(_remote)); - git_remote_free(_remote); - _remote = NULL; - - /* Load it from config and make sure everything matches */ - cl_git_pass(git_remote_lookup(&_remote, _repo, "upstream")); - - cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); - cl_assert_equal_i(2, (int)array.count); - cl_assert_equal_s(fetch_refspec1, array.strings[0]); - cl_assert_equal_s(fetch_refspec2, array.strings[1]); - git_strarray_free(&array); - - cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); - cl_assert_equal_i(2, (int)array.count); - cl_assert_equal_s(push_refspec1, array.strings[0]); - cl_assert_equal_s(push_refspec2, array.strings[1]); - git_strarray_free(&array); - - cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); - cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); - - git_remote_free(_remote); - _remote = NULL; - - /* remove the pushurl again and see if we can save that too */ - cl_git_pass(git_remote_set_pushurl(_repo, "upstream", NULL)); - cl_git_pass(git_remote_lookup(&_remote, _repo, "upstream")); - cl_assert(git_remote_pushurl(_remote) == NULL); -} - void test_network_remote_remotes__fnmatch(void) { cl_assert(git_refspec_src_matches(_refspec, "refs/heads/master")); @@ -499,13 +452,16 @@ void test_network_remote_remotes__query_refspecs(void) git_strarray array; int i; - cl_git_pass(git_remote_create_anonymous(&remote, _repo, "git://github.com/libgit2/libgit2", NULL)); + cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "query", "git://github.com/libgit2/libgit2", NULL)); + git_remote_free(remote); for (i = 0; i < 3; i++) { - cl_git_pass(git_remote_add_fetch(remote, fetch_refspecs[i])); - cl_git_pass(git_remote_add_push(remote, push_refspecs[i])); + cl_git_pass(git_remote_add_fetch(_repo, "query", fetch_refspecs[i])); + cl_git_pass(git_remote_add_push(_repo, "query", push_refspecs[i])); } + cl_git_pass(git_remote_lookup(&remote, _repo, "query")); + cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); for (i = 0; i < 3; i++) { cl_assert_equal_s(fetch_refspecs[i], array.strings[i]); @@ -519,6 +475,7 @@ void test_network_remote_remotes__query_refspecs(void) git_strarray_free(&array); git_remote_free(remote); + git_remote_delete(_repo, "test"); } void test_network_remote_remotes__fetch_from_anonymous(void) diff --git a/tests/online/clone.c b/tests/online/clone.c index 1d4196948..1930a8ba3 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -134,16 +134,9 @@ static int remote_mirror_cb(git_remote **out, git_repository *repo, GIT_UNUSED(payload); - if ((error = git_remote_create(&remote, repo, name, url)) < 0) + if ((error = git_remote_create_with_fetchspec(&remote, repo, name, url, "+refs/*:refs/*")) < 0) return error; - git_remote_clear_refspecs(remote); - - if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) { - git_remote_free(remote); - return error; - } - *out = remote; return 0; } diff --git a/tests/online/push.c b/tests/online/push.c index b35632755..04ad7a2ed 100644 --- a/tests/online/push.c +++ b/tests/online/push.c @@ -861,6 +861,7 @@ void test_online_push__configured(void) { git_oid note_oid, *target_oid, expected_oid; git_signature *signature; + git_remote *old_remote; const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; push_status exp_stats[] = { { "refs/notes/commits", 1 } }; expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; @@ -870,7 +871,10 @@ void test_online_push__configured(void) target_oid = &_oid_b6; - cl_git_pass(git_remote_add_push(_remote, specs[0])); + cl_git_pass(git_remote_add_push(_repo, git_remote_name(_remote), specs[0])); + old_remote = _remote; + cl_git_pass(git_remote_lookup(&_remote, _repo, git_remote_name(_remote))); + git_remote_free(old_remote); /* Create note to push */ cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ diff --git a/tests/refs/branches/remote.c b/tests/refs/branches/remote.c index bac088454..47526717f 100644 --- a/tests/refs/branches/remote.c +++ b/tests/refs/branches/remote.c @@ -57,12 +57,7 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void) git_buf buf; /* Create the remote */ - cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2")); - - /* Update the remote fetch spec */ - git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_add_fetch(remote, "refs/heads/*:refs/remotes/test/*")); - cl_git_pass(git_remote_save(remote)); + cl_git_pass(git_remote_create_with_fetchspec(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2", "refs/heads/*:refs/remotes/test/*")); git_remote_free(remote); From a4b6452a6a32ac94c5c616eb4cc9c691d954732e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 23 Apr 2015 06:55:29 +0200 Subject: [PATCH 10/13] remote: remove git_remote_save() It has now become a no-op, so remove the function and all references to it. --- include/git2/remote.h | 17 ++--------------- src/clone.c | 3 --- src/remote.c | 24 ------------------------ tests/network/remote/remotes.c | 12 ------------ 4 files changed, 2 insertions(+), 54 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 73440a966..ab14ad4dc 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -28,8 +28,7 @@ GIT_BEGIN_DECL typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload); /** - * Add a remote with the default fetch refspec to the repository's configuration. This - * calls git_remote_save before returning. + * Add a remote with the default fetch refspec to the repository's configuration. * * @param out the resulting remote * @param repo the repository in which to create the remote @@ -45,8 +44,7 @@ GIT_EXTERN(int) git_remote_create( /** * Add a remote with the provided fetch refspec (or default if NULL) to the repository's - * configuration. This - * calls git_remote_save before returning. + * configuration. * * @param out the resulting remote * @param repo the repository in which to create the remote @@ -97,17 +95,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. diff --git a/src/clone.c b/src/clone.c index c44cf599f..8b42ce706 100644 --- a/src/clone.c +++ b/src/clone.c @@ -279,9 +279,6 @@ static int create_and_configure_origin( if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0) goto on_error; - if ((error = git_remote_save(origin)) < 0) - goto on_error; - *out = origin; return 0; diff --git a/src/remote.c b/src/remote.c index f4a2f0452..891f0f2b6 100644 --- a/src/remote.c +++ b/src/remote.c @@ -302,9 +302,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; @@ -595,27 +592,6 @@ cleanup: return error; } -int git_remote_save(const git_remote *remote) -{ - int error; - git_config *cfg; - - 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; - - return error; -} - const char *git_remote_name(const git_remote *remote) { assert(remote); diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 0da76da6c..f81c1ccc0 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -319,18 +319,6 @@ void test_network_remote_remotes__cannot_add_a_nameless_remote(void) git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); } -void test_network_remote_remotes__cannot_save_an_inmemory_remote(void) -{ - git_remote *remote; - - cl_git_pass(git_remote_create_anonymous(&remote, _repo, "git://github.com/libgit2/libgit2", NULL)); - - cl_assert_equal_p(NULL, git_remote_name(remote)); - - cl_git_fail(git_remote_save(remote)); - git_remote_free(remote); -} - void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) { git_remote *remote = NULL; From 3e20154a9d1ac15913cb639b057561e9043e6215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 25 Apr 2015 00:38:22 +0200 Subject: [PATCH 11/13] remote: simplify anonymous creation We're down to simply having it be a call to create_internal() so let's simply do that. The rest of the code is just a distraction. --- src/remote.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/remote.c b/src/remote.c index 891f0f2b6..44885bd17 100644 --- a/src/remote.c +++ b/src/remote.c @@ -313,14 +313,7 @@ on_error: int git_remote_create_anonymous(git_remote **out, git_repository *repo, const char *url, const char *fetch) { - int error; - git_remote *remote; - - if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0) - return error; - - *out = remote; - return 0; + return create_internal(out, repo, NULL, url, fetch); } int git_remote_dup(git_remote **dest, git_remote *source) From b1ae3e5317239db70670a13fd751a4442289e128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 26 Apr 2015 02:20:22 +0200 Subject: [PATCH 12/13] Update CHANGELOG with the changes to the remotes --- CHANGELOG.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8bea9e15..80d7b41f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,12 @@ support for HTTPS connections insead of OpenSSL. * Checkout can now accept an index for the baseline computations via the `baseline_index` member. +* The configuration for fetching is no longer stored inside the + `git_remote` struct but has been moved to a `git_fetch_options`. The + remote functions now take these options or the callbacks instead of + setting them beforehand. + + ### API additions * The `git_merge_options` gained a `file_flags` member. @@ -64,7 +70,15 @@ support for HTTPS connections insead of OpenSSL. put into the reflog as the source/target. * `git_index_add_frombuffer()` can now create a blob from memory - buffer and add it to the index which is attached to a repository. + buffer and add it to the index which is attached to a repository. + +* The structure `git_fetch_options` has been added to determine the + runtime configuration for fetching, such as callbacks, pruning and + autotag behaviour. It has the runtime initializer + `git_fetch_init_options()`. + +* The enum `git_fetch_prune_t` has been added, letting you specify the + pruning behaviour for a fetch. * `git_stash_apply()` can now apply a stashed state from the stash list, placing the data into the working directory and index. @@ -74,6 +88,15 @@ support for HTTPS connections insead of OpenSSL. ### API removals +* `git_remote_save()` and `git_remote_clear_refspecs()` has been + removed. Remote's configuration is changed via the configuration + directly or through a convenience function which performs changes to + the configuration directly. + +* `git_remote_set_callbacks()`, `git_remote_get_callbacks()` and + `git_remote_set_transport()` have been removed a the remote no + longer stores this configuration. + ### Breaking API changes * `git_smart_subtransport_cb` now has a `param` parameter. @@ -130,6 +153,39 @@ support for HTTPS connections insead of OpenSSL. `git_rebase_open` functions take a `git_rebase_options`, where they will persist the options to subsequent `git_rebase` calls. +* The `git_clone_options` struct now has fetch options in a + `fetch_opts` field instead of remote callbacks in + `remote_callbacks`. + +* The following functions now longer act on a remote instance but + change the repository's configuration. Their signatures have changed + accordingly: + + * `git_remote_set_url()`, `git_remote_seturl()` + * `git_remote_add_fetch()`, `git_remote_add_push()` and + * `git_remote_set_autotag()` + +* `git_remote_connect()` and `git_remote_prune()` now take a pointer + to the callbacks. + +* `git_remote_fetch()` and `git_remote_download()` now take a poitner + to fetch options which determine the runtime configuration. + +* The `git_remote_autotag_option_t` values have been changed. It has + gained a `_FALLBACK` default value to specify no override for the + configured setting. + +* `git_remote_update_tips()` now takes a pointer to the callbacks as + well as a boolean whether to write `FETCH_HEAD` and the autotag + setting. + +* The `git_submodule_update_options` struct now has fetch options in + the `fetch_opts` field instead of callbacks in the + `remote_callbacks` field. + +* The `push` function in the `git_transport` interface now takes a + pointer to the remote callbacks. + v0.22 ------ From 3251972e1fbab379d9ec5a94e455431d005446d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 4 May 2015 09:39:55 +0200 Subject: [PATCH 13/13] push: free the update list --- src/push.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/push.c b/src/push.c index cd219e905..abe90b76d 100644 --- a/src/push.c +++ b/src/push.c @@ -682,6 +682,7 @@ void git_push_free(git_push *push) { push_spec *spec; push_status *status; + git_push_update *update; unsigned int i; if (push == NULL) @@ -697,6 +698,13 @@ void git_push_free(git_push *push) } git_vector_free(&push->status); + git_vector_foreach(&push->updates, i, update) { + git__free(update->src_refname); + git__free(update->dst_refname); + git__free(update); + } + git_vector_free(&push->updates); + git__free(push); }