@@ -2847,11 +2847,87 @@ enum ref_type ref_type(const char *refname)
2847
2847
return REF_TYPE_NORMAL ;
2848
2848
}
2849
2849
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
+
2850
2923
int delete_ref (const char * refname , const unsigned char * sha1 , unsigned int flags )
2851
2924
{
2852
2925
struct ref_transaction * transaction ;
2853
2926
struct strbuf err = STRBUF_INIT ;
2854
2927
2928
+ if (ref_type (refname ) == REF_TYPE_PSEUDOREF )
2929
+ return delete_pseudoref (refname , sha1 );
2930
+
2855
2931
transaction = ref_transaction_begin (& err );
2856
2932
if (!transaction ||
2857
2933
ref_transaction_delete (transaction , refname ,
@@ -3908,17 +3984,25 @@ int update_ref(const char *msg, const char *refname,
3908
3984
const unsigned char * new_sha1 , const unsigned char * old_sha1 ,
3909
3985
unsigned int flags , enum action_on_err onerr )
3910
3986
{
3911
- struct ref_transaction * t ;
3987
+ struct ref_transaction * t = NULL ;
3912
3988
struct strbuf err = STRBUF_INIT ;
3989
+ int ret = 0 ;
3913
3990
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 ) {
3919
4004
const char * str = "update_ref failed for ref '%s': %s" ;
3920
4005
3921
- ref_transaction_free (t );
3922
4006
switch (onerr ) {
3923
4007
case UPDATE_REFS_MSG_ON_ERR :
3924
4008
error (str , refname , err .buf );
@@ -3933,7 +4017,8 @@ int update_ref(const char *msg, const char *refname,
3933
4017
return 1 ;
3934
4018
}
3935
4019
strbuf_release (& err );
3936
- ref_transaction_free (t );
4020
+ if (t )
4021
+ ref_transaction_free (t );
3937
4022
return 0 ;
3938
4023
}
3939
4024
0 commit comments