diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2022-02-05 10:43:08 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2022-02-05 11:15:27 -0500 |
commit | b523776785e542792bd22f185ed0a678ab07c872 (patch) | |
tree | 6a2615a87f2bf0ece64f77acce2abb2080583755 /src | |
parent | b1e83cca1bbc255627950b4e8d4fdb1174bf7a12 (diff) | |
download | libgit2-b523776785e542792bd22f185ed0a678ab07c872.tar.gz |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/remote.c | 218 |
1 files changed, 118 insertions, 100 deletions
diff --git a/src/remote.c b/src/remote.c index a0cb1efdb..fd470366e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1738,141 +1738,153 @@ static int update_ref( return 0; } -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) +static int update_one_tip( + git_vector *update_heads, + git_remote *remote, + git_refspec *spec, + git_remote_head *head, + git_refspec *tagspec, + git_remote_autotag_option_t tagopt, + const char *log_message, + const git_remote_callbacks *callbacks) { - int error = 0, autotag, valid; - unsigned int i = 0; + git_odb *odb; git_str refname = GIT_STR_INIT; + git_reference *ref = NULL; + bool autotag = false; git_oid old; - git_odb *odb; - git_remote_head *head; - git_reference *ref; - git_refspec tagspec; - git_vector update_heads; + int valid; + int error; - 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) - return -1; + /* Ignore malformed ref names (which also saves us from tag^{} */ + if ((error = git_reference_name_is_valid(&valid, head->name)) < 0) + goto done; - if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) - return -1; + if (!valid) + goto done; - /* Make a copy of the transport's refs */ - if (git_vector_init(&update_heads, 16, NULL) < 0) - return -1; + /* If we have a tag, see if the auto-follow rules say to update it */ + if (git_refspec_src_matches(tagspec, head->name)) { + if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) + autotag = true; - for (; i < refs->length; ++i) { - head = git_vector_get(refs, i); - autotag = 0; - git_str_clear(&refname); + if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { + if (git_str_puts(&refname, head->name) < 0) + goto done; + } + } - /* Ignore malformed ref names (which also saves us from tag^{} */ - if (git_reference_name_is_valid(&valid, head->name) < 0) - goto on_error; + /* 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 (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) - continue; + /* If we still don't have a refname, we don't want it */ + if (git_str_len(&refname) == 0) + goto done; - /* If we have a tag, see if the auto-follow rules say to update it */ - if (git_refspec_src_matches(&tagspec, head->name)) { - if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) { + /* In autotag mode, only create tags for objects already in db */ + if (autotag && !git_odb_exists(odb, &head->oid)) + goto done; - if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO) - autotag = 1; + if (!autotag && (error = git_vector_insert(update_heads, head)) < 0) + goto done; - git_str_clear(&refname); - if (git_str_puts(&refname, head->name) < 0) - goto on_error; - } - } + error = git_reference_name_to_id(&old, remote->repo, refname.ptr); - /* 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 (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; + if (error < 0 && error != GIT_ENOTFOUND) + goto done; - 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 (git_str_len(&refname) == 0) { - continue; - } + if (error == GIT_ENOTFOUND) { + memset(&old, 0, GIT_OID_RAWSZ); + error = 0; - /* In autotag mode, only create tags for objects already in db */ - if (autotag && !git_odb_exists(odb, &head->oid)) - continue; + if (autotag && (error = git_vector_insert(update_heads, head)) < 0) + goto done; + } - if (!autotag && git_vector_insert(&update_heads, head) < 0) - goto on_error; + if (!git_oid__cmp(&old, &head->oid)) + goto done; - error = git_reference_name_to_id(&old, remote->repo, refname.ptr); - if (error < 0 && error != GIT_ENOTFOUND) - goto on_error; + /* 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 || error == GIT_ENOTFOUND) - && !spec->force - && !git_graph_descendant_of(remote->repo, &head->oid, &old)) - continue; + if (error < 0) { + if (error == GIT_EEXISTS) + error = 0; - if (error == GIT_ENOTFOUND) { - memset(&old, 0, GIT_OID_RAWSZ); + goto done; + } - if (autotag && git_vector_insert(&update_heads, head) < 0) - 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"); - if (!git_oid__cmp(&old, &head->oid)) - continue; +done: + git_reference_free(ref); + return error; +} - /* In autotag mode, don't overwrite any locally-existing tags */ - error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag, - log_message); +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) +{ + git_refspec tagspec; + git_remote_head *head; + git_vector update_heads; + int error = 0; + size_t i; - if (error == GIT_EEXISTS) - continue; + GIT_ASSERT_ARG(remote); - if (error < 0) - goto on_error; + if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) + 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) { - if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0) - goto on_error; - } + git_vector_foreach(refs, i, head) { + if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0) + goto on_error; } if (update_fetchhead && (error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0) goto on_error; - git_vector_free(&update_heads); git_refspec__dispose(&tagspec); - git_str_dispose(&refname); + git_vector_free(&update_heads); return 0; on_error: - git_vector_free(&update_heads); git_refspec__dispose(&tagspec); - git_str_dispose(&refname); + git_vector_free(&update_heads); return -1; } @@ -1938,8 +1950,11 @@ static int next_head(const git_remote *remote, git_vector *refs, return GIT_ITEROVER; } -static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks, - git_vector *refs, const char *msg) +static int opportunistic_updates( + const git_remote *remote, + const git_remote_callbacks *callbacks, + git_vector *refs, + const char *msg) { size_t i, j, k; git_refspec *spec; @@ -1949,6 +1964,7 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call i = j = k = 0; + /* Handle refspecs matching remote heads */ while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) { /* * 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 goto cleanup; } - if (error == GIT_ITEROVER) - error = 0; + if (error != GIT_ITEROVER) + goto cleanup; + + error = 0; cleanup: git_str_dispose(&refname); |