@@ -2099,11 +2099,10 @@ static int split_head_update(struct ref_update *update,
20992099
21002100 /*
21012101 * First make sure that HEAD is not already in the
2102- * transaction. This insertion is O(N) in the transaction
2102+ * transaction. This check is O(lg N) in the transaction
21032103 * size, but it happens at most once per transaction.
21042104 */
2105- item = string_list_insert (affected_refnames , "HEAD" );
2106- if (item -> util ) {
2105+ if (string_list_has_string (affected_refnames , "HEAD" )) {
21072106 /* An entry already existed */
21082107 strbuf_addf (err ,
21092108 "multiple updates for 'HEAD' (including one "
@@ -2118,6 +2117,14 @@ static int split_head_update(struct ref_update *update,
21182117 update -> new_oid .hash , update -> old_oid .hash ,
21192118 update -> msg );
21202119
2120+ /*
2121+ * Add "HEAD". This insertion is O(N) in the transaction
2122+ * size, but it happens at most once per transaction.
2123+ * Add new_update->refname instead of a literal "HEAD".
2124+ */
2125+ if (strcmp (new_update -> refname , "HEAD" ))
2126+ BUG ("%s unexpectedly not 'HEAD'" , new_update -> refname );
2127+ item = string_list_insert (affected_refnames , new_update -> refname );
21212128 item -> util = new_update ;
21222129
21232130 return 0 ;
@@ -2144,13 +2151,12 @@ static int split_symref_update(struct files_ref_store *refs,
21442151
21452152 /*
21462153 * First make sure that referent is not already in the
2147- * transaction. This insertion is O(N) in the transaction
2154+ * transaction. This check is O(lg N) in the transaction
21482155 * size, but it happens at most once per symref in a
21492156 * transaction.
21502157 */
2151- item = string_list_insert (affected_refnames , referent );
2152- if (item -> util ) {
2153- /* An entry already existed */
2158+ if (string_list_has_string (affected_refnames , referent )) {
2159+ /* An entry already exists */
21542160 strbuf_addf (err ,
21552161 "multiple updates for '%s' (including one "
21562162 "via symref '%s') are not allowed" ,
@@ -2185,6 +2191,17 @@ static int split_symref_update(struct files_ref_store *refs,
21852191 update -> flags |= REF_LOG_ONLY | REF_NODEREF ;
21862192 update -> flags &= ~REF_HAVE_OLD ;
21872193
2194+ /*
2195+ * Add the referent. This insertion is O(N) in the transaction
2196+ * size, but it happens at most once per symref in a
2197+ * transaction. Make sure to add new_update->refname, which will
2198+ * be valid as long as affected_refnames is in use, and NOT
2199+ * referent, which might soon be freed by our caller.
2200+ */
2201+ item = string_list_insert (affected_refnames , new_update -> refname );
2202+ if (item -> util )
2203+ BUG ("%s unexpectedly found in affected_refnames" ,
2204+ new_update -> refname );
21882205 item -> util = new_update ;
21892206
21902207 return 0 ;
@@ -2256,7 +2273,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
22562273 struct strbuf referent = STRBUF_INIT ;
22572274 int mustexist = (update -> flags & REF_HAVE_OLD ) &&
22582275 !is_null_oid (& update -> old_oid );
2259- int ret ;
2276+ int ret = 0 ;
22602277 struct ref_lock * lock ;
22612278
22622279 files_assert_main_repository (refs , "lock_ref_for_update" );
@@ -2268,7 +2285,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
22682285 ret = split_head_update (update , transaction , head_ref ,
22692286 affected_refnames , err );
22702287 if (ret )
2271- return ret ;
2288+ goto out ;
22722289 }
22732290
22742291 ret = lock_raw_ref (refs , update -> refname , mustexist ,
@@ -2282,7 +2299,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
22822299 strbuf_addf (err , "cannot lock ref '%s': %s" ,
22832300 original_update_refname (update ), reason );
22842301 free (reason );
2285- return ret ;
2302+ goto out ;
22862303 }
22872304
22882305 update -> backend_data = lock ;
@@ -2301,10 +2318,12 @@ static int lock_ref_for_update(struct files_ref_store *refs,
23012318 strbuf_addf (err , "cannot lock ref '%s': "
23022319 "error reading reference" ,
23032320 original_update_refname (update ));
2304- return -1 ;
2321+ ret = TRANSACTION_GENERIC_ERROR ;
2322+ goto out ;
23052323 }
23062324 } else if (check_old_oid (update , & lock -> old_oid , err )) {
2307- return TRANSACTION_GENERIC_ERROR ;
2325+ ret = TRANSACTION_GENERIC_ERROR ;
2326+ goto out ;
23082327 }
23092328 } else {
23102329 /*
@@ -2318,13 +2337,15 @@ static int lock_ref_for_update(struct files_ref_store *refs,
23182337 referent .buf , transaction ,
23192338 affected_refnames , err );
23202339 if (ret )
2321- return ret ;
2340+ goto out ;
23222341 }
23232342 } else {
23242343 struct ref_update * parent_update ;
23252344
2326- if (check_old_oid (update , & lock -> old_oid , err ))
2327- return TRANSACTION_GENERIC_ERROR ;
2345+ if (check_old_oid (update , & lock -> old_oid , err )) {
2346+ ret = TRANSACTION_GENERIC_ERROR ;
2347+ goto out ;
2348+ }
23282349
23292350 /*
23302351 * If this update is happening indirectly because of a
@@ -2361,7 +2382,8 @@ static int lock_ref_for_update(struct files_ref_store *refs,
23612382 "cannot update ref '%s': %s" ,
23622383 update -> refname , write_err );
23632384 free (write_err );
2364- return TRANSACTION_GENERIC_ERROR ;
2385+ ret = TRANSACTION_GENERIC_ERROR ;
2386+ goto out ;
23652387 } else {
23662388 update -> flags |= REF_NEEDS_COMMIT ;
23672389 }
@@ -2375,10 +2397,14 @@ static int lock_ref_for_update(struct files_ref_store *refs,
23752397 if (close_ref (lock )) {
23762398 strbuf_addf (err , "couldn't close '%s.lock'" ,
23772399 update -> refname );
2378- return TRANSACTION_GENERIC_ERROR ;
2400+ ret = TRANSACTION_GENERIC_ERROR ;
2401+ goto out ;
23792402 }
23802403 }
2381- return 0 ;
2404+
2405+ out :
2406+ strbuf_release (& referent );
2407+ return ret ;
23822408}
23832409
23842410/*
0 commit comments