Commit 5bfead1d by Vicent Martí

Merge pull request #1855 from libgit2/cmn/clone-into

An alternative for 'clone' with options
parents 71e33d26 0e0cf787
...@@ -74,9 +74,9 @@ int do_clone(git_repository *repo, int argc, char **argv) ...@@ -74,9 +74,9 @@ int do_clone(git_repository *repo, int argc, char **argv)
checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_cb = checkout_progress;
checkout_opts.progress_payload = &pd; checkout_opts.progress_payload = &pd;
clone_opts.checkout_opts = checkout_opts; clone_opts.checkout_opts = checkout_opts;
clone_opts.fetch_progress_cb = &fetch_progress; clone_opts.remote_callbacks.transfer_progress = &fetch_progress;
clone_opts.fetch_progress_payload = &pd; clone_opts.remote_callbacks.credentials = cred_acquire_cb;
clone_opts.cred_acquire_cb = cred_acquire_cb; clone_opts.remote_callbacks.payload = &pd;
// Do the clone // Do the clone
error = git_clone(&cloned_repo, url, path, &clone_opts); error = git_clone(&cloned_repo, url, path, &clone_opts);
......
...@@ -35,7 +35,7 @@ static void *download(void *ptr) ...@@ -35,7 +35,7 @@ static void *download(void *ptr)
// Download the packfile and index it. This function updates the // Download the packfile and index it. This function updates the
// amount of received data and the indexer stats which lets you // amount of received data and the indexer stats which lets you
// inform the user about progress. // inform the user about progress.
if (git_remote_download(data->remote, NULL, NULL) < 0) { if (git_remote_download(data->remote) < 0) {
data->ret = -1; data->ret = -1;
goto exit; goto exit;
} }
...@@ -91,8 +91,8 @@ int fetch(git_repository *repo, int argc, char **argv) ...@@ -91,8 +91,8 @@ int fetch(git_repository *repo, int argc, char **argv)
// Set up the callbacks (only update_tips for now) // Set up the callbacks (only update_tips for now)
callbacks.update_tips = &update_cb; callbacks.update_tips = &update_cb;
callbacks.progress = &progress_cb; callbacks.progress = &progress_cb;
callbacks.credentials = cred_acquire_cb;
git_remote_set_callbacks(remote, &callbacks); git_remote_set_callbacks(remote, &callbacks);
git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL);
// Set up the information for the background worker thread // Set up the information for the background worker thread
data.remote = remote; data.remote = remote;
......
...@@ -18,6 +18,7 @@ static int use_remote(git_repository *repo, char *name) ...@@ -18,6 +18,7 @@ static int use_remote(git_repository *repo, char *name)
{ {
git_remote *remote = NULL; git_remote *remote = NULL;
int error; int error;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
// Find the remote by name // Find the remote by name
error = git_remote_load(&remote, repo, name); error = git_remote_load(&remote, repo, name);
...@@ -27,7 +28,8 @@ static int use_remote(git_repository *repo, char *name) ...@@ -27,7 +28,8 @@ static int use_remote(git_repository *repo, char *name)
goto cleanup; goto cleanup;
} }
git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); 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);
if (error < 0) if (error < 0)
......
...@@ -255,7 +255,7 @@ typedef struct git_checkout_opts { ...@@ -255,7 +255,7 @@ typedef struct git_checkout_opts {
*/ */
GIT_EXTERN(int) git_checkout_head( GIT_EXTERN(int) git_checkout_head(
git_repository *repo, git_repository *repo,
git_checkout_opts *opts); const git_checkout_opts *opts);
/** /**
* Updates files in the working tree to match the content of the index. * Updates files in the working tree to match the content of the index.
......
...@@ -35,30 +35,12 @@ GIT_BEGIN_DECL ...@@ -35,30 +35,12 @@ GIT_BEGIN_DECL
* set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT. * set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT.
* - `bare` should be set to zero to create a standard repo, non-zero for * - `bare` should be set to zero to create a standard repo, non-zero for
* a bare repo * a bare repo
* - `fetch_progress_cb` is optional callback for fetch progress. Be aware that * - `ignore_cert_errors` should be set to 1 if errors validating the remote host's
* this is called inline with network and indexing operations, so performance * certificate should be ignored.
* may be affected.
* - `fetch_progress_payload` is payload for fetch_progress_cb
* *
* ** "origin" remote options: ** * ** "origin" remote options: **
* - `remote_name` is the name given to the "origin" remote. The default is * - `remote_name` is the name given to the "origin" remote. The default is
* "origin". * "origin".
* - `pushurl` is a URL to be used for pushing. NULL means use the fetch url.
* - `fetch_spec` is the fetch specification to be used for fetching. NULL
* results in the same behavior as GIT_REMOTE_DEFAULT_FETCH.
* - `push_spec` is the fetch specification to be used for pushing. NULL means
* use the same spec as for fetching.
* - `cred_acquire_cb` is a callback to be used if credentials are required
* during the initial fetch.
* - `cred_acquire_payload` is the payload for the above callback.
* - `transport_flags` is flags used to create transport if no transport is
* provided.
* - `transport` is a custom transport to be used for the initial fetch. NULL
* means use the transport autodetected from the URL.
* - `remote_callbacks` may be used to specify custom progress callbacks for
* the origin remote before the fetch is initiated.
* - `remote_autotag` may be used to specify the autotag setting before the
* initial fetch. The default is GIT_REMOTE_DOWNLOAD_TAGS_ALL.
* - `checkout_branch` gives the name of the branch to checkout. NULL means * - `checkout_branch` gives the name of the branch to checkout. NULL means
* use the remote's HEAD. * use the remote's HEAD.
*/ */
...@@ -67,30 +49,23 @@ typedef struct git_clone_options { ...@@ -67,30 +49,23 @@ typedef struct git_clone_options {
unsigned int version; unsigned int version;
git_checkout_opts checkout_opts; git_checkout_opts checkout_opts;
git_repository_init_options *init_options; git_remote_callbacks remote_callbacks;
int bare;
git_transfer_progress_callback fetch_progress_cb;
void *fetch_progress_payload;
int bare;
int ignore_cert_errors;
const char *remote_name; const char *remote_name;
const char *pushurl;
const char *fetch_spec;
const char *push_spec;
git_cred_acquire_cb cred_acquire_cb;
void *cred_acquire_payload;
git_transport_flags_t transport_flags;
git_transport *transport;
git_remote_callbacks *remote_callbacks;
git_remote_autotag_option_t remote_autotag;
const char* checkout_branch; const char* checkout_branch;
} git_clone_options; } git_clone_options;
#define GIT_CLONE_OPTIONS_VERSION 1 #define GIT_CLONE_OPTIONS_VERSION 1
#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}} #define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT}
/** /**
* Clone a remote repository, and checkout the branch pointed to by the remote * Clone a remote repository.
* HEAD. *
* This version handles the simple case. If you'd like to create the
* repository or remote with non-default settings, you can create and
* configure them and then use `git_clone_into()`.
* *
* @param out pointer that will receive the resulting repository object * @param out pointer that will receive the resulting repository object
* @param url the remote repository to clone * @param url the remote repository to clone
...@@ -106,6 +81,22 @@ GIT_EXTERN(int) git_clone( ...@@ -106,6 +81,22 @@ GIT_EXTERN(int) git_clone(
const char *local_path, const char *local_path,
const git_clone_options *options); const git_clone_options *options);
/**
* Clone into a repository
*
* After creating the repository and remote and configuring them for
* paths and callbacks respectively, you can call this function to
* perform the clone operation and optionally checkout files.
*
* @param repo the repository to use
* @param remote the remote repository to clone from
* @param co_opts options to use during checkout
* @param branch the branch to checkout after the clone, pass NULL for the remote's
* default branch
* @return 0 on success or an error code
*/
GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -257,17 +257,9 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void ...@@ -257,17 +257,9 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void
* The .idx file will be created and both it and the packfile with be * The .idx file will be created and both it and the packfile with be
* renamed to their final name. * renamed to their final name.
* *
* @param remote the remote to download from
* @param progress_cb function to call with progress information. Be aware that
* this is called inline with network and indexing operations, so performance
* may be affected.
* @param payload payload for the progress callback
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_remote_download( GIT_EXTERN(int) git_remote_download(git_remote *remote);
git_remote *remote,
git_transfer_progress_callback progress_cb,
void *payload);
/** /**
* Check whether the remote is connected * Check whether the remote is connected
...@@ -319,6 +311,17 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); ...@@ -319,6 +311,17 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote);
GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); GIT_EXTERN(int) git_remote_update_tips(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
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_fetch(git_remote *remote);
/**
* Return whether a string is a valid remote URL * Return whether a string is a valid remote URL
* *
* @param url the url to check * @param url the url to check
...@@ -397,13 +400,47 @@ typedef enum git_remote_completion_type { ...@@ -397,13 +400,47 @@ typedef enum git_remote_completion_type {
/** /**
* The callback settings structure * The callback settings structure
* *
* Set the calbacks to be called by the remote. * Set the callbacks to be called by the remote when informing the user
* about the progress of the network operations.
*/ */
struct git_remote_callbacks { struct git_remote_callbacks {
unsigned int version; unsigned int version;
/**
* Textual progress from the remote. Text send over the
* progress side-band will be passed to this function (this is
* the 'counting objects' output.
*/
void (*progress)(const char *str, int len, void *data); void (*progress)(const char *str, int len, void *data);
/**
* Completion is called when different parts of the download
* process are done (currently unused).
*/
int (*completion)(git_remote_completion_type type, void *data); int (*completion)(git_remote_completion_type type, void *data);
/**
* This will be called if the remote host requires
* authentication in order to connect to it.
*/
int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data);
/**
* During the download of new data, this will be regularly
* called with the current count of progress done by the
* indexer.
*/
int (*transfer_progress)(const git_transfer_progress *stats, void *data);
/**
* Each time a reference is updated locally, this function
* will be called with information about it.
*/
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
/**
* This will be passed to each of the callbacks in this struct
* as the last parameter.
*/
void *payload; void *payload;
}; };
...@@ -420,7 +457,7 @@ struct git_remote_callbacks { ...@@ -420,7 +457,7 @@ struct git_remote_callbacks {
* @param callbacks a pointer to the user's callback settings * @param callbacks a pointer to the user's callback settings
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks); GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks);
/** /**
* Get the statistics structure that is filled in by the fetch operation. * Get the statistics structure that is filled in by the fetch operation.
......
...@@ -1119,7 +1119,7 @@ static void checkout_data_clear(checkout_data *data) ...@@ -1119,7 +1119,7 @@ static void checkout_data_clear(checkout_data *data)
static int checkout_data_init( static int checkout_data_init(
checkout_data *data, checkout_data *data,
git_iterator *target, git_iterator *target,
git_checkout_opts *proposed) const git_checkout_opts *proposed)
{ {
int error = 0; int error = 0;
git_repository *repo = git_iterator_owner(target); git_repository *repo = git_iterator_owner(target);
...@@ -1229,7 +1229,7 @@ cleanup: ...@@ -1229,7 +1229,7 @@ cleanup:
int git_checkout_iterator( int git_checkout_iterator(
git_iterator *target, git_iterator *target,
git_checkout_opts *opts) const git_checkout_opts *opts)
{ {
int error = 0; int error = 0;
git_iterator *baseline = NULL, *workdir = NULL; git_iterator *baseline = NULL, *workdir = NULL;
...@@ -1404,7 +1404,7 @@ int git_checkout_tree( ...@@ -1404,7 +1404,7 @@ int git_checkout_tree(
int git_checkout_head( int git_checkout_head(
git_repository *repo, git_repository *repo,
git_checkout_opts *opts) const git_checkout_opts *opts)
{ {
int error; int error;
git_tree *head = NULL; git_tree *head = NULL;
......
...@@ -19,6 +19,6 @@ ...@@ -19,6 +19,6 @@
*/ */
extern int git_checkout_iterator( extern int git_checkout_iterator(
git_iterator *target, git_iterator *target,
git_checkout_opts *opts); const git_checkout_opts *opts);
#endif #endif
...@@ -270,23 +270,23 @@ cleanup: ...@@ -270,23 +270,23 @@ cleanup:
static int update_head_to_branch( static int update_head_to_branch(
git_repository *repo, git_repository *repo,
const git_clone_options *options) const char *remote_name,
const char *branch)
{ {
int retcode; int retcode;
git_buf remote_branch_name = GIT_BUF_INIT; git_buf remote_branch_name = GIT_BUF_INIT;
git_reference* remote_ref = NULL; git_reference* remote_ref = NULL;
assert(options->checkout_branch); assert(remote_name && branch);
if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s", if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s",
options->remote_name, options->checkout_branch)) < 0 ) remote_name, branch)) < 0 )
goto cleanup; goto cleanup;
if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0) if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0)
goto cleanup; goto cleanup;
retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch);
options->checkout_branch);
cleanup: cleanup:
git_reference_free(remote_ref); git_reference_free(remote_ref);
...@@ -306,41 +306,18 @@ static int create_and_configure_origin( ...@@ -306,41 +306,18 @@ static int create_and_configure_origin(
{ {
int error; int error;
git_remote *origin = NULL; git_remote *origin = NULL;
const char *name;
if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) name = options->remote_name ? options->remote_name : "origin";
goto on_error; if ((error = git_remote_create(&origin, repo, name, url)) < 0)
git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb,
options->cred_acquire_payload);
git_remote_set_autotag(origin, options->remote_autotag);
/*
* Don't write FETCH_HEAD, we'll check out the remote tracking
* branch ourselves based on the server's default.
*/
git_remote_set_update_fetchhead(origin, 0);
if (options->remote_callbacks &&
(error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0)
goto on_error; goto on_error;
if (options->fetch_spec) { if (options->ignore_cert_errors)
git_remote_clear_refspecs(origin); git_remote_check_cert(origin, 0);
if ((error = git_remote_add_fetch(origin, options->fetch_spec)) < 0)
goto on_error;
}
if (options->push_spec &&
(error = git_remote_add_push(origin, options->push_spec)) < 0)
goto on_error;
if (options->pushurl && if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0)
(error = git_remote_set_pushurl(origin, options->pushurl)) < 0)
goto on_error; goto on_error;
if (options->transport_flags == GIT_TRANSPORTFLAGS_NO_CHECK_CERT) {
git_remote_check_cert(origin, 0);
}
if ((error = git_remote_save(origin)) < 0) if ((error = git_remote_save(origin)) < 0)
goto on_error; goto on_error;
...@@ -352,59 +329,10 @@ on_error: ...@@ -352,59 +329,10 @@ on_error:
return error; return error;
} }
static int setup_remotes_and_fetch(
git_repository *repo,
const char *url,
const git_clone_options *options)
{
int retcode = GIT_ERROR;
git_remote *origin = NULL;
/* Construct an origin remote */
if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0)
goto on_error;
git_remote_set_update_fetchhead(origin, 0);
/* If the download_tags value has not been specified, then make sure to
* download tags as well. It is set here because we want to download tags
* on the initial clone, but do not want to persist the value in the
* configuration file.
*/
if (origin->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO &&
((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0))
goto on_error;
/* Connect and download everything */
if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0)
goto on_error;
if ((retcode = git_remote_download(origin, options->fetch_progress_cb,
options->fetch_progress_payload)) < 0)
goto on_error;
/* Create "origin/foo" branches for all remote branches */
if ((retcode = git_remote_update_tips(origin)) < 0)
goto on_error;
/* Point HEAD to the requested branch */
if (options->checkout_branch)
retcode = update_head_to_branch(repo, options);
/* Point HEAD to the same ref as the remote's head */
else
retcode = update_head_to_remote(repo, origin);
on_error:
git_remote_free(origin);
return retcode;
}
static bool should_checkout( static bool should_checkout(
git_repository *repo, git_repository *repo,
bool is_bare, bool is_bare,
git_checkout_opts *opts) const git_checkout_opts *opts)
{ {
if (is_bare) if (is_bare)
return false; return false;
...@@ -418,39 +346,63 @@ static bool should_checkout( ...@@ -418,39 +346,63 @@ static bool should_checkout(
return !git_repository_head_unborn(repo); return !git_repository_head_unborn(repo);
} }
static void normalize_options(git_clone_options *dst, const git_clone_options *src, git_repository_init_options *initOptions) int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch)
{ {
git_clone_options default_options = GIT_CLONE_OPTIONS_INIT; int error = 0, old_fetchhead;
if (!src) src = &default_options; size_t nspecs;
*dst = *src; assert(repo && remote);
/* Provide defaults for null pointers */ if (!git_repository_is_empty(repo)) {
if (!dst->remote_name) dst->remote_name = "origin"; giterr_set(GITERR_INVALID, "the repository is not empty");
if (!dst->init_options) { return -1;
dst->init_options = initOptions;
initOptions->flags = GIT_REPOSITORY_INIT_MKPATH;
if (dst->bare)
initOptions->flags |= GIT_REPOSITORY_INIT_BARE;
} }
if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0)
return error;
old_fetchhead = git_remote_update_fetchhead(remote);
git_remote_set_update_fetchhead(remote, 0);
if ((error = git_remote_fetch(remote)) < 0)
goto cleanup;
if (branch)
error = update_head_to_branch(repo, git_remote_name(remote), branch);
/* Point HEAD to the same ref as the remote's head */
else
error = update_head_to_remote(repo, remote);
if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts))
error = git_checkout_head(repo, co_opts);
cleanup:
git_remote_set_update_fetchhead(remote, old_fetchhead);
/* Remove the tags refspec */
nspecs = git_remote_refspec_count(remote);
git_remote_remove_refspec(remote, nspecs);
return error;
} }
int git_clone( int git_clone(
git_repository **out, git_repository **out,
const char *url, const char *url,
const char *local_path, const char *local_path,
const git_clone_options *options) const git_clone_options *_options)
{ {
int retcode = GIT_ERROR; int retcode = GIT_ERROR;
git_repository *repo = NULL; git_repository *repo = NULL;
git_clone_options normOptions; git_remote *origin;
git_clone_options options = GIT_CLONE_OPTIONS_INIT;
int remove_directory_on_failure = 0; int remove_directory_on_failure = 0;
git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT;
assert(out && url && local_path); assert(out && url && local_path);
normalize_options(&normOptions, options, &initOptions); if (_options)
GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); memcpy(&options, _options, sizeof(git_clone_options));
GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
/* Only clone to a new directory or an empty directory */ /* Only clone to a new directory or an empty directory */
if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) {
...@@ -462,24 +414,27 @@ int git_clone( ...@@ -462,24 +414,27 @@ int git_clone(
/* Only remove the directory on failure if we create it */ /* Only remove the directory on failure if we create it */
remove_directory_on_failure = !git_path_exists(local_path); remove_directory_on_failure = !git_path_exists(local_path);
if (!(retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options))) { if ((retcode = git_repository_init(&repo, local_path, options.bare)) < 0)
if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { return retcode;
/* Failed to fetch; clean up */
git_repository_free(repo);
if (remove_directory_on_failure) if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0)
git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); goto cleanup;
else
git_futils_cleanupdir_r(local_path);
} else { retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch);
*out = repo; git_remote_free(origin);
retcode = 0;
} if (retcode < 0)
} goto cleanup;
if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts)) *out = repo;
retcode = git_checkout_head(*out, &normOptions.checkout_opts); return 0;
cleanup:
git_repository_free(repo);
if (remove_directory_on_failure)
git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES);
else
git_futils_cleanupdir_r(local_path);
return retcode; return retcode;
} }
...@@ -119,15 +119,13 @@ int git_fetch_negotiate(git_remote *remote) ...@@ -119,15 +119,13 @@ int git_fetch_negotiate(git_remote *remote)
remote->refs.length); remote->refs.length);
} }
int git_fetch_download_pack( int git_fetch_download_pack(git_remote *remote)
git_remote *remote,
git_transfer_progress_callback progress_cb,
void *progress_payload)
{ {
git_transport *t = remote->transport; git_transport *t = remote->transport;
if(!remote->need_pack) if(!remote->need_pack)
return 0; return 0;
return t->download_pack(t, remote->repo, &remote->stats, progress_cb, progress_payload); return t->download_pack(t, remote->repo, &remote->stats,
remote->callbacks.transfer_progress, remote->callbacks.payload);
} }
...@@ -11,10 +11,7 @@ ...@@ -11,10 +11,7 @@
int git_fetch_negotiate(git_remote *remote); int git_fetch_negotiate(git_remote *remote);
int git_fetch_download_pack( int git_fetch_download_pack(git_remote *remote);
git_remote *remote,
git_transfer_progress_callback progress_cb,
void *progress_payload);
int git_fetch__download_pack( int git_fetch__download_pack(
git_transport *t, git_transport *t,
......
...@@ -591,7 +591,7 @@ int git_remote_connect(git_remote *remote, git_direction direction) ...@@ -591,7 +591,7 @@ int git_remote_connect(git_remote *remote, git_direction direction)
if (!remote->check_cert) if (!remote->check_cert)
flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT; flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
if (t->connect(t, url, remote->cred_acquire_cb, remote->cred_acquire_payload, direction, flags) < 0) if (t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags) < 0)
goto on_error; goto on_error;
remote->transport = t; remote->transport = t;
...@@ -742,10 +742,7 @@ static int remote_head_cmp(const void *_a, const void *_b) ...@@ -742,10 +742,7 @@ static int remote_head_cmp(const void *_a, const void *_b)
return git__strcmp_cb(a->name, b->name); return git__strcmp_cb(a->name, b->name);
} }
int git_remote_download( int git_remote_download(git_remote *remote)
git_remote *remote,
git_transfer_progress_callback progress_cb,
void *progress_payload)
{ {
int error; int error;
git_vector refs; git_vector refs;
...@@ -767,7 +764,25 @@ int git_remote_download( ...@@ -767,7 +764,25 @@ int git_remote_download(
if ((error = git_fetch_negotiate(remote)) < 0) if ((error = git_fetch_negotiate(remote)) < 0)
return error; return error;
return git_fetch_download_pack(remote, progress_cb, progress_payload); return git_fetch_download_pack(remote);
}
int git_remote_fetch(git_remote *remote)
{
int error;
/* Connect and download everything */
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) < 0)
return error;
if ((error = git_remote_download(remote)) < 0)
return error;
/* We don't need to be connected anymore */
git_remote_disconnect(remote);
/* Create "remote/foo" branches for all remote branches */
return git_remote_update_tips(remote);
} }
static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
...@@ -1138,7 +1153,7 @@ void git_remote_check_cert(git_remote *remote, int check) ...@@ -1138,7 +1153,7 @@ void git_remote_check_cert(git_remote *remote, int check)
remote->check_cert = check; remote->check_cert = check;
} }
int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks) int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks)
{ {
assert(remote && callbacks); assert(remote && callbacks);
...@@ -1147,7 +1162,7 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks ...@@ -1147,7 +1162,7 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks
memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks)); memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
if (remote->transport && remote->transport->set_callbacks) if (remote->transport && remote->transport->set_callbacks)
remote->transport->set_callbacks(remote->transport, return remote->transport->set_callbacks(remote->transport,
remote->callbacks.progress, remote->callbacks.progress,
NULL, NULL,
remote->callbacks.payload); remote->callbacks.payload);
...@@ -1155,17 +1170,6 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks ...@@ -1155,17 +1170,6 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks
return 0; return 0;
} }
void git_remote_set_cred_acquire_cb(
git_remote *remote,
git_cred_acquire_cb cred_acquire_cb,
void *payload)
{
assert(remote);
remote->cred_acquire_cb = cred_acquire_cb;
remote->cred_acquire_payload = payload;
}
int git_remote_set_transport(git_remote *remote, git_transport *transport) int git_remote_set_transport(git_remote *remote, git_transport *transport)
{ {
assert(remote && transport); assert(remote && transport);
......
...@@ -21,8 +21,6 @@ struct git_remote { ...@@ -21,8 +21,6 @@ struct git_remote {
char *pushurl; char *pushurl;
git_vector refs; git_vector refs;
git_vector refspecs; git_vector refspecs;
git_cred_acquire_cb cred_acquire_cb;
void *cred_acquire_payload;
git_transport *transport; git_transport *transport;
git_repository *repo; git_repository *repo;
git_remote_callbacks callbacks; git_remote_callbacks callbacks;
......
...@@ -434,7 +434,7 @@ static int local_push( ...@@ -434,7 +434,7 @@ static int local_push(
if (!url || t->parent.close(&t->parent) < 0 || if (!url || t->parent.close(&t->parent) < 0 ||
t->parent.connect(&t->parent, url, t->parent.connect(&t->parent, url,
push->remote->cred_acquire_cb, NULL, GIT_DIRECTION_PUSH, flags)) push->remote->callbacks.credentials, NULL, GIT_DIRECTION_PUSH, flags))
goto on_error; goto on_error;
} }
......
...@@ -10,12 +10,14 @@ static git_repository *g_repo_cloned; ...@@ -10,12 +10,14 @@ static git_repository *g_repo_cloned;
void test_clone_empty__initialize(void) void test_clone_empty__initialize(void)
{ {
git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); git_repository *sandbox = cl_git_sandbox_init("empty_bare.git");
git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT;
cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt");
g_repo = NULL; g_repo = NULL;
memset(&g_options, 0, sizeof(git_clone_options)); memset(&g_options, 0, sizeof(git_clone_options));
g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.version = GIT_CLONE_OPTIONS_VERSION;
g_options.remote_callbacks = dummy_callbacks;
} }
void test_clone_empty__cleanup(void) void test_clone_empty__cleanup(void)
......
...@@ -15,6 +15,7 @@ static git_remote* g_remote; ...@@ -15,6 +15,7 @@ static git_remote* g_remote;
void test_clone_nonetwork__initialize(void) void test_clone_nonetwork__initialize(void)
{ {
git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT;
git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT;
g_repo = NULL; g_repo = NULL;
...@@ -22,6 +23,7 @@ void test_clone_nonetwork__initialize(void) ...@@ -22,6 +23,7 @@ void test_clone_nonetwork__initialize(void)
g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.version = GIT_CLONE_OPTIONS_VERSION;
g_options.checkout_opts = dummy_opts; g_options.checkout_opts = dummy_opts;
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
g_options.remote_callbacks = dummy_callbacks;
} }
void test_clone_nonetwork__cleanup(void) void test_clone_nonetwork__cleanup(void)
...@@ -124,84 +126,17 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo ...@@ -124,84 +126,17 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo
void test_clone_nonetwork__custom_origin_name(void) void test_clone_nonetwork__custom_origin_name(void)
{ {
g_options.remote_name = "my_origin"; g_options.remote_name = "my_origin";
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin"));
} }
void test_clone_nonetwork__custom_push_url(void) void test_clone_nonetwork__defaults(void)
{ {
const char *url = "http://example.com"; cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL));
cl_assert(g_repo);
g_options.pushurl = url;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_remote_load(&g_remote, g_repo, "origin"));
cl_assert_equal_s(url, git_remote_pushurl(g_remote));
}
void test_clone_nonetwork__custom_fetch_spec(void)
{
const git_refspec *actual_fs;
const char *spec = "+refs/heads/master:refs/heads/foo";
g_options.fetch_spec = spec;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_remote_load(&g_remote, g_repo, "origin"));
actual_fs = git_remote_get_refspec(g_remote, 0);
cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs));
cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs));
cl_git_pass(git_reference_lookup(&g_ref, g_repo, "refs/heads/foo"));
}
void test_clone_nonetwork__custom_push_spec(void)
{
const git_refspec *actual_fs;
const char *spec = "+refs/heads/master:refs/heads/foo";
g_options.push_spec = spec;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); cl_git_pass(git_remote_load(&g_remote, g_repo, "origin"));
actual_fs = git_remote_get_refspec(g_remote, git_remote_refspec_count(g_remote) - 1);
cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs));
cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs));
}
void test_clone_nonetwork__custom_autotag(void)
{
git_remote *origin;
git_strarray tags = {0};
g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_tag_list(&tags, g_repo));
cl_assert_equal_sz(0, tags.count);
cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_NONE, origin->download_tags);
git_strarray_free(&tags);
git_remote_free(origin);
}
void test_clone_nonetwork__custom_autotag_tags_all(void)
{
git_strarray tags = {0};
git_remote *origin;
g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
cl_git_pass(git_remote_load(&origin, g_repo, "origin"));
cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_ALL, origin->download_tags);
git_strarray_free(&tags);
git_remote_free(origin);
} }
void test_clone_nonetwork__cope_with_already_existing_directory(void) void test_clone_nonetwork__cope_with_already_existing_directory(void)
......
...@@ -25,13 +25,18 @@ void test_network_fetchlocal__complete(void) ...@@ -25,13 +25,18 @@ void test_network_fetchlocal__complete(void)
git_strarray refnames = {0}; git_strarray refnames = {0};
const char *url = cl_git_fixture_url("testrepo.git"); const char *url = cl_git_fixture_url("testrepo.git");
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
callbacks.transfer_progress = transfer_cb;
callbacks.payload = &callcount;
cl_set_cleanup(&cleanup_local_repo, "foo"); cl_set_cleanup(&cleanup_local_repo, "foo");
cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_repository_init(&repo, "foo", true));
cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); 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_connect(origin, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); cl_git_pass(git_remote_download(origin));
cl_git_pass(git_remote_update_tips(origin)); cl_git_pass(git_remote_update_tips(origin));
cl_git_pass(git_reference_list(&refnames, repo)); cl_git_pass(git_reference_list(&refnames, repo));
...@@ -56,6 +61,10 @@ void test_network_fetchlocal__partial(void) ...@@ -56,6 +61,10 @@ void test_network_fetchlocal__partial(void)
int callcount = 0; int callcount = 0;
git_strarray refnames = {0}; git_strarray refnames = {0};
const char *url; const char *url;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
callbacks.transfer_progress = transfer_cb;
callbacks.payload = &callcount;
cl_set_cleanup(&cleanup_sandbox, NULL); cl_set_cleanup(&cleanup_sandbox, NULL);
cl_git_pass(git_reference_list(&refnames, repo)); cl_git_pass(git_reference_list(&refnames, repo));
...@@ -63,8 +72,9 @@ void test_network_fetchlocal__partial(void) ...@@ -63,8 +72,9 @@ void test_network_fetchlocal__partial(void)
url = cl_git_fixture_url("testrepo.git"); url = cl_git_fixture_url("testrepo.git");
cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); 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_connect(origin, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); cl_git_pass(git_remote_download(origin));
cl_git_pass(git_remote_update_tips(origin)); cl_git_pass(git_remote_update_tips(origin));
git_strarray_free(&refnames); git_strarray_free(&refnames);
......
...@@ -123,7 +123,7 @@ void test_network_remote_local__shorthand_fetch_refspec0(void) ...@@ -123,7 +123,7 @@ void test_network_remote_local__shorthand_fetch_refspec0(void)
cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec));
cl_git_pass(git_remote_add_fetch(remote, refspec2)); cl_git_pass(git_remote_add_fetch(remote, refspec2));
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master"));
...@@ -145,7 +145,7 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) ...@@ -145,7 +145,7 @@ void test_network_remote_local__shorthand_fetch_refspec1(void)
cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec));
cl_git_pass(git_remote_add_fetch(remote, refspec2)); cl_git_pass(git_remote_add_fetch(remote, refspec2));
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master"));
...@@ -160,7 +160,7 @@ void test_network_remote_local__tagopt(void) ...@@ -160,7 +160,7 @@ void test_network_remote_local__tagopt(void)
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL);
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
...@@ -179,7 +179,7 @@ void test_network_remote_local__push_to_bare_remote(void) ...@@ -179,7 +179,7 @@ void test_network_remote_local__push_to_bare_remote(void)
/* Get some commits */ /* Get some commits */
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
cl_git_pass(git_remote_add_fetch(remote, "master:master")); cl_git_pass(git_remote_add_fetch(remote, "master:master"));
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
git_remote_disconnect(remote); git_remote_disconnect(remote);
...@@ -215,7 +215,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) ...@@ -215,7 +215,7 @@ void test_network_remote_local__push_to_non_bare_remote(void)
/* Get some commits */ /* Get some commits */
connect_to_local_repository(cl_fixture("testrepo.git")); connect_to_local_repository(cl_fixture("testrepo.git"));
cl_git_pass(git_remote_add_fetch(remote, "master:master")); cl_git_pass(git_remote_add_fetch(remote, "master:master"));
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
git_remote_disconnect(remote); git_remote_disconnect(remote);
......
...@@ -18,6 +18,7 @@ static git_clone_options g_options; ...@@ -18,6 +18,7 @@ static git_clone_options g_options;
void test_online_clone__initialize(void) void test_online_clone__initialize(void)
{ {
git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT;
git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT;
g_repo = NULL; g_repo = NULL;
...@@ -25,6 +26,7 @@ void test_online_clone__initialize(void) ...@@ -25,6 +26,7 @@ void test_online_clone__initialize(void)
g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.version = GIT_CLONE_OPTIONS_VERSION;
g_options.checkout_opts = dummy_opts; g_options.checkout_opts = dummy_opts;
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
g_options.remote_callbacks = dummy_callbacks;
} }
void test_online_clone__cleanup(void) void test_online_clone__cleanup(void)
...@@ -103,8 +105,8 @@ void test_online_clone__can_checkout_a_cloned_repo(void) ...@@ -103,8 +105,8 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_cb = &checkout_progress;
g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called;
g_options.fetch_progress_cb = &fetch_progress; g_options.remote_callbacks.transfer_progress = &fetch_progress;
g_options.fetch_progress_payload = &fetch_progress_cb_was_called; g_options.remote_callbacks.payload = &fetch_progress_cb_was_called;
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
...@@ -122,6 +124,45 @@ void test_online_clone__can_checkout_a_cloned_repo(void) ...@@ -122,6 +124,45 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
git_buf_free(&path); git_buf_free(&path);
} }
void test_online_clone__clone_into(void)
{
git_buf path = GIT_BUF_INIT;
git_remote *remote;
git_reference *head;
git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
bool checkout_progress_cb_was_called = false,
fetch_progress_cb_was_called = false;
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
checkout_opts.progress_cb = &checkout_progress;
checkout_opts.progress_payload = &checkout_progress_cb_was_called;
cl_git_pass(git_repository_init(&g_repo, "./foo", false));
cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL));
callbacks.transfer_progress = &fetch_progress;
callbacks.payload = &fetch_progress_cb_was_called;
git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL));
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt"));
cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path)));
cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD"));
cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head));
cl_assert_equal_i(true, checkout_progress_cb_was_called);
cl_assert_equal_i(true, fetch_progress_cb_was_called);
git_remote_free(remote);
git_reference_free(head);
git_buf_free(&path);
}
static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload)
{ {
int *callcount = (int*)payload; int *callcount = (int*)payload;
...@@ -132,12 +173,10 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, ...@@ -132,12 +173,10 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b,
void test_online_clone__custom_remote_callbacks(void) void test_online_clone__custom_remote_callbacks(void)
{ {
git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT;
int callcount = 0; int callcount = 0;
g_options.remote_callbacks = &remote_callbacks; g_options.remote_callbacks.update_tips = update_tips;
remote_callbacks.update_tips = update_tips; g_options.remote_callbacks.payload = &callcount;
remote_callbacks.payload = &callcount;
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
cl_assert(callcount > 0); cl_assert(callcount > 0);
...@@ -154,8 +193,8 @@ void test_online_clone__credentials(void) ...@@ -154,8 +193,8 @@ void test_online_clone__credentials(void)
if (!remote_url) return; if (!remote_url) return;
g_options.cred_acquire_cb = git_cred_userpass; g_options.remote_callbacks.credentials = git_cred_userpass;
g_options.cred_acquire_payload = &user_pass; g_options.remote_callbacks.payload = &user_pass;
cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options));
git_repository_free(g_repo); g_repo = NULL; git_repository_free(g_repo); g_repo = NULL;
...@@ -168,8 +207,8 @@ void test_online_clone__bitbucket_style(void) ...@@ -168,8 +207,8 @@ void test_online_clone__bitbucket_style(void)
"libgit2", "libgit2" "libgit2", "libgit2"
}; };
g_options.cred_acquire_cb = git_cred_userpass; g_options.remote_callbacks.credentials = git_cred_userpass;
g_options.cred_acquire_payload = &user_pass; g_options.remote_callbacks.payload = &user_pass;
cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options));
git_repository_free(g_repo); g_repo = NULL; git_repository_free(g_repo); g_repo = NULL;
...@@ -199,6 +238,13 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) ...@@ -199,6 +238,13 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload)
void test_online_clone__can_cancel(void) void test_online_clone__can_cancel(void)
{ {
g_options.fetch_progress_cb = cancel_at_half; g_options.remote_callbacks.transfer_progress = cancel_at_half;
cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER);
} }
...@@ -38,14 +38,16 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) ...@@ -38,14 +38,16 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
size_t bytes_received = 0; size_t bytes_received = 0;
callbacks.transfer_progress = progress;
callbacks.update_tips = update_tips; callbacks.update_tips = update_tips;
callbacks.payload = &bytes_received;
counter = 0; counter = 0;
cl_git_pass(git_remote_create(&remote, _repo, "test", url)); cl_git_pass(git_remote_create(&remote, _repo, "test", url));
git_remote_set_callbacks(remote, &callbacks); git_remote_set_callbacks(remote, &callbacks);
git_remote_set_autotag(remote, flag); git_remote_set_autotag(remote, flag);
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_download(remote, progress, &bytes_received)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
git_remote_disconnect(remote); git_remote_disconnect(remote);
cl_assert_equal_i(counter, n); cl_assert_equal_i(counter, n);
...@@ -93,6 +95,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date ...@@ -93,6 +95,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
git_repository *_repository; git_repository *_repository;
bool invoked = false; bool invoked = false;
git_remote *remote; git_remote *remote;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.bare = true; opts.bare = true;
...@@ -107,7 +110,10 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date ...@@ -107,7 +110,10 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
cl_assert_equal_i(false, invoked); cl_assert_equal_i(false, invoked);
cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked)); callbacks.transfer_progress = &transferProgressCallback;
callbacks.payload = &invoked;
git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_remote_download(remote));
cl_assert_equal_i(false, invoked); cl_assert_equal_i(false, invoked);
...@@ -131,11 +137,17 @@ void test_online_fetch__can_cancel(void) ...@@ -131,11 +137,17 @@ void test_online_fetch__can_cancel(void)
{ {
git_remote *remote; git_remote *remote;
size_t bytes_received = 0; size_t bytes_received = 0;
git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
cl_git_pass(git_remote_create(&remote, _repo, "test", cl_git_pass(git_remote_create(&remote, _repo, "test",
"http://github.com/libgit2/TestGitRepository.git")); "http://github.com/libgit2/TestGitRepository.git"));
callbacks.transfer_progress = cancel_at_half;
callbacks.payload = &bytes_received;
git_remote_set_callbacks(remote, &callbacks);
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
cl_git_fail_with(git_remote_download(remote, cancel_at_half, &bytes_received), GIT_EUSER); cl_git_fail_with(git_remote_download(remote), GIT_EUSER);
git_remote_disconnect(remote); git_remote_disconnect(remote);
git_remote_free(remote); git_remote_free(remote);
} }
......
...@@ -12,10 +12,12 @@ static git_clone_options g_options; ...@@ -12,10 +12,12 @@ static git_clone_options g_options;
void test_online_fetchhead__initialize(void) void test_online_fetchhead__initialize(void)
{ {
git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT;
g_repo = NULL; g_repo = NULL;
memset(&g_options, 0, sizeof(git_clone_options)); memset(&g_options, 0, sizeof(git_clone_options));
g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.version = GIT_CLONE_OPTIONS_VERSION;
g_options.remote_callbacks = dummy_callbacks;
} }
void test_online_fetchhead__cleanup(void) void test_online_fetchhead__cleanup(void)
...@@ -48,7 +50,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet ...@@ -48,7 +50,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
} }
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_download(remote, NULL, NULL)); cl_git_pass(git_remote_download(remote));
cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_remote_update_tips(remote));
git_remote_disconnect(remote); git_remote_disconnect(remote);
git_remote_free(remote); git_remote_free(remote);
......
...@@ -17,6 +17,8 @@ static char *_remote_url; ...@@ -17,6 +17,8 @@ static char *_remote_url;
static char *_remote_user; static char *_remote_user;
static char *_remote_pass; static char *_remote_pass;
static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *);
static git_remote *_remote; static git_remote *_remote;
static bool _cred_acquire_called; static bool _cred_acquire_called;
static record_callbacks_data _record_cbs_data = {{ 0 }}; static record_callbacks_data _record_cbs_data = {{ 0 }};
...@@ -294,7 +296,6 @@ void test_online_push__initialize(void) ...@@ -294,7 +296,6 @@ void test_online_push__initialize(void)
if (_remote_url) { if (_remote_url) {
cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url));
git_remote_set_cred_acquire_cb(_remote, cred_acquire_cb, &_cred_acquire_called);
record_callbacks_data_clear(&_record_cbs_data); record_callbacks_data_clear(&_record_cbs_data);
git_remote_set_callbacks(_remote, &_record_cbs); git_remote_set_callbacks(_remote, &_record_cbs);
...@@ -326,7 +327,7 @@ void test_online_push__initialize(void) ...@@ -326,7 +327,7 @@ void test_online_push__initialize(void)
/* Now that we've deleted everything, fetch from the remote */ /* 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_connect(_remote, GIT_DIRECTION_FETCH));
cl_git_pass(git_remote_download(_remote, NULL, NULL)); cl_git_pass(git_remote_download(_remote));
cl_git_pass(git_remote_update_tips(_remote)); cl_git_pass(git_remote_update_tips(_remote));
git_remote_disconnect(_remote); git_remote_disconnect(_remote);
} else } else
......
...@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; ...@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance * @param data pointer to a record_callbacks_data instance
*/ */
#define RECORD_CALLBACKS_INIT(data) \ #define RECORD_CALLBACKS_INIT(data) \
{ GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, record_update_tips_cb, data } { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data }
typedef struct { typedef struct {
char *name; char *name;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment