Unverified Commit 45fd9ed7 by Edward Thomson Committed by GitHub

Merge pull request #6645 from libgit2/ethomson/report_unchanged_tips

remote: optionally report unchanged tips
parents a6205fa5 95e517be
......@@ -77,6 +77,17 @@ typedef enum {
} git_remote_create_flags;
/**
* How to handle reference updates.
*/
typedef enum {
/* Write the fetch results to FETCH_HEAD. */
GIT_REMOTE_UPDATE_FETCHHEAD = (1 << 0),
/* Report unchanged tips in the update_tips callback. */
GIT_REMOTE_UPDATE_REPORT_UNCHANGED = (1 << 1)
} git_remote_update_flags;
/**
* Remote creation options structure
*
* Initialize with `GIT_REMOTE_CREATE_OPTIONS_INIT`. Alternatively, you can
......@@ -733,10 +744,10 @@ typedef struct {
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.
* How to handle reference updates; a combination of
* `git_remote_update_flags`.
*/
int update_fetchhead;
unsigned int update_flags;
/**
* Determines how to behave regarding tags on the remote, such
......@@ -775,8 +786,13 @@ typedef struct {
} git_fetch_options;
#define GIT_FETCH_OPTIONS_VERSION 1
#define GIT_FETCH_OPTIONS_INIT { GIT_FETCH_OPTIONS_VERSION, GIT_REMOTE_CALLBACKS_INIT, GIT_FETCH_PRUNE_UNSPECIFIED, 1, \
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, GIT_PROXY_OPTIONS_INIT }
#define GIT_FETCH_OPTIONS_INIT { \
GIT_FETCH_OPTIONS_VERSION, \
GIT_REMOTE_CALLBACKS_INIT, \
GIT_FETCH_PRUNE_UNSPECIFIED, \
GIT_REMOTE_UPDATE_FETCHHEAD, \
GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, \
GIT_PROXY_OPTIONS_INIT }
/**
* Initialize git_fetch_options structure
......@@ -1001,7 +1017,7 @@ GIT_EXTERN(int) git_remote_upload(
* 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 or NULL
* @param update_fetchhead whether to write to FETCH_HEAD. Pass 1 to behave like git.
* @param update_flags the git_remote_update_flags for these tips.
* @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
......@@ -1009,7 +1025,7 @@ GIT_EXTERN(int) git_remote_upload(
GIT_EXTERN(int) git_remote_update_tips(
git_remote *remote,
const git_remote_callbacks *callbacks,
int update_fetchhead,
unsigned int update_flags,
git_remote_autotag_option_t download_tags,
const char *reflog_message);
......
......@@ -419,7 +419,7 @@ static int clone_into(
return error;
memcpy(&fetch_opts, opts, sizeof(git_fetch_options));
fetch_opts.update_fetchhead = 0;
fetch_opts.update_flags = ~GIT_REMOTE_UPDATE_FETCHHEAD;
if (!opts->depth)
fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
......
......@@ -1348,13 +1348,14 @@ int git_remote_fetch(
const git_fetch_options *opts,
const char *reflog_message)
{
int error, update_fetchhead = 1;
git_remote_autotag_option_t tagopt = remote->download_tags;
bool prune = false;
git_str reflog_msg_buf = GIT_STR_INIT;
git_remote_connect_options connect_opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
unsigned int capabilities;
git_oid_t oid_type;
unsigned int update_flags = GIT_REMOTE_UPDATE_FETCHHEAD;
int error;
GIT_ASSERT_ARG(remote);
......@@ -1371,7 +1372,7 @@ int git_remote_fetch(
return error;
if (opts) {
update_fetchhead = opts->update_fetchhead;
update_flags = opts->update_flags;
tagopt = opts->download_tags;
}
......@@ -1398,8 +1399,14 @@ int git_remote_fetch(
}
/* Create "remote/foo" branches for all remote branches */
error = git_remote_update_tips(remote, &connect_opts.callbacks, update_fetchhead, tagopt, git_str_cstr(&reflog_msg_buf));
error = git_remote_update_tips(remote,
&connect_opts.callbacks,
update_flags,
tagopt,
git_str_cstr(&reflog_msg_buf));
git_str_dispose(&reflog_msg_buf);
if (error < 0)
goto done;
......@@ -1774,6 +1781,7 @@ static int update_one_tip(
git_refspec *spec,
git_remote_head *head,
git_refspec *tagspec,
unsigned int update_flags,
git_remote_autotag_option_t tagopt,
const char *log_message,
const git_remote_callbacks *callbacks)
......@@ -1781,7 +1789,7 @@ static int update_one_tip(
git_odb *odb;
git_str refname = GIT_STR_INIT;
git_reference *ref = NULL;
bool autotag = false;
bool autotag = false, updated = false;
git_oid old;
int valid;
int error;
......@@ -1855,21 +1863,21 @@ static int update_one_tip(
goto done;
}
if (!git_oid__cmp(&old, &head->oid))
goto done;
if ((updated = !git_oid_equal(&old, &head->oid))) {
/* In autotag mode, don't overwrite any locally-existing tags */
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
log_message);
/* In autotag mode, don't overwrite any locally-existing tags */
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
log_message);
if (error < 0) {
if (error == GIT_EEXISTS)
error = 0;
if (error < 0) {
if (error == GIT_EEXISTS)
error = 0;
goto done;
goto done;
}
}
if (callbacks && callbacks->update_tips != NULL &&
(updated || (update_flags & GIT_REMOTE_UPDATE_REPORT_UNCHANGED)) &&
(error = callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload)) < 0)
git_error_set_after_callback_function(error, "git_remote_fetch");
......@@ -1882,7 +1890,7 @@ done:
static int update_tips_for_spec(
git_remote *remote,
const git_remote_callbacks *callbacks,
int update_fetchhead,
unsigned int update_flags,
git_remote_autotag_option_t tagopt,
git_refspec *spec,
git_vector *refs,
......@@ -1905,7 +1913,10 @@ static int update_tips_for_spec(
/* Update tips based on the remote heads */
git_vector_foreach(refs, i, head) {
if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0)
if (update_one_tip(&update_heads,
remote, spec, head, &tagspec,
update_flags, tagopt, log_message,
callbacks) < 0)
goto on_error;
}
......@@ -1927,7 +1938,7 @@ static int update_tips_for_spec(
goto on_error;
}
if (update_fetchhead &&
if ((update_flags & GIT_REMOTE_UPDATE_FETCHHEAD) &&
(error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
goto on_error;
......@@ -2058,11 +2069,11 @@ static int truncate_fetch_head(const char *gitdir)
}
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_remote *remote,
const git_remote_callbacks *callbacks,
unsigned int update_flags,
git_remote_autotag_option_t download_tags,
const char *reflog_message)
{
git_refspec *spec, tagspec;
git_vector refs = GIT_VECTOR_INIT;
......@@ -2091,7 +2102,7 @@ int git_remote_update_tips(
goto out;
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0)
if ((error = update_tips_for_spec(remote, callbacks, update_flags, tagopt, &tagspec, &refs, reflog_message)) < 0)
goto out;
}
......@@ -2099,7 +2110,7 @@ int git_remote_update_tips(
if (spec->push)
continue;
if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, spec, &refs, reflog_message)) < 0)
if ((error = update_tips_for_spec(remote, callbacks, update_flags, tagopt, spec, &refs, reflog_message)) < 0)
goto out;
}
......
......@@ -128,6 +128,8 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.bare = true;
counter = 0;
cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
"./fetch/lg2", &opts));
git_repository_free(_repository);
......@@ -141,11 +143,52 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
options.callbacks.transfer_progress = &transferProgressCallback;
options.callbacks.payload = &invoked;
options.callbacks.update_tips = update_tips;
cl_git_pass(git_remote_download(remote, NULL, &options));
cl_assert_equal_i(false, invoked);
cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, options.download_tags, NULL));
cl_git_pass(git_remote_update_tips(remote, &options.callbacks, GIT_REMOTE_UPDATE_FETCHHEAD, options.download_tags, NULL));
cl_assert_equal_i(0, counter);
git_remote_disconnect(remote);
git_remote_free(remote);
git_repository_free(_repository);
}
void test_online_fetch__report_unchanged_tips(void)
{
git_repository *_repository;
bool invoked = false;
git_remote *remote;
git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.bare = true;
counter = 0;
cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
"./fetch/lg2", &opts));
git_repository_free(_repository);
cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));
cl_git_pass(git_remote_lookup(&remote, _repository, "origin"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
cl_assert_equal_i(false, invoked);
options.callbacks.transfer_progress = &transferProgressCallback;
options.callbacks.payload = &invoked;
options.callbacks.update_tips = update_tips;
cl_git_pass(git_remote_download(remote, NULL, &options));
cl_assert_equal_i(false, invoked);
cl_git_pass(git_remote_update_tips(remote, &options.callbacks, GIT_REMOTE_UPDATE_REPORT_UNCHANGED, options.download_tags, NULL));
cl_assert(counter > 0);
git_remote_disconnect(remote);
git_remote_free(remote);
......
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