55#include  "config.h" 
66#include  "gettext.h" 
77#include  "hash.h" 
8+ #include  "hex.h" 
89#include  "refs.h" 
910#include  "object-name.h" 
1011#include  "parse-options.h" 
1314static  const  char  *  const  git_update_ref_usage [] =  {
1415	N_ ("git update-ref [<options>] -d <refname> [<old-oid>]" ),
1516	N_ ("git update-ref [<options>]    <refname> <new-oid> [<old-oid>]" ),
16- 	N_ ("git update-ref [<options>] --stdin [-z]" ),
17+ 	N_ ("git update-ref [<options>] --stdin [-z] [--allow-partial] " ),
1718	NULL 
1819};
1920
@@ -565,6 +566,49 @@ static void parse_cmd_abort(struct ref_transaction *transaction,
565566	report_ok ("abort" );
566567}
567568
569+ static  void  print_rejected_refs (const  char  * refname ,
570+ 				const  struct  object_id  * old_oid ,
571+ 				const  struct  object_id  * new_oid ,
572+ 				const  char  * old_target ,
573+ 				const  char  * new_target ,
574+ 				enum  ref_transaction_error  err ,
575+ 				void  * cb_data  UNUSED )
576+ {
577+ 	struct  strbuf  sb  =  STRBUF_INIT ;
578+ 	const  char  * reason  =  "" ;
579+ 
580+ 	switch  (err ) {
581+ 	case  REF_TRANSACTION_ERROR_NAME_CONFLICT :
582+ 		reason  =  "refname conflict" ;
583+ 		break ;
584+ 	case  REF_TRANSACTION_ERROR_CREATE_EXISTS :
585+ 		reason  =  "reference already exists" ;
586+ 		break ;
587+ 	case  REF_TRANSACTION_ERROR_NONEXISTENT_REF :
588+ 		reason  =  "reference does not exist" ;
589+ 		break ;
590+ 	case  REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE :
591+ 		reason  =  "incorrect old value provided" ;
592+ 		break ;
593+ 	case  REF_TRANSACTION_ERROR_INVALID_NEW_VALUE :
594+ 		reason  =  "invalid new value provided" ;
595+ 		break ;
596+ 	case  REF_TRANSACTION_ERROR_EXPECTED_SYMREF :
597+ 		reason  =  "expected symref but found regular ref" ;
598+ 		break ;
599+ 	default :
600+ 		reason  =  "unkown failure" ;
601+ 	}
602+ 
603+ 	strbuf_addf (& sb , "rejected %s %s %s %s\n" , refname ,
604+ 		    new_oid  ? oid_to_hex (new_oid ) : new_target ,
605+ 		    old_oid  ? oid_to_hex (old_oid ) : old_target ,
606+ 		    reason );
607+ 
608+ 	fwrite (sb .buf , sb .len , 1 , stdout );
609+ 	strbuf_release (& sb );
610+ }
611+ 
568612static  void  parse_cmd_commit (struct  ref_transaction  * transaction ,
569613			     const  char  * next , const  char  * end  UNUSED )
570614{
@@ -573,6 +617,10 @@ static void parse_cmd_commit(struct ref_transaction *transaction,
573617		die ("commit: extra input: %s" , next );
574618	if  (ref_transaction_commit (transaction , & error ))
575619		die ("commit: %s" , error .buf );
620+ 
621+ 	ref_transaction_for_each_rejected_update (transaction ,
622+ 						 print_rejected_refs , NULL );
623+ 
576624	report_ok ("commit" );
577625	ref_transaction_free (transaction );
578626}
@@ -609,15 +657,15 @@ static const struct parse_cmd {
609657	{ "commit" ,        parse_cmd_commit ,        0 , UPDATE_REFS_CLOSED  },
610658};
611659
612- static  void  update_refs_stdin (void )
660+ static  void  update_refs_stdin (unsigned  int   flags )
613661{
614662	struct  strbuf  input  =  STRBUF_INIT , err  =  STRBUF_INIT ;
615663	enum  update_refs_state  state  =  UPDATE_REFS_OPEN ;
616664	struct  ref_transaction  * transaction ;
617665	int  i , j ;
618666
619667	transaction  =  ref_store_transaction_begin (get_main_ref_store (the_repository ),
620- 						  0 , & err );
668+ 						  flags , & err );
621669	if  (!transaction )
622670		die ("%s" , err .buf );
623671
@@ -685,7 +733,7 @@ static void update_refs_stdin(void)
685733			 */ 
686734			state  =  cmd -> state ;
687735			transaction  =  ref_store_transaction_begin (get_main_ref_store (the_repository ),
688- 								  0 , & err );
736+ 								  flags , & err );
689737			if  (!transaction )
690738				die ("%s" , err .buf );
691739
@@ -701,6 +749,8 @@ static void update_refs_stdin(void)
701749		/* Commit by default if no transaction was requested. */ 
702750		if  (ref_transaction_commit (transaction , & err ))
703751			die ("%s" , err .buf );
752+ 		ref_transaction_for_each_rejected_update (transaction ,
753+ 						 print_rejected_refs , NULL );
704754		ref_transaction_free (transaction );
705755		break ;
706756	case  UPDATE_REFS_STARTED :
@@ -727,6 +777,8 @@ int cmd_update_ref(int argc,
727777	struct  object_id  oid , oldoid ;
728778	int  delete  =  0 , no_deref  =  0 , read_stdin  =  0 , end_null  =  0 ;
729779	int  create_reflog  =  0 ;
780+ 	unsigned int   flags  =  0 ;
781+ 
730782	struct  option  options [] =  {
731783		OPT_STRING ( 'm' , NULL , & msg , N_ ("reason" ), N_ ("reason of the update" )),
732784		OPT_BOOL ('d' , NULL , & delete , N_ ("delete the reference" )),
@@ -735,6 +787,8 @@ int cmd_update_ref(int argc,
735787		OPT_BOOL ('z' , NULL , & end_null , N_ ("stdin has NUL-terminated arguments" )),
736788		OPT_BOOL ( 0  , "stdin" , & read_stdin , N_ ("read updates from stdin" )),
737789		OPT_BOOL ( 0  , "create-reflog" , & create_reflog , N_ ("create a reflog" )),
790+ 		OPT_BIT ('0' , "allow-partial" , & flags , N_ ("allow partial transactions" ),
791+ 			REF_TRANSACTION_ALLOW_PARTIAL ),
738792		OPT_END (),
739793	};
740794
@@ -756,9 +810,10 @@ int cmd_update_ref(int argc,
756810			usage_with_options (git_update_ref_usage , options );
757811		if  (end_null )
758812			line_termination  =  '\0' ;
759- 		update_refs_stdin ();
813+ 		update_refs_stdin (flags );
760814		return  0 ;
761- 	}
815+ 	} else  if  (flags  &  REF_TRANSACTION_ALLOW_PARTIAL )
816+ 		die ("--allow-partial can only be used with --stdin" );
762817
763818	if  (end_null )
764819		usage_with_options (git_update_ref_usage , options );
0 commit comments