Skip to content

Commit b523776

Browse files
committed
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.
1 parent b1e83cc commit b523776

File tree

1 file changed

+118
-100
lines changed

1 file changed

+118
-100
lines changed

src/remote.c

Lines changed: 118 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,141 +1738,153 @@ static int update_ref(
17381738
return 0;
17391739
}
17401740

1741-
static int update_tips_for_spec(
1742-
git_remote *remote,
1743-
const git_remote_callbacks *callbacks,
1744-
int update_fetchhead,
1745-
git_remote_autotag_option_t tagopt,
1746-
git_refspec *spec,
1747-
git_vector *refs,
1748-
const char *log_message)
1741+
static int update_one_tip(
1742+
git_vector *update_heads,
1743+
git_remote *remote,
1744+
git_refspec *spec,
1745+
git_remote_head *head,
1746+
git_refspec *tagspec,
1747+
git_remote_autotag_option_t tagopt,
1748+
const char *log_message,
1749+
const git_remote_callbacks *callbacks)
17491750
{
1750-
int error = 0, autotag, valid;
1751-
unsigned int i = 0;
1751+
git_odb *odb;
17521752
git_str refname = GIT_STR_INIT;
1753+
git_reference *ref = NULL;
1754+
bool autotag = false;
17531755
git_oid old;
1754-
git_odb *odb;
1755-
git_remote_head *head;
1756-
git_reference *ref;
1757-
git_refspec tagspec;
1758-
git_vector update_heads;
1756+
int valid;
1757+
int error;
17591758

1760-
GIT_ASSERT_ARG(remote);
1759+
if ((error = git_repository_odb__weakptr(&odb, remote->repo)) < 0)
1760+
goto done;
17611761

1762-
if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
1763-
return -1;
1762+
/* Ignore malformed ref names (which also saves us from tag^{} */
1763+
if ((error = git_reference_name_is_valid(&valid, head->name)) < 0)
1764+
goto done;
17641765

1765-
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1766-
return -1;
1766+
if (!valid)
1767+
goto done;
17671768

1768-
/* Make a copy of the transport's refs */
1769-
if (git_vector_init(&update_heads, 16, NULL) < 0)
1770-
return -1;
1769+
/* If we have a tag, see if the auto-follow rules say to update it */
1770+
if (git_refspec_src_matches(tagspec, head->name)) {
1771+
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1772+
autotag = true;
17711773

1772-
for (; i < refs->length; ++i) {
1773-
head = git_vector_get(refs, i);
1774-
autotag = 0;
1775-
git_str_clear(&refname);
1774+
if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1775+
if (git_str_puts(&refname, head->name) < 0)
1776+
goto done;
1777+
}
1778+
}
17761779

1777-
/* Ignore malformed ref names (which also saves us from tag^{} */
1778-
if (git_reference_name_is_valid(&valid, head->name) < 0)
1779-
goto on_error;
1780+
/* If we didn't want to auto-follow the tag, check if the refspec matches */
1781+
if (!autotag && git_refspec_src_matches(spec, head->name)) {
1782+
if (spec->dst) {
1783+
if ((error = git_refspec__transform(&refname, spec, head->name)) < 0)
1784+
goto done;
1785+
} else {
1786+
/*
1787+
* no rhs means store it in FETCH_HEAD, even if we don't
1788+
* update anything else.
1789+
*/
1790+
error = git_vector_insert(update_heads, head);
1791+
goto done;
1792+
}
1793+
}
17801794

1781-
if (!valid)
1782-
continue;
1795+
/* If we still don't have a refname, we don't want it */
1796+
if (git_str_len(&refname) == 0)
1797+
goto done;
17831798

1784-
/* If we have a tag, see if the auto-follow rules say to update it */
1785-
if (git_refspec_src_matches(&tagspec, head->name)) {
1786-
if (tagopt != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
1799+
/* In autotag mode, only create tags for objects already in db */
1800+
if (autotag && !git_odb_exists(odb, &head->oid))
1801+
goto done;
17871802

1788-
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
1789-
autotag = 1;
1803+
if (!autotag && (error = git_vector_insert(update_heads, head)) < 0)
1804+
goto done;
17901805

1791-
git_str_clear(&refname);
1792-
if (git_str_puts(&refname, head->name) < 0)
1793-
goto on_error;
1794-
}
1795-
}
1806+
error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
17961807

1797-
/* If we didn't want to auto-follow the tag, check if the refspec matches */
1798-
if (!autotag && git_refspec_src_matches(spec, head->name)) {
1799-
if (spec->dst) {
1800-
if (git_refspec__transform(&refname, spec, head->name) < 0)
1801-
goto on_error;
1802-
} else {
1803-
/*
1804-
* no rhs mans store it in FETCH_HEAD, even if we don't
1805-
update anything else.
1806-
*/
1807-
if ((error = git_vector_insert(&update_heads, head)) < 0)
1808-
goto on_error;
1808+
if (error < 0 && error != GIT_ENOTFOUND)
1809+
goto done;
18091810

1810-
continue;
1811-
}
1812-
}
1811+
if (!spec->force &&
1812+
!git_graph_descendant_of(remote->repo, &head->oid, &old)) {
1813+
error = 0;
1814+
goto done;
1815+
}
18131816

1814-
/* If we still don't have a refname, we don't want it */
1815-
if (git_str_len(&refname) == 0) {
1816-
continue;
1817-
}
1817+
if (error == GIT_ENOTFOUND) {
1818+
memset(&old, 0, GIT_OID_RAWSZ);
1819+
error = 0;
18181820

1819-
/* In autotag mode, only create tags for objects already in db */
1820-
if (autotag && !git_odb_exists(odb, &head->oid))
1821-
continue;
1821+
if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
1822+
goto done;
1823+
}
18221824

1823-
if (!autotag && git_vector_insert(&update_heads, head) < 0)
1824-
goto on_error;
1825+
if (!git_oid__cmp(&old, &head->oid))
1826+
goto done;
18251827

1826-
error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1827-
if (error < 0 && error != GIT_ENOTFOUND)
1828-
goto on_error;
1828+
/* In autotag mode, don't overwrite any locally-existing tags */
1829+
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1830+
log_message);
18291831

