Commit b5237767 by Edward Thomson

remote: refactor update tips function

Move the functionality to update an individual tip out of the loop;
although the update tip function remains rather gnarly, at least the
outer function is a bit less onerous.
parent b1e83cca
...@@ -1738,141 +1738,153 @@ static int update_ref( ...@@ -1738,141 +1738,153 @@ static int update_ref(
return 0; return 0;
} }
static int update_tips_for_spec( static int update_one_tip(
git_vector *update_heads,
git_remote *remote, git_remote *remote,
const git_remote_callbacks *callbacks,
int update_fetchhead,
git_remote_autotag_option_t tagopt,
git_refspec *spec, git_refspec *spec,
git_vector *refs, git_remote_head *head,
const char *log_message) git_refspec *tagspec,
git_remote_autotag_option_t tagopt,
const char *log_message,
const git_remote_callbacks *callbacks)
{ {
int error = 0, autotag, valid; git_odb *odb;
unsigned int i = 0;
git_str refname = GIT_STR_INIT; git_str refname = GIT_STR_INIT;
git_reference *ref = NULL;
bool autotag = false;
git_oid old; git_oid old;
git_odb *odb; int valid;
git_remote_head *head; int error;
git_reference *ref;
git_refspec tagspec;
git_vector update_heads;
GIT_ASSERT_ARG(remote);
if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
return -1;
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
return -1;
/* Make a copy of the transport's refs */
if (git_vector_init(&update_heads, 16, NULL) < 0)
return -1;
for (; i < refs->length; ++i) { if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
head = git_vector_get(refs, i); goto done;
autotag = 0;
git_str_clear(&refname);
/* Ignore malformed ref names (which also saves us from tag^{} */ /* Ignore malformed ref names (which also saves us from tag^{} */
if (git_reference_name_is_valid(&valid, head->name) < 0) if ((error = git_reference_name_is_valid(&valid, head->name)) < 0)
goto on_error; goto done;
if (!valid) if (!valid)
continue; goto done;
/* If we have a tag, see if the auto-follow rules say to update it */ /* If we have a tag, see if the auto-follow rules say to update it */
if (git_refspec_src_matches(&tagspec, head->name)) { if (git_refspec_src_matches(tagspec, head->name)) {
if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
autotag = 1; autotag = true;
git_str_clear(&refname); if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
if (git_str_puts(&refname, head->name) < 0) if (git_str_puts(&refname, head->name) < 0)
goto on_error; goto done;
} }
} }
/* If we didn't want to auto-follow the tag, check if the refspec matches */ /* If we didn't want to auto-follow the tag, check if the refspec matches */
if (!autotag && git_refspec_src_matches(spec, head->name)) { if (!autotag && git_refspec_src_matches(spec, head->name)) {
if (spec->dst) { if (spec->dst) {
if (git_refspec__transform(&refname, spec, head->name) < 0) if ((error = git_refspec__transform(&refname, spec, head->name)) < 0)
goto on_error; goto done;
} else { } else {
/* /*
* no rhs mans store it in FETCH_HEAD, even if we don't * no rhs means store it in FETCH_HEAD, even if we don't
update anything else. * update anything else.
*/ */
if ((error = git_vector_insert(&update_heads, head)) < 0) error = git_vector_insert(update_heads, head);
goto on_error; goto done;
continue;
} }
} }
/* If we still don't have a refname, we don't want it */ /* If we still don't have a refname, we don't want it */
if (git_str_len(&refname) == 0) { if (git_str_len(&refname) == 0)
continue; goto done;
}
/* In autotag mode, only create tags for objects already in db */ /* In autotag mode, only create tags for objects already in db */
if (autotag && !git_odb_exists(odb, &head->oid)) if (autotag && !git_odb_exists(odb, &head->oid))
continue; goto done;
if (!autotag && git_vector_insert(&update_heads, head) < 0) if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
goto on_error; goto done;
error = git_reference_name_to_id(&old, remote->repo, refname.ptr); error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
if (error < 0 && error != GIT_ENOTFOUND) if (error < 0 && error != GIT_ENOTFOUND)
goto on_error; goto done;
if (!(error || error == GIT_ENOTFOUND) if (!spec->force &&
&& !spec->force !git_graph_descendant_of(remote->repo, &head->oid, &old)) {
&& !git_graph_descendant_of(remote->repo, &head->oid, &old)) error = 0;
continue; goto done;
}
if (error == GIT_ENOTFOUND) { if (error == GIT_ENOTFOUND) {
memset(&old, 0, GIT_OID_RAWSZ); memset(&old, 0, GIT_OID_RAWSZ);
error = 0;
if (autotag && git_vector_insert(&update_heads, head) < 0) if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
goto on_error; goto done;
} }
if (!git_oid__cmp(&old, &head->oid)) if (!git_oid__cmp(&old, &head->oid))
continue; goto done;
/* In autotag mode, don't overwrite any locally-existing tags */ /* In autotag mode, don't overwrite any locally-existing tags */
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag, error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
log_message); log_message);
if (error < 0) {
if (error == GIT_EEXISTS) if (error == GIT_EEXISTS)
continue; error = 0;
if (error < 0) goto done;
goto on_error; }
if (callbacks && callbacks->update_tips != NULL &&
callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
git_error_set_after_callback_function(error, "git_remote_fetch");
done:
git_reference_free(ref); git_reference_free(ref);
return error;
}
if (callbacks && callbacks->update_tips != NULL) { static int update_tips_for_spec(
if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0) 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)
{
git_refspec tagspec;
git_remote_head *head;
git_vector update_heads;
int error = 0;
size_t i;
GIT_ASSERT_ARG(remote);
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
return -1;
/* Make a copy of the transport's refs */
if (git_vector_init(&update_heads, 16, NULL) < 0)
return -1;
git_vector_foreach(refs, i, head) {
if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0)
goto on_error; goto on_error;
} }
}
if (update_fetchhead && if (update_fetchhead &&
(error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0) (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
goto on_error; goto on_error;
git_vector_free(&update_heads);
git_refspec__dispose(&tagspec); git_refspec__dispose(&tagspec);
git_str_dispose(&refname); git_vector_free(&update_heads);
return 0; return 0;
on_error: on_error:
git_vector_free(&update_heads);
git_refspec__dispose(&tagspec); git_refspec__dispose(&tagspec);
git_str_dispose(&refname); git_vector_free(&update_heads);
return -1; return -1;
} }
...@@ -1938,8 +1950,11 @@ static int next_head(const git_remote *remote, git_vector *refs, ...@@ -1938,8 +1950,11 @@ static int next_head(const git_remote *remote, git_vector *refs,
return GIT_ITEROVER; return GIT_ITEROVER;
} }
static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks, static int opportunistic_updates(
git_vector *refs, const char *msg) const git_remote *remote,
const git_remote_callbacks *callbacks,
git_vector *refs,
const char *msg)
{ {
size_t i, j, k; size_t i, j, k;
git_refspec *spec; git_refspec *spec;
...@@ -1949,6 +1964,7 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call ...@@ -1949,6 +1964,7 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
i = j = k = 0; i = j = k = 0;
/* Handle refspecs matching remote heads */
while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) { while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
/* /*
* If we got here, there is a refspec which was used * If we got here, there is a refspec which was used
...@@ -1964,7 +1980,9 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call ...@@ -1964,7 +1980,9 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
goto cleanup; goto cleanup;
} }
if (error == GIT_ITEROVER) if (error != GIT_ITEROVER)
goto cleanup;
error = 0; error = 0;
cleanup: cleanup:
......
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