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_remote *remote, git_vector *update_heads,
const git_remote_callbacks *callbacks, git_remote *remote,
int update_fetchhead, git_refspec *spec,
git_remote_autotag_option_t tagopt, git_remote_head *head,
git_refspec *spec, git_refspec *tagspec,
git_vector *refs, git_remote_autotag_option_t tagopt,
const char *log_message) 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 ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
goto done;
if (git_repository_odb__weakptr(&odb, remote->repo) < 0) /* Ignore malformed ref names (which also saves us from tag^{} */
return -1; if ((error = git_reference_name_is_valid(&valid, head->name)) < 0)
goto done;
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) if (!valid)
return -1; goto done;
/* Make a copy of the transport's refs */ /* If we have a tag, see if the auto-follow rules say to update it */
if (git_vector_init(&update_heads, 16, NULL) < 0) if (git_refspec_src_matches(tagspec, head->name)) {
return -1; if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
autotag = true;
for (; i < refs->length; ++i) { if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
head = git_vector_get(refs, i); if (git_str_puts(&refname, head->name) < 0)
autotag = 0; goto done;
git_str_clear(&refname); }
}
/* Ignore malformed ref names (which also saves us from tag^{} */ /* If we didn't want to auto-follow the tag, check if the refspec matches */
if (git_reference_name_is_valid(&valid, head->name) < 0) if (!autotag && git_refspec_src_matches(spec, head->name)) {
goto on_error; if (spec->dst) {
if ((error = git_refspec__transform(&refname, spec, head->name)) < 0)
goto done;
} else {
/*
* no rhs means store it in FETCH_HEAD, even if we don't
* update anything else.
*/
error = git_vector_insert(update_heads, head);
goto done;
}
}
if (!valid) /* If we still don't have a refname, we don't want it */
continue; if (git_str_len(&refname) == 0)
goto done;
/* If we have a tag, see if the auto-follow rules say to update it */ /* In autotag mode, only create tags for objects already in db */
if (git_refspec_src_matches(&tagspec, head->name)) { if (autotag && !git_odb_exists(odb, &head->oid))
if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { goto done;
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
autotag = 1; goto done;
git_str_clear(&refname); error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
if (git_str_puts(&refname, head->name) < 0)
goto on_error;
}
}
/* If we didn't want to auto-follow the tag, check if the refspec matches */ if (error < 0 && error != GIT_ENOTFOUND)
if (!autotag && git_refspec_src_matches(spec, head->name)) { goto done;
if (spec->dst) {
if (git_refspec__transform(&refname, spec, head->name) < 0)
goto on_error;
} else {
/*
* no rhs mans store it in FETCH_HEAD, even if we don't
update anything else.
*/
if ((error = git_vector_insert(&update_heads, head)) < 0)
goto on_error;
continue; if (!spec->force &&
} !git_graph_descendant_of(remote->repo, &head->oid, &old)) {
} error = 0;
goto done;
}
/* If we still don't have a refname, we don't want it */ if (error == GIT_ENOTFOUND) {
if (git_str_len(&refname) == 0) { memset(&old, 0, GIT_OID_RAWSZ);
continue; error = 0;
}
/* In autotag mode, only create tags for objects already in db */ if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
if (autotag && !git_odb_exists(odb, &head->oid)) goto done;
continue; }
if (!autotag && git_vector_insert(&update_heads, head) < 0) if (!git_oid__cmp(&old, &head->oid))
goto on_error; goto done;
error = git_reference_name_to_id(&old, remote->repo, refname.ptr); /* In autotag mode, don't overwrite any locally-existing tags */
if (error < 0 && error != GIT_ENOTFOUND) error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
goto on_error; log_message);
if (!(error || error == GIT_ENOTFOUND) if (error < 0) {
&& !spec->force if (error == GIT_EEXISTS)
&& !git_graph_descendant_of(remote->repo, &head->oid, &old)) error = 0;
continue;
if (error == GIT_ENOTFOUND) { goto done;
memset(&old, 0, GIT_OID_RAWSZ); }
if (autotag && git_vector_insert(&update_heads, head) < 0) if (callbacks && callbacks->update_tips != NULL &&
goto on_error; callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
} git_error_set_after_callback_function(error, "git_remote_fetch");
if (!git_oid__cmp(&old, &head->oid)) done:
continue; git_reference_free(ref);
return error;
}
/* In autotag mode, don't overwrite any locally-existing tags */ static int update_tips_for_spec(
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag, git_remote *remote,
log_message); 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;
if (error == GIT_EEXISTS) GIT_ASSERT_ARG(remote);
continue;
if (error < 0) if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
goto on_error; return -1;
git_reference_free(ref); /* Make a copy of the transport's refs */
if (git_vector_init(&update_heads, 16, NULL) < 0)
return -1;
if (callbacks && callbacks->update_tips != NULL) { git_vector_foreach(refs, i, head) {
if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0) 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,8 +1980,10 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call ...@@ -1964,8 +1980,10 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
goto cleanup; goto cleanup;
} }
if (error == GIT_ITEROVER) if (error != GIT_ITEROVER)
error = 0; goto cleanup;
error = 0;
cleanup: cleanup:
git_str_dispose(&refname); git_str_dispose(&refname);
......
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