@@ -30,6 +30,13 @@ static unsigned char refname_disposition[256] = {
3030 * pruned.
3131 */
3232#define REF_ISPRUNING 0x0100
33+
34+ /*
35+ * Used as a flag in ref_update::flags when the lockfile needs to be
36+ * committed.
37+ */
38+ #define REF_NEEDS_COMMIT 0x0200
39+
3340/*
3441 * Try to read one refname component from the front of refname.
3542 * Return the length of the component found, or -1 if the component is
@@ -2747,8 +2754,9 @@ static int rename_ref_available(const char *oldname, const char *newname)
27472754 return ret ;
27482755}
27492756
2750- static int write_ref_sha1 (struct ref_lock * lock , const unsigned char * sha1 ,
2751- const char * logmsg );
2757+ static int write_ref_to_lockfile (struct ref_lock * lock , const unsigned char * sha1 );
2758+ static int commit_ref_update (struct ref_lock * lock ,
2759+ const unsigned char * sha1 , const char * logmsg );
27522760
27532761int rename_ref (const char * oldrefname , const char * newrefname , const char * logmsg )
27542762{
@@ -2807,7 +2815,9 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
28072815 }
28082816 lock -> force_write = 1 ;
28092817 hashcpy (lock -> old_sha1 , orig_sha1 );
2810- if (write_ref_sha1 (lock , orig_sha1 , logmsg )) {
2818+
2819+ if (write_ref_to_lockfile (lock , orig_sha1 ) ||
2820+ commit_ref_update (lock , orig_sha1 , logmsg )) {
28112821 error ("unable to write current sha1 into %s" , newrefname );
28122822 goto rollback ;
28132823 }
@@ -2824,7 +2834,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
28242834 lock -> force_write = 1 ;
28252835 flag = log_all_ref_updates ;
28262836 log_all_ref_updates = 0 ;
2827- if (write_ref_sha1 (lock , orig_sha1 , NULL ))
2837+ if (write_ref_to_lockfile (lock , orig_sha1 ) ||
2838+ commit_ref_update (lock , orig_sha1 , NULL ))
28282839 error ("unable to write current sha1 into %s" , oldrefname );
28292840 log_all_ref_updates = flag ;
28302841
@@ -2996,23 +3007,15 @@ int is_branch(const char *refname)
29963007}
29973008
29983009/*
2999- * Write sha1 into the ref specified by the lock. Make sure that errno
3000- * is sane on error .
3010+ * Write sha1 into the open lockfile, then close the lockfile. On
3011+ * errors, rollback the lockfile and set errno to reflect the problem .
30013012 */
3002- static int write_ref_sha1 (struct ref_lock * lock ,
3003- const unsigned char * sha1 , const char * logmsg )
3013+ static int write_ref_to_lockfile (struct ref_lock * lock ,
3014+ const unsigned char * sha1 )
30043015{
30053016 static char term = '\n' ;
30063017 struct object * o ;
30073018
3008- if (!lock ) {
3009- errno = EINVAL ;
3010- return -1 ;
3011- }
3012- if (!lock -> force_write && !hashcmp (lock -> old_sha1 , sha1 )) {
3013- unlock_ref (lock );
3014- return 0 ;
3015- }
30163019 o = parse_object (sha1 );
30173020 if (!o ) {
30183021 error ("Trying to write ref %s with nonexistent object %s" ,
@@ -3037,6 +3040,17 @@ static int write_ref_sha1(struct ref_lock *lock,
30373040 errno = save_errno ;
30383041 return -1 ;
30393042 }
3043+ return 0 ;
3044+ }
3045+
3046+ /*
3047+ * Commit a change to a loose reference that has already been written
3048+ * to the loose reference lockfile. Also update the reflogs if
3049+ * necessary, using the specified lockmsg (which can be NULL).
3050+ */
3051+ static int commit_ref_update (struct ref_lock * lock ,
3052+ const unsigned char * sha1 , const char * logmsg )
3053+ {
30403054 clear_loose_ref_cache (& ref_cache );
30413055 if (log_ref_write (lock -> ref_name , lock -> old_sha1 , sha1 , logmsg ) < 0 ||
30423056 (strcmp (lock -> ref_name , lock -> orig_ref_name ) &&
@@ -3738,19 +3752,23 @@ int ref_transaction_commit(struct ref_transaction *transaction,
37383752 goto cleanup ;
37393753 }
37403754
3741- /* Acquire all locks while verifying old values */
3755+ /*
3756+ * Acquire all locks, verify old values if provided, check
3757+ * that new values are valid, and write new values to the
3758+ * lockfiles, ready to be activated. Only keep one lockfile
3759+ * open at a time to avoid running out of file descriptors.
3760+ */
37423761 for (i = 0 ; i < n ; i ++ ) {
37433762 struct ref_update * update = updates [i ];
3744- int flags = update -> flags ;
37453763
37463764 if (is_null_sha1 (update -> new_sha1 ))
3747- flags |= REF_DELETING ;
3765+ update -> flags |= REF_DELETING ;
37483766 update -> lock = lock_ref_sha1_basic (update -> refname ,
37493767 (update -> have_old ?
37503768 update -> old_sha1 :
37513769 NULL ),
37523770 NULL ,
3753- flags ,
3771+ update -> flags ,
37543772 & update -> type );
37553773 if (!update -> lock ) {
37563774 ret = (errno == ENOTDIR )
@@ -3760,30 +3778,59 @@ int ref_transaction_commit(struct ref_transaction *transaction,
37603778 update -> refname );
37613779 goto cleanup ;
37623780 }
3781+ if (!(update -> flags & REF_DELETING ) &&
3782+ (update -> lock -> force_write ||
3783+ hashcmp (update -> lock -> old_sha1 , update -> new_sha1 ))) {
3784+ if (write_ref_to_lockfile (update -> lock , update -> new_sha1 )) {
3785+ /*
3786+ * The lock was freed upon failure of
3787+ * write_ref_to_lockfile():
3788+ */
3789+ update -> lock = NULL ;
3790+ strbuf_addf (err , "Cannot update the ref '%s'." ,
3791+ update -> refname );
3792+ ret = TRANSACTION_GENERIC_ERROR ;
3793+ goto cleanup ;
3794+ }
3795+ update -> flags |= REF_NEEDS_COMMIT ;
3796+ } else {
3797+ /*
3798+ * We didn't have to write anything to the lockfile.
3799+ * Close it to free up the file descriptor:
3800+ */
3801+ if (close_ref (update -> lock )) {
3802+ strbuf_addf (err , "Couldn't close %s.lock" ,
3803+ update -> refname );
3804+ goto cleanup ;
3805+ }
3806+ }
37633807 }
37643808
37653809 /* Perform updates first so live commits remain referenced */
37663810 for (i = 0 ; i < n ; i ++ ) {
37673811 struct ref_update * update = updates [i ];
37683812
3769- if (!is_null_sha1 (update -> new_sha1 )) {
3770- if (write_ref_sha1 (update -> lock , update -> new_sha1 ,
3771- update -> msg )) {
3772- update -> lock = NULL ; /* freed by write_ref_sha1 */
3813+ if (update -> flags & REF_NEEDS_COMMIT ) {
3814+ if (commit_ref_update (update -> lock ,
3815+ update -> new_sha1 , update -> msg )) {
3816+ /* The lock was freed by commit_ref_update(): */
3817+ update -> lock = NULL ;
37733818 strbuf_addf (err , "Cannot update the ref '%s'." ,
37743819 update -> refname );
37753820 ret = TRANSACTION_GENERIC_ERROR ;
37763821 goto cleanup ;
3822+ } else {
3823+ /* freed by the above call: */
3824+ update -> lock = NULL ;
37773825 }
3778- update -> lock = NULL ; /* freed by write_ref_sha1 */
37793826 }
37803827 }
37813828
37823829 /* Perform deletes now that updates are safely completed */
37833830 for (i = 0 ; i < n ; i ++ ) {
37843831 struct ref_update * update = updates [i ];
37853832
3786- if (update -> lock ) {
3833+ if (update -> flags & REF_DELETING ) {
37873834 if (delete_ref_loose (update -> lock , update -> type , err )) {
37883835 ret = TRANSACTION_GENERIC_ERROR ;
37893836 goto cleanup ;
0 commit comments