@@ -748,7 +748,7 @@ static int check_cert_push_options(const struct string_list *push_options)
748
748
return retval ;
749
749
}
750
750
751
- static void prepare_push_cert_sha1 (struct child_process * proc )
751
+ static void prepare_push_cert_sha1 (struct run_hooks_opt * opt )
752
752
{
753
753
static int already_done ;
754
754
@@ -772,110 +772,42 @@ static void prepare_push_cert_sha1(struct child_process *proc)
772
772
nonce_status = check_nonce (push_cert .buf , bogs );
773
773
}
774
774
if (!is_null_oid (& push_cert_oid )) {
775
- strvec_pushf (& proc -> env_array , "GIT_PUSH_CERT=%s" ,
775
+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT=%s" ,
776
776
oid_to_hex (& push_cert_oid ));
777
- strvec_pushf (& proc -> env_array , "GIT_PUSH_CERT_SIGNER=%s" ,
777
+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_SIGNER=%s" ,
778
778
sigcheck .signer ? sigcheck .signer : "" );
779
- strvec_pushf (& proc -> env_array , "GIT_PUSH_CERT_KEY=%s" ,
779
+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_KEY=%s" ,
780
780
sigcheck .key ? sigcheck .key : "" );
781
- strvec_pushf (& proc -> env_array , "GIT_PUSH_CERT_STATUS=%c" ,
781
+ strvec_pushf (& opt -> env , "GIT_PUSH_CERT_STATUS=%c" ,
782
782
sigcheck .result );
783
783
if (push_cert_nonce ) {
784
- strvec_pushf (& proc -> env_array ,
784
+ strvec_pushf (& opt -> env ,
785
785
"GIT_PUSH_CERT_NONCE=%s" ,
786
786
push_cert_nonce );
787
- strvec_pushf (& proc -> env_array ,
787
+ strvec_pushf (& opt -> env ,
788
788
"GIT_PUSH_CERT_NONCE_STATUS=%s" ,
789
789
nonce_status );
790
790
if (nonce_status == NONCE_SLOP )
791
- strvec_pushf (& proc -> env_array ,
791
+ strvec_pushf (& opt -> env ,
792
792
"GIT_PUSH_CERT_NONCE_SLOP=%ld" ,
793
793
nonce_stamp_slop );
794
794
}
795
795
}
796
796
}
797
797
798
+ struct receive_hook_feed_context {
799
+ struct command * cmd ;
800
+ int skip_broken ;
801
+ };
802
+
798
803
struct receive_hook_feed_state {
799
804
struct command * cmd ;
800
805
struct ref_push_report * report ;
801
806
int skip_broken ;
802
807
struct strbuf buf ;
803
- const struct string_list * push_options ;
804
808
};
805
809
806
- typedef int (* feed_fn )(void * , const char * * , size_t * );
807
- static int run_and_feed_hook (const char * hook_name , feed_fn feed ,
808
- struct receive_hook_feed_state * feed_state )
809
- {
810
- struct child_process proc = CHILD_PROCESS_INIT ;
811
- struct async muxer ;
812
- const char * argv [2 ];
813
- int code ;
814
-
815
- argv [0 ] = find_hook (hook_name );
816
- if (!argv [0 ])
817
- return 0 ;
818
-
819
- argv [1 ] = NULL ;
820
-
821
- proc .argv = argv ;
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
- int i ;
828
- for (i = 0 ; i < feed_state -> push_options -> nr ; i ++ )
829
- strvec_pushf (& proc .env_array ,
830
- "GIT_PUSH_OPTION_%d=%s" , i ,
831
- feed_state -> push_options -> items [i ].string );
832
- strvec_pushf (& proc .env_array , "GIT_PUSH_OPTION_COUNT=%d" ,
833
- feed_state -> push_options -> nr );
834
- } else
835
- strvec_pushf (& proc .env_array , "GIT_PUSH_OPTION_COUNT" );
836
-
837
- if (tmp_objdir )
838
- strvec_pushv (& proc .env_array , tmp_objdir_env (tmp_objdir ));
839
-
840
- if (use_sideband ) {
841
- memset (& muxer , 0 , sizeof (muxer ));
842
- muxer .proc = copy_to_sideband ;
843
- muxer .in = -1 ;
844
- code = start_async (& muxer );
845
- if (code )
846
- return code ;
847
- proc .err = muxer .in ;
848
- }
849
-
850
- prepare_push_cert_sha1 (& proc );
851
-
852
- code = start_command (& proc );
853
- if (code ) {
854
- if (use_sideband )
855
- finish_async (& muxer );
856
- return code ;
857
- }
858
-
859
- sigchain_push (SIGPIPE , SIG_IGN );
860
-
861
- while (1 ) {
862
- const char * buf ;
863
- size_t n ;
864
- if (feed (feed_state , & buf , & n ))
865
- break ;
866
- if (write_in_full (proc .in , buf , n ) < 0 )
867
- break ;
868
- }
869
- close (proc .in );
870
- if (use_sideband )
871
- finish_async (& muxer );
872
-
873
- sigchain_pop (SIGPIPE );
874
-
875
- return finish_command (& proc );
876
- }
877
-
878
- static int feed_receive_hook (void * state_ , const char * * bufp , size_t * sizep )
810
+ static int feed_receive_hook (void * state_ )
879
811
{
880
812
struct receive_hook_feed_state * state = state_ ;
881
813
struct command * cmd = state -> cmd ;
@@ -884,9 +816,7 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
884
816
state -> skip_broken && (cmd -> error_string || cmd -> did_not_exist ))
885
817
cmd = cmd -> next ;
886
818
if (!cmd )
887
- return -1 ; /* EOF */
888
- if (!bufp )
889
- return 0 ; /* OK, can feed something. */
819
+ return 1 ; /* EOF - close the pipe*/
890
820
strbuf_reset (& state -> buf );
891
821
if (!state -> report )
892
822
state -> report = cmd -> report ;
@@ -910,32 +840,36 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
910
840
cmd -> ref_name );
911
841
state -> cmd = cmd -> next ;
912
842
}
913
- if (bufp ) {
914
- * bufp = state -> buf .buf ;
915
- * sizep = state -> buf .len ;
916
- }
917
843
return 0 ;
918
844
}
919
845
920
- static int run_receive_hook (struct command * commands ,
921
- const char * hook_name ,
922
- int skip_broken ,
923
- const struct string_list * push_options )
846
+ static int feed_receive_hook_cb (struct strbuf * pipe , void * pp_cb , void * pp_task_cb )
924
847
{
925
- struct receive_hook_feed_state state ;
926
- int status ;
927
-
928
- strbuf_init (& state .buf , 0 );
929
- state .cmd = commands ;
930
- state .skip_broken = skip_broken ;
931
- state .report = NULL ;
932
- if (feed_receive_hook (& state , NULL , NULL ))
933
- return 0 ;
934
- state .cmd = commands ;
935
- state .push_options = push_options ;
936
- status = run_and_feed_hook (hook_name , feed_receive_hook , & state );
937
- strbuf_release (& state .buf );
938
- return status ;
848
+ struct hook * hook = pp_task_cb ;
849
+ struct receive_hook_feed_state * feed_state = hook -> feed_pipe_cb_data ;
850
+ int rc ;
851
+
852
+ /* first-time setup */
853
+ if (!feed_state ) {
854
+ struct hook_cb_data * hook_cb = pp_cb ;
855
+ struct run_hooks_opt * opt = hook_cb -> options ;
856
+ struct receive_hook_feed_context * ctx = opt -> feed_pipe_ctx ;
857
+ if (!ctx )
858
+ BUG ("run_hooks_opt.feed_pipe_ctx required for receive hook" );
859
+
860
+ feed_state = xmalloc (sizeof (struct receive_hook_feed_state ));
861
+ strbuf_init (& feed_state -> buf , 0 );
862
+ feed_state -> cmd = ctx -> cmd ;
863
+ feed_state -> skip_broken = ctx -> skip_broken ;
864
+ feed_state -> report = NULL ;
865
+
866
+ hook -> feed_pipe_cb_data = feed_state ;
867
+ }
868
+
869
+ rc = feed_receive_hook (feed_state );
870
+ if (!rc )
871
+ strbuf_addbuf (pipe , & feed_state -> buf );
872
+ return rc ;
939
873
}
940
874
941
875
static void hook_output_to_sideband (struct strbuf * output , void * cb_data )
@@ -971,6 +905,55 @@ static void hook_output_to_sideband(struct strbuf *output, void *cb_data)
971
905
send_sideband (1 , 2 , output -> buf , output -> len , use_sideband );
972
906
}
973
907
908
+ static int run_receive_hook (struct command * commands ,
909
+ const char * hook_name ,
910
+ int skip_broken ,
911
+ const struct string_list * push_options )
912
+ {
913
+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
914
+ struct receive_hook_feed_context ctx ;
915
+ int rc ;
916
+ struct command * iter = commands ;
917
+
918
+ /* if there are no valid commands, don't invoke the hook at all. */
919
+ while (iter && skip_broken && (iter -> error_string || iter -> did_not_exist ))
920
+ iter = iter -> next ;
921
+ if (!iter )
922
+ return 0 ;
923
+
924
+ /* pre-receive hooks should run in series as the hook updates refs */
925
+ if (!strcmp (hook_name , "pre-receive" ))
926
+ opt .jobs = 1 ;
927
+
928
+ if (push_options ) {
929
+ int i ;
930
+ for (i = 0 ; i < push_options -> nr ; i ++ )
931
+ strvec_pushf (& opt .env , "GIT_PUSH_OPTION_%d=%s" , i ,
932
+ push_options -> items [i ].string );
933
+ strvec_pushf (& opt .env , "GIT_PUSH_OPTION_COUNT=%d" , push_options -> nr );
934
+ } else
935
+ strvec_push (& opt .env , "GIT_PUSH_OPTION_COUNT" );
936
+
937
+ if (tmp_objdir )
938
+ strvec_pushv (& opt .env , tmp_objdir_env (tmp_objdir ));
939
+
940
+ prepare_push_cert_sha1 (& opt );
941
+
942
+ /* set up sideband printer */
943
+ if (use_sideband )
944
+ opt .consume_sideband = hook_output_to_sideband ;
945
+
946
+ /* set up stdin callback */
947
+ ctx .cmd = commands ;
948
+ ctx .skip_broken = skip_broken ;
949
+ opt .feed_pipe = feed_receive_hook_cb ;
950
+ opt .feed_pipe_ctx = & ctx ;
951
+
952
+ rc = run_hooks (hook_name , & opt );
953
+ run_hooks_opt_clear (& opt );
954
+ return rc ;
955
+ }
956
+
974
957
static int run_update_hook (struct command * cmd )
975
958
{
976
959
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT ;
0 commit comments