@@ -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
18721885on_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
19701988cleanup :
19711989 git_str_dispose (& refname );
0 commit comments