@@ -2847,11 +2847,87 @@ enum ref_type ref_type(const char *refname)
28472847 return REF_TYPE_NORMAL ;
28482848}
28492849
2850+ static int write_pseudoref (const char * pseudoref , const unsigned char * sha1 ,
2851+ const unsigned char * old_sha1 , struct strbuf * err )
2852+ {
2853+ const char * filename ;
2854+ int fd ;
2855+ static struct lock_file lock ;
2856+ struct strbuf buf = STRBUF_INIT ;
2857+ int ret = -1 ;
2858+
2859+ strbuf_addf (& buf , "%s\n" , sha1_to_hex (sha1 ));
2860+
2861+ filename = git_path ("%s" , pseudoref );
2862+ fd = hold_lock_file_for_update (& lock , filename , LOCK_DIE_ON_ERROR );
2863+ if (fd < 0 ) {
2864+ strbuf_addf (err , "Could not open '%s' for writing: %s" ,
2865+ filename , strerror (errno ));
2866+ return -1 ;
2867+ }
2868+
2869+ if (old_sha1 ) {
2870+ unsigned char actual_old_sha1 [20 ];
2871+ read_ref (pseudoref , actual_old_sha1 );
2872+ if (hashcmp (actual_old_sha1 , old_sha1 )) {
2873+ strbuf_addf (err , "Unexpected sha1 when writing %s" , pseudoref );
2874+ rollback_lock_file (& lock );
2875+ goto done ;
2876+ }
2877+ }
2878+
2879+ if (write_in_full (fd , buf .buf , buf .len ) != buf .len ) {
2880+ strbuf_addf (err , "Could not write to '%s'" , filename );
2881+ rollback_lock_file (& lock );
2882+ goto done ;
2883+ }
2884+
2885+ commit_lock_file (& lock );
2886+ ret = 0 ;
2887+ done :
2888+ strbuf_release (& buf );
2889+ return ret ;
2890+ }
2891+
2892+ static int delete_pseudoref (const char * pseudoref , const unsigned char * old_sha1 )
2893+ {
2894+ static struct lock_file lock ;
2895+ const char * filename ;
2896+
2897+ filename = git_path ("%s" , pseudoref );
2898+
2899+ if (old_sha1 && !is_null_sha1 (old_sha1 )) {
2900+ int fd ;
2901+ unsigned char actual_old_sha1 [20 ];
2902+
2903+ fd = hold_lock_file_for_update (& lock , filename ,
2904+ LOCK_DIE_ON_ERROR );
2905+ if (fd < 0 )
2906+ die_errno (_ ("Could not open '%s' for writing" ), filename );
2907+ read_ref (pseudoref , actual_old_sha1 );
2908+ if (hashcmp (actual_old_sha1 , old_sha1 )) {
2909+ warning ("Unexpected sha1 when deleting %s" , pseudoref );
2910+ rollback_lock_file (& lock );
2911+ return -1 ;
2912+ }
2913+
2914+ unlink (filename );
2915+ rollback_lock_file (& lock );
2916+ } else {
2917+ unlink (filename );
2918+ }
2919+
2920+ return 0 ;
2921+ }
2922+
28502923int delete_ref (const char * refname , const unsigned char * sha1 , unsigned int flags )
28512924{
28522925 struct ref_transaction * transaction ;
28532926 struct strbuf err = STRBUF_INIT ;
28542927
2928+ if (ref_type (refname ) == REF_TYPE_PSEUDOREF )
2929+ return delete_pseudoref (refname , sha1 );
2930+
28552931 transaction = ref_transaction_begin (& err );
28562932 if (!transaction ||
28572933 ref_transaction_delete (transaction , refname ,
@@ -3908,17 +3984,25 @@ int update_ref(const char *msg, const char *refname,
39083984 const unsigned char * new_sha1 , const unsigned char * old_sha1 ,
39093985 unsigned int flags , enum action_on_err onerr )
39103986{
3911- struct ref_transaction * t ;
3987+ struct ref_transaction * t = NULL ;
39123988 struct strbuf err = STRBUF_INIT ;
3989+ int ret = 0 ;
39133990
3914- t = ref_transaction_begin (& err );
3915- if (!t ||
3916- ref_transaction_update (t , refname , new_sha1 , old_sha1 ,
3917- flags , msg , & err ) ||
3918- ref_transaction_commit (t , & err )) {
3991+ if (ref_type (refname ) == REF_TYPE_PSEUDOREF ) {
3992+ ret = write_pseudoref (refname , new_sha1 , old_sha1 , & err );
3993+ } else {
3994+ t = ref_transaction_begin (& err );
3995+ if (!t ||
3996+ ref_transaction_update (t , refname , new_sha1 , old_sha1 ,
3997+ flags , msg , & err ) ||
3998+ ref_transaction_commit (t , & err )) {
3999+ ret = 1 ;
4000+ ref_transaction_free (t );
4001+ }
4002+ }
4003+ if (ret ) {
39194004 const char * str = "update_ref failed for ref '%s': %s" ;
39204005
3921- ref_transaction_free (t );
39224006 switch (onerr ) {
39234007 case UPDATE_REFS_MSG_ON_ERR :
39244008 error (str , refname , err .buf );
@@ -3933,7 +4017,8 @@ int update_ref(const char *msg, const char *refname,
39334017 return 1 ;
39344018 }
39354019 strbuf_release (& err );
3936- ref_transaction_free (t );
4020+ if (t )
4021+ ref_transaction_free (t );
39374022 return 0 ;
39384023}
39394024
0 commit comments