1830-
if (!(error || error == GIT_ENOTFOUND)
1831-
&& !spec->force
1832-
&& !git_graph_descendant_of(remote->repo, &head->oid, &old))
1833-
continue;
1832+
if (error < 0) {
1833+
if (error == GIT_EEXISTS)
1834+
error = 0;
18341835

1835-
if (error == GIT_ENOTFOUND) {
1836-
memset(&old, 0, GIT_OID_RAWSZ);
1836+
goto done;
1837+
}
18371838

1838-
if (autotag && git_vector_insert(&update_heads, head) < 0)
1839-
goto on_error;
1840-
}
1839+
if (callbacks && callbacks->update_tips != NULL &&
1840+
callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1841+
git_error_set_after_callback_function(error, "git_remote_fetch");
18411842

1842-
if (!git_oid__cmp(&old, &head->oid))
1843-
continue;
1843+
done:
1844+
git_reference_free(ref);
1845+
return error;
1846+
}
18441847

1845-
/* In autotag mode, don't overwrite any locally-existing tags */
1846-
error = git_reference_create(&ref, remote->repo, refname.ptr, &head->oid, !autotag,
1847-
log_message);
1848+
static int update_tips_for_spec(
1849+
git_remote *remote,
1850+
const git_remote_callbacks *callbacks,
1851+
int update_fetchhead,
1852+
git_remote_autotag_option_t tagopt,
1853+
git_refspec *spec,
1854+
git_vector *refs,
1855+
const char *log_message)
1856+
{
1857+
git_refspec tagspec;
1858+
git_remote_head *head;
1859+
git_vector update_heads;
1860+
int error = 0;
1861+
size_t i;
18481862

1849-
if (error == GIT_EEXISTS)
1850-
continue;
1863+
GIT_ASSERT_ARG(remote);
18511864

1852-
if (error < 0)
1853-
goto on_error;
1865+
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
1866+
return -1;
18541867

1855-
git_reference_free(ref);
1868+
/* Make a copy of the transport's refs */
1869+
if (git_vector_init(&update_heads, 16, NULL) < 0)
1870+
return -1;
18561871

1857-
if (callbacks && callbacks->update_tips != NULL) {
1858-
if (callbacks->update_tips(refname.ptr, &old, &head->oid, callbacks->payload) < 0)
1859-
goto on_error;
1860-
}
1872+
git_vector_foreach(refs, i, head) {
1873+
if (update_one_tip(&update_heads, remote, spec, head, &tagspec, tagopt, log_message, callbacks) < 0)
1874+
goto on_error;
18611875
}
18621876

18631877
if (update_fetchhead &&
18641878
(error = git_remote_write_fetchhead(remote, spec, &update_heads)) < 0)
18651879
goto on_error;
18661880

1867-
git_vector_free(&update_heads);
18681881
git_refspec__dispose(&tagspec);
1869-
git_str_dispose(&refname);
1882+
git_vector_free(&update_heads);
18701883
return 0;
18711884

18721885
on_error:
1873-
git_vector_free(&update_heads);
18741886
git_refspec__dispose(&tagspec);
1875-
git_str_dispose(&refname);
1887+
git_vector_free(&update_heads);
18761888
return -1;
18771889

18781890
}
@@ -1938,8 +1950,11 @@ static int next_head(const git_remote *remote, git_vector *refs,
19381950
return GIT_ITEROVER;
19391951
}
19401952

1941-
static int opportunistic_updates(const git_remote *remote, const git_remote_callbacks *callbacks,
1942-
git_vector *refs, const char *msg)
1953+
static int opportunistic_updates(
1954+
const git_remote *remote,
1955+
const git_remote_callbacks *callbacks,
1956+
git_vector *refs,
1957+
const char *msg)
19431958
{
19441959
size_t i, j, k;
19451960
git_refspec *spec;
@@ -1949,6 +1964,7 @@ static int opportunistic_updates(const git_remote *remote, const git_remote_call
19491964

19501965
i = j = k = 0;
19511966

1967+
/* Handle refspecs matching remote heads */
19521968
while ((error = next_head(remote, refs, &spec, &head, &i, &j, &k)) == 0) {
19531969
/*
19541970
* 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
19641980
goto cleanup;
19651981
}
19661982

1967-
if (error == GIT_ITEROVER)
1968-
error = 0;
1983+
if (error != GIT_ITEROVER)
1984+
goto cleanup;
1985+
1986+
error = 0;
19691987

19701988
cleanup:
19711989
git_str_dispose(&refname);

0 commit comments

Comments
 (0)