@@ -791,7 +791,7 @@ static int check_cert_push_options(const struct string_list *push_options)
791791 return retval ;
792792}
793793
794- static void prepare_push_cert_sha1 (struct child_process * proc )
794+ static void prepare_push_cert_sha1 (struct run_hooks_opt * opt )
795795{
796796 static int already_done ;
797797
@@ -817,23 +817,23 @@ static void prepare_push_cert_sha1(struct child_process *proc)
817817 nonce_status = check_nonce (sigcheck .payload );
818818 }
819819 if (!is_null_oid (& push_cert_oid )) {
820- strvec_pushf (& proc -> env , "GIT_PUSH_CERT=%s" ,
820+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT=%s" ,
821821 oid_to_hex (& push_cert_oid ));
822- strvec_pushf (& proc -> env , "GIT_PUSH_CERT_SIGNER=%s" ,
822+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_SIGNER=%s" ,
823823 sigcheck .signer ? sigcheck .signer : "" );
824- strvec_pushf (& proc -> env , "GIT_PUSH_CERT_KEY=%s" ,
824+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_KEY=%s" ,
825825 sigcheck .key ? sigcheck .key : "" );
826- strvec_pushf (& proc -> env , "GIT_PUSH_CERT_STATUS=%c" ,
826+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_STATUS=%c" ,
827827 sigcheck .result );
828828 if (push_cert_nonce ) {
829- strvec_pushf (& proc -> env ,
829+ strvec_pushf (& opt -> env ,
830830 "GIT_PUSH_CERT_NONCE=%s" ,
831831 push_cert_nonce );
832- strvec_pushf (& proc -> env ,
832+ strvec_pushf (& opt -> env ,
833833 "GIT_PUSH_CERT_NONCE_STATUS=%s" ,
834834 nonce_status );
835835 if (nonce_status == NONCE_SLOP )
836- strvec_pushf (& proc -> env ,
836+ strvec_pushf (& opt -> env ,
837837 "GIT_PUSH_CERT_NONCE_SLOP=%ld" ,
838838 nonce_stamp_slop );
839839 }
@@ -845,94 +845,25 @@ struct receive_hook_feed_state {
845845 struct ref_push_report * report ;
846846 int skip_broken ;
847847 struct strbuf buf ;
848- const struct string_list * push_options ;
849848};
850849
851- typedef int (* feed_fn )(void * , const char * * , size_t * );
852- static int run_and_feed_hook (const char * hook_name , feed_fn feed ,
853- struct receive_hook_feed_state * feed_state )
850+ static int feed_receive_hook_cb (int hook_stdin_fd , void * pp_cb UNUSED , void * pp_task_cb )
854851{
855- struct child_process proc = CHILD_PROCESS_INIT ;
856- struct async muxer ;
857- int code ;
858- const char * hook_path = find_hook (the_repository , hook_name );
859-
860- if (!hook_path )
861- return 0 ;
862-
863- strvec_push (& proc .args , hook_path );
864- proc .in = -1 ;
865- proc .stdout_to_stderr = 1 ;
866- proc .trace2_hook_name = hook_name ;
867-
868- if (feed_state -> push_options ) {
869- size_t i ;
870- for (i = 0 ; i < feed_state -> push_options -> nr ; i ++ )
871- strvec_pushf (& proc .env ,
872- "GIT_PUSH_OPTION_%" PRIuMAX "=%s" ,
873- (uintmax_t )i ,
874- feed_state -> push_options -> items [i ].string );
875- strvec_pushf (& proc .env , "GIT_PUSH_OPTION_COUNT=%" PRIuMAX "" ,
876- (uintmax_t )feed_state -> push_options -> nr );
877- } else
878- strvec_pushf (& proc .env , "GIT_PUSH_OPTION_COUNT" );
879-
880- if (tmp_objdir )
881- strvec_pushv (& proc .env , tmp_objdir_env (tmp_objdir ));
882-
883- if (use_sideband ) {
884- memset (& muxer , 0 , sizeof (muxer ));
885- muxer .proc = copy_to_sideband ;
886- muxer .in = -1 ;
887- code = start_async (& muxer );
888- if (code )
889- return code ;
890- proc .err = muxer .in ;
891- }
892-
893- prepare_push_cert_sha1 (& proc );
894-
895- code = start_command (& proc );
896- if (code ) {
897- if (use_sideband )
898- finish_async (& muxer );
899- return code ;
900- }
901-
902- sigchain_push (SIGPIPE , SIG_IGN );
903-
904- while (1 ) {
905- const char * buf ;
906- size_t n ;
907- if (feed (feed_state , & buf , & n ))
908- break ;
909- if (write_in_full (proc .in , buf , n ) < 0 )
910- break ;
911- }
912- close (proc .in );
913- if (use_sideband )
914- finish_async (& muxer );
915-
916- sigchain_pop (SIGPIPE );
917-
918- return finish_command (& proc );
919- }
920-
921- static int feed_receive_hook (void * state_ , const char * * bufp , size_t * sizep )
922- {
923- struct receive_hook_feed_state * state = state_ ;
852+ struct receive_hook_feed_state * state = pp_task_cb ;
924853 struct command * cmd = state -> cmd ;
925854
855+ strbuf_reset (& state -> buf );
856+
926857 while (cmd &&
927858 state -> skip_broken && (cmd -> error_string || cmd -> did_not_exist ))
928859 cmd = cmd -> next ;
860+
929861 if (!cmd )
930- return -1 ; /* EOF */
931- if (!bufp )
932- return 0 ; /* OK, can feed something. */
933- strbuf_reset (& state -> buf );
862+ return 1 ; /* no more commands left */
863+
934864 if (!state -> report )
935865 state -> report = cmd -> report ;
866+
936867 if (state -> report ) {
937868 struct object_id * old_oid ;
938869 struct object_id * new_oid ;
@@ -941,44 +872,85 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
941872 old_oid = state -> report -> old_oid ? state -> report -> old_oid : & cmd -> old_oid ;
942873 new_oid = state -> report -> new_oid ? state -> report -> new_oid : & cmd -> new_oid ;
943874 ref_name = state -> report -> ref_name ? state -> report -> ref_name : cmd -> ref_name ;
875+
944876 strbuf_addf (& state -> buf , "%s %s %s\n" ,
945877 oid_to_hex (old_oid ), oid_to_hex (new_oid ),
946878 ref_name );
879+
947880 state -> report = state -> report -> next ;
948881 if (!state -> report )
949- state -> cmd = cmd -> next ;
882+ cmd = cmd -> next ;
950883 } else {
951884 strbuf_addf (& state -> buf , "%s %s %s\n" ,
952885 oid_to_hex (& cmd -> old_oid ), oid_to_hex (& cmd -> new_oid ),
953886 cmd -> ref_name );
954- state -> cmd = cmd -> next ;
887+ cmd = cmd -> next ;
955888 }
956- if (bufp ) {
957- * bufp = state -> buf .buf ;
958- * sizep = state -> buf .len ;
889+
890+ state -> cmd = cmd ;
891+
892+ if (state -> buf .len > 0 ) {
893+ int ret = write_in_full (hook_stdin_fd , state -> buf .buf , state -> buf .len );
894+ if (ret < 0 ) {
895+ if (errno == EPIPE )
896+ return 1 ; /* child closed pipe */
897+ return ret ;
898+ }
959899 }
960- return 0 ;
900+
901+ return state -> cmd ? 0 : 1 ; /* 0 = more to come, 1 = EOF */
961902}
962903
963904static int run_receive_hook (struct command * commands ,
964905 const char * hook_name ,
965906 int skip_broken ,
966907 const struct string_list * push_options )
967908{
968- struct receive_hook_feed_state state ;
969- int status ;
909+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
910+ struct command * iter = commands ;
911+ struct receive_hook_feed_state feed_state ;
912+ struct async sideband_async ;
913+ int sideband_async_started = 0 ;
914+ int saved_stderr = -1 ;
915+ int ret ;
970916
971- strbuf_init (& state .buf , 0 );
972- state .cmd = commands ;
973- state .skip_broken = skip_broken ;
974- state .report = NULL ;
975- if (feed_receive_hook (& state , NULL , NULL ))
917+ /* if there are no valid commands, don't invoke the hook at all. */
918+ while (iter && skip_broken && (iter -> error_string || iter -> did_not_exist ))
919+ iter = iter -> next ;
920+ if (!iter )
976921 return 0 ;
977- state .cmd = commands ;
978- state .push_options = push_options ;
979- status = run_and_feed_hook (hook_name , feed_receive_hook , & state );
980- strbuf_release (& state .buf );
981- return status ;
922+
923+ if (push_options ) {
924+ for (int i = 0 ; i < push_options -> nr ; i ++ )
925+ strvec_pushf (& opt .env , "GIT_PUSH_OPTION_%d=%s" , i ,
926+ push_options -> items [i ].string );
927+ strvec_pushf (& opt .env , "GIT_PUSH_OPTION_COUNT=%" PRIuMAX "" ,
928+ (uintmax_t )push_options -> nr );
929+ } else {
930+ strvec_push (& opt .env , "GIT_PUSH_OPTION_COUNT" );
931+ }
932+
933+ if (tmp_objdir )
934+ strvec_pushv (& opt .env , tmp_objdir_env (tmp_objdir ));
935+
936+ prepare_push_cert_sha1 (& opt );
937+
938+ prepare_sideband_async (& sideband_async , & saved_stderr , & sideband_async_started );
939+
940+ /* set up stdin callback */
941+ feed_state .cmd = commands ;
942+ feed_state .skip_broken = skip_broken ;
943+ feed_state .report = NULL ;
944+ strbuf_init (& feed_state .buf , 0 );
945+ opt .feed_pipe_cb_data = & feed_state ;
946+ opt .feed_pipe = feed_receive_hook_cb ;
947+
948+ ret = run_hooks_opt (the_repository , hook_name , & opt );
949+
950+ strbuf_release (& feed_state .buf );
951+ finish_sideband_async (& sideband_async , saved_stderr , sideband_async_started );
952+
953+ return ret ;
982954}
983955
984956static int run_update_hook (struct command * cmd )
0 commit comments