@@ -749,7 +749,7 @@ static int check_cert_push_options(const struct string_list *push_options)
749749 return retval ;
750750}
751751
752- static void prepare_push_cert_sha1 (struct run_hooks_opt * opt )
752+ static void prepare_push_cert_sha1 (struct child_process * proc )
753753{
754754 static int already_done ;
755755
@@ -775,23 +775,23 @@ static void prepare_push_cert_sha1(struct run_hooks_opt *opt)
775775 nonce_status = check_nonce (sigcheck .payload );
776776 }
777777 if (!is_null_oid (& push_cert_oid )) {
778- strvec_pushf (& opt -> env , "GIT_PUSH_CERT=%s" ,
778+ strvec_pushf (& proc -> env , "GIT_PUSH_CERT=%s" ,
779779 oid_to_hex (& push_cert_oid ));
780- strvec_pushf (& opt -> env , "GIT_PUSH_CERT_SIGNER=%s" ,
780+ strvec_pushf (& proc -> env , "GIT_PUSH_CERT_SIGNER=%s" ,
781781 sigcheck .signer ? sigcheck .signer : "" );
782- strvec_pushf (& opt -> env , "GIT_PUSH_CERT_KEY=%s" ,
782+ strvec_pushf (& proc -> env , "GIT_PUSH_CERT_KEY=%s" ,
783783 sigcheck .key ? sigcheck .key : "" );
784- strvec_pushf (& opt -> env , "GIT_PUSH_CERT_STATUS=%c" ,
784+ strvec_pushf (& proc -> env , "GIT_PUSH_CERT_STATUS=%c" ,
785785 sigcheck .result );
786786 if (push_cert_nonce ) {
787- strvec_pushf (& opt -> env ,
787+ strvec_pushf (& proc -> env ,
788788 "GIT_PUSH_CERT_NONCE=%s" ,
789789 push_cert_nonce );
790- strvec_pushf (& opt -> env ,
790+ strvec_pushf (& proc -> env ,
791791 "GIT_PUSH_CERT_NONCE_STATUS=%s" ,
792792 nonce_status );
793793 if (nonce_status == NONCE_SLOP )
794- strvec_pushf (& opt -> env ,
794+ strvec_pushf (& proc -> env ,
795795 "GIT_PUSH_CERT_NONCE_SLOP=%ld" ,
796796 nonce_stamp_slop );
797797 }
@@ -803,140 +803,167 @@ struct receive_hook_feed_state {
803803 struct ref_push_report * report ;
804804 int skip_broken ;
805805 struct strbuf buf ;
806+ const struct string_list * push_options ;
806807};
807808
808- static int feed_receive_hook_cb (int hook_stdin_fd , void * pp_cb UNUSED , void * pp_task_cb )
809+ typedef int (* feed_fn )(void * , const char * * , size_t * );
810+ static int run_and_feed_hook (const char * hook_name , feed_fn feed ,
811+ struct receive_hook_feed_state * feed_state )
809812{
810- struct receive_hook_feed_state * state = pp_task_cb ;
811- struct command * cmd = state -> cmd ;
812- unsigned int lines_batch_size = 500 ;
813-
814- strbuf_reset (& state -> buf );
815-
816- /* batch lines to avoid going through run-command's poll loop for each line */
817- for (unsigned int i = 0 ; i < lines_batch_size ; i ++ ) {
818- while (cmd &&
819- state -> skip_broken && (cmd -> error_string || cmd -> did_not_exist ))
820- cmd = cmd -> next ;
813+ struct child_process proc = CHILD_PROCESS_INIT ;
814+ struct async muxer ;
815+ int code ;
816+ const char * hook_path = find_hook (the_repository , hook_name );
821817
822- if (!cmd )
823- break ; /* no more commands left */
818+ if (!hook_path )
819+ return 0 ;
824820
825- if (!state -> report )
826- state -> report = cmd -> report ;
821+ strvec_push (& proc .args , hook_path );
822+ proc .in = -1 ;
823+ proc .stdout_to_stderr = 1 ;
824+ proc .trace2_hook_name = hook_name ;
825+
826+ if (feed_state -> push_options ) {
827+ size_t i ;
828+ for (i = 0 ; i < feed_state -> push_options -> nr ; i ++ )
829+ strvec_pushf (& proc .env ,
830+ "GIT_PUSH_OPTION_%" PRIuMAX "=%s" ,
831+ (uintmax_t )i ,
832+ feed_state -> push_options -> items [i ].string );
833+ strvec_pushf (& proc .env , "GIT_PUSH_OPTION_COUNT=%" PRIuMAX "" ,
834+ (uintmax_t )feed_state -> push_options -> nr );
835+ } else
836+ strvec_pushf (& proc .env , "GIT_PUSH_OPTION_COUNT" );
827837
828- if (state -> report ) {
829- struct object_id * old_oid ;
830- struct object_id * new_oid ;
831- const char * ref_name ;
838+ if (tmp_objdir )
839+ strvec_pushv (& proc .env , tmp_objdir_env (tmp_objdir ));
832840
833- old_oid = state -> report -> old_oid ? state -> report -> old_oid : & cmd -> old_oid ;
834- new_oid = state -> report -> new_oid ? state -> report -> new_oid : & cmd -> new_oid ;
835- ref_name = state -> report -> ref_name ? state -> report -> ref_name : cmd -> ref_name ;
841+ if (use_sideband ) {
842+ memset (& muxer , 0 , sizeof (muxer ));
843+ muxer .proc = copy_to_sideband ;
844+ muxer .in = -1 ;
845+ code = start_async (& muxer );
846+ if (code )
847+ return code ;
848+ proc .err = muxer .in ;
849+ }
836850
837- strbuf_addf (& state -> buf , "%s %s %s\n" ,
838- oid_to_hex (old_oid ), oid_to_hex (new_oid ),
839- ref_name );
851+ prepare_push_cert_sha1 (& proc );
840852
841- state -> report = state -> report -> next ;
842- if (!state -> report )
843- cmd = cmd -> next ;
844- } else {
845- strbuf_addf (& state -> buf , "%s %s %s\n" ,
846- oid_to_hex (& cmd -> old_oid ), oid_to_hex (& cmd -> new_oid ),
847- cmd -> ref_name );
848- cmd = cmd -> next ;
849- }
853+ code = start_command (& proc );
854+ if (code ) {
855+ if (use_sideband )
856+ finish_async (& muxer );
857+ return code ;
850858 }
851859
852- state -> cmd = cmd ;
860+ sigchain_push ( SIGPIPE , SIG_IGN ) ;
853861
854- if ( state -> buf . len > 0 ) {
855- int ret = write_in_full ( hook_stdin_fd , state -> buf . buf , state -> buf . len ) ;
856- if ( ret < 0 ) {
857- if (errno == EPIPE )
858- return 1 ; /* child closed pipe */
859- return ret ;
860- }
862+ while ( 1 ) {
863+ const char * buf ;
864+ size_t n ;
865+ if (feed ( feed_state , & buf , & n ) )
866+ break ;
867+ if ( write_in_full ( proc . in , buf , n ) < 0 )
868+ break ;
861869 }
870+ close (proc .in );
871+ if (use_sideband )
872+ finish_async (& muxer );
862873
863- return state -> cmd ? 0 : 1 ; /* 0 = more to come, 1 = EOF */
874+ sigchain_pop (SIGPIPE );
875+
876+ return finish_command (& proc );
864877}
865878
866- static void hook_output_to_sideband ( struct strbuf * output , void * cb_data UNUSED )
879+ static int feed_receive_hook ( void * state_ , const char * * bufp , size_t * sizep )
867880{
868- if (! output )
869- BUG ( "output must be non-NULL" ) ;
881+ struct receive_hook_feed_state * state = state_ ;
882+ struct command * cmd = state -> cmd ;
870883
871- /* buffer might be empty for keepalives */
872- if (output -> len )
873- send_sideband (1 , 2 , output -> buf , output -> len , use_sideband );
884+ while (cmd &&
885+ state -> skip_broken && (cmd -> error_string || cmd -> did_not_exist ))
886+ cmd = cmd -> next ;
887+ if (!cmd )
888+ return -1 ; /* EOF */
889+ if (!bufp )
890+ return 0 ; /* OK, can feed something. */
891+ strbuf_reset (& state -> buf );
892+ if (!state -> report )
893+ state -> report = cmd -> report ;
894+ if (state -> report ) {
895+ struct object_id * old_oid ;
896+ struct object_id * new_oid ;
897+ const char * ref_name ;
898+
899+ old_oid = state -> report -> old_oid ? state -> report -> old_oid : & cmd -> old_oid ;
900+ new_oid = state -> report -> new_oid ? state -> report -> new_oid : & cmd -> new_oid ;
901+ ref_name = state -> report -> ref_name ? state -> report -> ref_name : cmd -> ref_name ;
902+ strbuf_addf (& state -> buf , "%s %s %s\n" ,
903+ oid_to_hex (old_oid ), oid_to_hex (new_oid ),
904+ ref_name );
905+ state -> report = state -> report -> next ;
906+ if (!state -> report )
907+ state -> cmd = cmd -> next ;
908+ } else {
909+ strbuf_addf (& state -> buf , "%s %s %s\n" ,
910+ oid_to_hex (& cmd -> old_oid ), oid_to_hex (& cmd -> new_oid ),
911+ cmd -> ref_name );
912+ state -> cmd = cmd -> next ;
913+ }
914+ if (bufp ) {
915+ * bufp = state -> buf .buf ;
916+ * sizep = state -> buf .len ;
917+ }
918+ return 0 ;
874919}
875920
876921static int run_receive_hook (struct command * commands ,
877922 const char * hook_name ,
878923 int skip_broken ,
879924 const struct string_list * push_options )
880925{
881- struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
882- struct command * iter = commands ;
883- struct receive_hook_feed_state feed_state ;
884- int ret ;
885-
886- /* if there are no valid commands, don't invoke the hook at all. */
887- while (iter && skip_broken && (iter -> error_string || iter -> did_not_exist ))
888- iter = iter -> next ;
889- if (!iter )
890- return 0 ;
891-
892- if (push_options ) {
893- for (int i = 0 ; i < push_options -> nr ; i ++ )
894- strvec_pushf (& opt .env , "GIT_PUSH_OPTION_%d=%s" , i ,
895- push_options -> items [i ].string );
896- strvec_pushf (& opt .env , "GIT_PUSH_OPTION_COUNT=%" PRIuMAX "" ,
897- (uintmax_t )push_options -> nr );
898- } else {
899- strvec_push (& opt .env , "GIT_PUSH_OPTION_COUNT" );
900- }
901-
902- if (tmp_objdir )
903- strvec_pushv (& opt .env , tmp_objdir_env (tmp_objdir ));
904-
905- prepare_push_cert_sha1 (& opt );
906-
907- /* set up sideband printer */
908- if (use_sideband )
909- opt .consume_output = hook_output_to_sideband ;
910-
911- /* set up stdin callback */
912- feed_state .cmd = commands ;
913- feed_state .skip_broken = skip_broken ;
914- feed_state .report = NULL ;
915- strbuf_init (& feed_state .buf , 0 );
916- opt .feed_pipe_cb_data = & feed_state ;
917- opt .feed_pipe = feed_receive_hook_cb ;
918-
919- ret = run_hooks_opt (the_repository , hook_name , & opt );
920-
921- strbuf_release (& feed_state .buf );
926+ struct receive_hook_feed_state state ;
927+ int status ;
922928
923- return ret ;
929+ strbuf_init (& state .buf , 0 );
930+ state .cmd = commands ;
931+ state .skip_broken = skip_broken ;
932+ state .report = NULL ;
933+ if (feed_receive_hook (& state , NULL , NULL ))
934+ return 0 ;
935+ state .cmd = commands ;
936+ state .push_options = push_options ;
937+ status = run_and_feed_hook (hook_name , feed_receive_hook , & state );
938+ strbuf_release (& state .buf );
939+ return status ;
924940}
925941
926942static int run_update_hook (struct command * cmd )
927943{
928- struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
944+ struct child_process proc = CHILD_PROCESS_INIT ;
945+ int code ;
946+ const char * hook_path = find_hook (the_repository , "update" );
929947
930- strvec_pushl (& opt .args ,
931- cmd -> ref_name ,
932- oid_to_hex (& cmd -> old_oid ),
933- oid_to_hex (& cmd -> new_oid ),
934- NULL );
948+ if (!hook_path )
949+ return 0 ;
935950
936- if (use_sideband )
937- opt .consume_output = hook_output_to_sideband ;
951+ strvec_push (& proc .args , hook_path );
952+ strvec_push (& proc .args , cmd -> ref_name );
953+ strvec_push (& proc .args , oid_to_hex (& cmd -> old_oid ));
954+ strvec_push (& proc .args , oid_to_hex (& cmd -> new_oid ));
955+
956+ proc .no_stdin = 1 ;
957+ proc .stdout_to_stderr = 1 ;
958+ proc .err = use_sideband ? -1 : 0 ;
959+ proc .trace2_hook_name = "update" ;
938960
939- return run_hooks_opt (the_repository , "update" , & opt );
961+ code = start_command (& proc );
962+ if (code )
963+ return code ;
964+ if (use_sideband )
965+ copy_to_sideband (proc .err , -1 , NULL );
966+ return finish_command (& proc );
940967}
941968
942969static struct command * find_command_by_refname (struct command * list ,
@@ -1613,20 +1640,33 @@ static const char *update(struct command *cmd, struct shallow_info *si)
16131640static void run_update_post_hook (struct command * commands )
16141641{
16151642 struct command * cmd ;
1616- struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
1643+ struct child_process proc = CHILD_PROCESS_INIT ;
1644+ const char * hook ;
1645+
1646+ hook = find_hook (the_repository , "post-update" );
1647+ if (!hook )
1648+ return ;
16171649
16181650 for (cmd = commands ; cmd ; cmd = cmd -> next ) {
16191651 if (cmd -> error_string || cmd -> did_not_exist )
16201652 continue ;
1621- strvec_push (& opt .args , cmd -> ref_name );
1653+ if (!proc .args .nr )
1654+ strvec_push (& proc .args , hook );
1655+ strvec_push (& proc .args , cmd -> ref_name );
16221656 }
1623- if (!opt .args .nr )
1657+ if (!proc .args .nr )
16241658 return ;
16251659
1626- if (use_sideband )
1627- opt .consume_output = hook_output_to_sideband ;
1660+ proc .no_stdin = 1 ;
1661+ proc .stdout_to_stderr = 1 ;
1662+ proc .err = use_sideband ? -1 : 0 ;
1663+ proc .trace2_hook_name = "post-update" ;
16281664
1629- run_hooks_opt (the_repository , "post-update" , & opt );
1665+ if (!start_command (& proc )) {
1666+ if (use_sideband )
1667+ copy_to_sideband (proc .err , -1 , NULL );
1668+ finish_command (& proc );
1669+ }
16301670}
16311671
16321672static void check_aliased_update_internal (struct command * cmd ,
0 commit comments