Revert "Merge branch 'ar/run-command-hook'"

This reverts commit f406b8955295d01089ba2baf35eceadff2d11cae, reversing changes made to 1627809eeff75e6ec936fc609e7be46d5eb2fa9e. It seems to have caused a few regressions, two of the three known ones we have proposed solutions for. Let's give ourselves a bit more room to maneuver during the pre-release freeze period and restart once the 2.53 ships.

Junio C Hamano committed Jan 15, 2026 at 11:12 UTC a3d1f391d35762162356201028fb73774a6c4a8b
13 files changed +292 -586
Documentation/RelNotes/2.53.0.adoc
-3
@@ -93,9 +93,6 @@ Performance, Internal Implementation, Development Support etc.
93 * Prepare test suite for Git for Windows that supports symbolic
94 links.
95
96 - * Use hook API to replace ad-hoc invocation of hook scripts with the
97 - run_command() API.
98 -
96 * Import newer version of "clar", unit testing framework.
97 (merge 84071a6dea ps/clar-integers later to maint).
98
builtin/hook.c
-6
@@ -43,12 +43,6 @@ static int run(int argc, const char **argv, const char *prefix,
43 if (!argc)
44 goto usage;
45
46 - /*
47 - * All current "hook run" use-cases require ungrouped child output.
48 - * If this changes, a hook run argument can be added to toggle it.
49 - */
50 - opt.ungroup = 1;
51 -
46 /*
47 * Having a -- for "run" when providing <hook-args> is
48 * mandatory.
builtin/receive-pack.c
+155 -115
@@ -749,7 +749,7 @@ static int check_cert_push_options(const struct string_list *push_options)
749 return retval;
750 }
751
752 -static void prepare_push_cert_sha1(struct run_hooks_opt *opt)
752 +static void prepare_push_cert_sha1(struct child_process *proc)
753 {
754 static int already_done;
755
@@ -775,23 +775,23 @@ static void prepare_push_cert_sha1(struct run_hooks_opt *opt)
775 nonce_status = check_nonce(sigcheck.payload);
776 }
777 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",
779 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",
781 sigcheck.signer ? sigcheck.signer : "");
782 - strvec_pushf(&opt->env, "GIT_PUSH_CERT_KEY=%s",
782 + strvec_pushf(&proc->env, "GIT_PUSH_CERT_KEY=%s",
783 sigcheck.key ? sigcheck.key : "");
784 - strvec_pushf(&opt->env, "GIT_PUSH_CERT_STATUS=%c",
784 + strvec_pushf(&proc->env, "GIT_PUSH_CERT_STATUS=%c",
785 sigcheck.result);
786 if (push_cert_nonce) {
787 - strvec_pushf(&opt->env,
787 + strvec_pushf(&proc->env,
788 "GIT_PUSH_CERT_NONCE=%s",
789 push_cert_nonce);
790 - strvec_pushf(&opt->env,
790 + strvec_pushf(&proc->env,
791 "GIT_PUSH_CERT_NONCE_STATUS=%s",
792 nonce_status);
793 if (nonce_status == NONCE_SLOP)
794 - strvec_pushf(&opt->env,
794 + strvec_pushf(&proc->env,
795 "GIT_PUSH_CERT_NONCE_SLOP=%ld",
796 nonce_stamp_slop);
797 }
@@ -803,74 +803,119 @@ struct receive_hook_feed_state {
803 struct ref_push_report *report;
804 int skip_broken;
805 struct strbuf buf;
806 + const struct string_list *push_options;
807 };
808
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)
812 {
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);
817
822 - if (!cmd)
823 - break; /* no more commands left */
818 + if (!hook_path)
819 + return 0;
820
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");
837
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));
840
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 + }
850
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);
852
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;
858 }
859
852 - state->cmd = cmd;
860 + sigchain_push(SIGPIPE, SIG_IGN);
861
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;
869 }
870 + close(proc.in);
871 + if (use_sideband)
872 + finish_async(&muxer);
873
863 - return state->cmd ? 0 : 1; /* 0 = more to come, 1 = EOF */
874 + sigchain_pop(SIGPIPE);
875 +
876 + return finish_command(&proc);
877 }
878
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)
880 {
868 - if (!output)
869 - BUG("output must be non-NULL");
881 + struct receive_hook_feed_state *state = state_;
882 + struct command *cmd = state->cmd;
883
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;
919 }
920
921 static int run_receive_hook(struct command *commands,
@@ -878,65 +923,47 @@ static int run_receive_hook(struct command *commands,
923 int skip_broken,
924 const struct string_list *push_options)
925 {
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;
928
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;
940 }
941
942 static int run_update_hook(struct command *cmd)
943 {
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");
947
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;
950
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";
960
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);
967 }
968
969 static struct command *find_command_by_refname(struct command *list,
@@ -1613,20 +1640,33 @@ out:
1640 static void run_update_post_hook(struct command *commands)
1641 {
1642 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;
1649
1650 for (cmd = commands; cmd; cmd = cmd->next) {
1651 if (cmd->error_string || cmd->did_not_exist)
1652 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);
1656 }
1623 - if (!opt.args.nr)
1657 + if (!proc.args.nr)
1658 return;
1659
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";
1664
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 + }
1670 }
1671
1672 static void check_aliased_update_internal(struct command *cmd,
commit.c
-3
@@ -1978,9 +1978,6 @@ int run_commit_hook(int editor_is_used, const char *index_file,
1978 strvec_push(&opt.args, arg);
1979 va_end(args);
1980
1981 - /* All commit hook use-cases require ungrouping child output. */
1982 - opt.ungroup = 1;
1983 -
1981 opt.invoked_hook = invoked_hook;
1982 return run_hooks_opt(the_repository, name, &opt);
1983 }
hook.c
+2 -27
@@ -55,7 +55,7 @@ int hook_exists(struct repository *r, const char *name)
55 static int pick_next_hook(struct child_process *cp,
56 struct strbuf *out UNUSED,
57 void *pp_cb,
58 - void **pp_task_cb)
58 + void **pp_task_cb UNUSED)
59 {
60 struct hook_cb_data *hook_cb = pp_cb;
61 const char *hook_path = hook_cb->hook_path;
@@ -65,22 +65,11 @@ static int pick_next_hook(struct child_process *cp,
65
66 cp->no_stdin = 1;
67 strvec_pushv(&cp->env, hook_cb->options->env.v);
68 -
69 - if (hook_cb->options->path_to_stdin && hook_cb->options->feed_pipe)
70 - BUG("options path_to_stdin and feed_pipe are mutually exclusive");
71 -
68 /* reopen the file for stdin; run_command closes it. */
69 if (hook_cb->options->path_to_stdin) {
70 cp->no_stdin = 0;
71 cp->in = xopen(hook_cb->options->path_to_stdin, O_RDONLY);
72 }
77 -
78 - if (hook_cb->options->feed_pipe) {
79 - cp->no_stdin = 0;
80 - /* start_command() will allocate a pipe / stdin fd for us */
81 - cp->in = -1;
82 - }
83 -
73 cp->stdout_to_stderr = 1;
74 cp->trace2_hook_name = hook_cb->hook_name;
75 cp->dir = hook_cb->options->dir;
@@ -88,12 +77,6 @@ static int pick_next_hook(struct child_process *cp,
77 strvec_push(&cp->args, hook_path);
78 strvec_pushv(&cp->args, hook_cb->options->args.v);
79
91 - /*
92 - * Provide per-hook internal state via task_cb for easy access, so
93 - * hook callbacks don't have to go through hook_cb->options.
94 - */
95 - *pp_task_cb = hook_cb->options->feed_pipe_cb_data;
96 -
80 /*
81 * This pick_next_hook() will be called again, we're only
82 * running one hook, so indicate that no more work will be
@@ -153,12 +136,10 @@ int run_hooks_opt(struct repository *r, const char *hook_name,
136 .tr2_label = hook_name,
137
138 .processes = 1,
156 - .ungroup = options->ungroup,
139 + .ungroup = 1,
140
141 .get_next_task = pick_next_hook,
142 .start_failure = notify_start_failure,
160 - .feed_pipe = options->feed_pipe,
161 - .consume_output = options->consume_output,
143 .task_finished = notify_hook_finished,
144
145 .data = &cb_data,
@@ -167,9 +148,6 @@ int run_hooks_opt(struct repository *r, const char *hook_name,
148 if (!options)
149 BUG("a struct run_hooks_opt must be provided to run_hooks");
150
170 - if (options->path_to_stdin && options->feed_pipe)
171 - BUG("options path_to_stdin and feed_pipe are mutually exclusive");
172 -
151 if (options->invoked_hook)
152 *options->invoked_hook = 0;
153
@@ -199,9 +177,6 @@ int run_hooks(struct repository *r, const char *hook_name)
177 {
178 struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
179
202 - /* All use-cases of this API require ungrouping. */
203 - opt.ungroup = 1;
204 -
180 return run_hooks_opt(r, hook_name, &opt);
181 }
182
hook.h
-51
@@ -1,7 +1,6 @@
1 #ifndef HOOK_H
2 #define HOOK_H
3 #include "strvec.h"
4 -#include "run-command.h"
4
5 struct repository;
6
@@ -34,60 +33,10 @@ struct run_hooks_opt
33 */
34 int *invoked_hook;
35
37 - /**
38 - * Allow hooks to set run_processes_parallel() 'ungroup' behavior.
39 - */
40 - unsigned int ungroup:1;
41 -
36 /**
37 * Path to file which should be piped to stdin for each hook.
38 */
39 const char *path_to_stdin;
46 -
47 - /**
48 - * Callback used to incrementally feed a child hook stdin pipe.
49 - *
50 - * Useful especially if a hook consumes large quantities of data
51 - * (e.g. a list of all refs in a client push), so feeding it via
52 - * in-memory strings or slurping to/from files is inefficient.
53 - * While the callback allows piecemeal writing, it can also be
54 - * used for smaller inputs, where it gets called only once.
55 - *
56 - * Add hook callback initalization context to `feed_pipe_ctx`.
57 - * Add hook callback internal state to `feed_pipe_cb_data`.
58 - *
59 - */
60 - feed_pipe_fn feed_pipe;
61 -
62 - /**
63 - * Opaque data pointer used to pass context to `feed_pipe_fn`.
64 - *
65 - * It can be accessed via the second callback arg 'pp_cb':
66 - * ((struct hook_cb_data *) pp_cb)->hook_cb->options->feed_pipe_ctx;
67 - *
68 - * The caller is responsible for managing the memory for this data.
69 - * Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it.
70 - */
71 - void *feed_pipe_ctx;
72 -
73 - /**
74 - * Opaque data pointer used to keep internal state across callback calls.
75 - *
76 - * It can be accessed directly via the third callback arg 'pp_task_cb':
77 - * struct ... *state = pp_task_cb;
78 - *
79 - * The caller is responsible for managing the memory for this data.
80 - * Only useful when using `run_hooks_opt.feed_pipe`, otherwise ignore it.
81 - */
82 - void *feed_pipe_cb_data;
83 -
84 - /*
85 - * Populate this to capture output and prevent it from being printed to
86 - * stderr. This will be passed directly through to
87 - * run_command:run_parallel_processes(). See t/helper/test-run-command.c
88 - * for an example.
89 - */
90 - consume_output_fn consume_output;
40 };
41
42 #define RUN_HOOKS_OPT_INIT { \
refs.c
+48 -52
@@ -2422,72 +2422,68 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
2422 return 0;
2423 }
2424
2425 -struct transaction_feed_cb_data {
2426 - size_t index;
2427 - struct strbuf buf;
2428 -};
2429 -
2430 -static int transaction_hook_feed_stdin(int hook_stdin_fd, void *pp_cb, void *pp_task_cb)
2425 +static int run_transaction_hook(struct ref_transaction *transaction,
2426 + const char *state)
2427 {
2432 - struct hook_cb_data *hook_cb = pp_cb;
2433 - struct ref_transaction *transaction = hook_cb->options->feed_pipe_ctx;
2434 - struct transaction_feed_cb_data *feed_cb_data = pp_task_cb;
2435 - struct strbuf *buf = &feed_cb_data->buf;
2436 - struct ref_update *update;
2437 - size_t i = feed_cb_data->index++;
2438 - int ret;
2439 -
2440 - if (i >= transaction->nr)
2441 - return 1; /* No more refs to process */
2442 -
2443 - update = transaction->updates[i];
2428 + struct child_process proc = CHILD_PROCESS_INIT;
2429 + struct strbuf buf = STRBUF_INIT;
2430 + const char *hook;
2431 + int ret = 0;
2432
2445 - if (update->flags & REF_LOG_ONLY)
2446 - return 0;
2433 + hook = find_hook(transaction->ref_store->repo, "reference-transaction");
2434 + if (!hook)
2435 + return ret;
2436
2448 - strbuf_reset(buf);
2437 + strvec_pushl(&proc.args, hook, state, NULL);
2438 + proc.in = -1;
2439 + proc.stdout_to_stderr = 1;
2440 + proc.trace2_hook_name = "reference-transaction";
2441
2450 - if (!(update->flags & REF_HAVE_OLD))
2451 - strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2452 - else if (update->old_target)
2453 - strbuf_addf(buf, "ref:%s ", update->old_target);
2454 - else
2455 - strbuf_addf(buf, "%s ", oid_to_hex(&update->old_oid));
2442 + ret = start_command(&proc);
2443 + if (ret)
2444 + return ret;
2445
2457 - if (!(update->flags & REF_HAVE_NEW))
2458 - strbuf_addf(buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2459 - else if (update->new_target)
2460 - strbuf_addf(buf, "ref:%s ", update->new_target);
2461 - else
2462 - strbuf_addf(buf, "%s ", oid_to_hex(&update->new_oid));
2446 + sigchain_push(SIGPIPE, SIG_IGN);
2447
2464 - strbuf_addf(buf, "%s\n", update->refname);
2448 + for (size_t i = 0; i < transaction->nr; i++) {
2449 + struct ref_update *update = transaction->updates[i];
2450
2466 - ret = write_in_full(hook_stdin_fd, buf->buf, buf->len);
2467 - if (ret < 0 && errno != EPIPE)
2468 - return ret;
2451 + if (update->flags & REF_LOG_ONLY)
2452 + continue;
2453
2470 - return 0; /* no more input to feed */
2471 -}
2454 + strbuf_reset(&buf);
2455
2473 -static int run_transaction_hook(struct ref_transaction *transaction,
2474 - const char *state)
2475 -{
2476 - struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
2477 - struct transaction_feed_cb_data feed_ctx = { 0 };
2478 - int ret = 0;
2456 + if (!(update->flags & REF_HAVE_OLD))
2457 + strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2458 + else if (update->old_target)
2459 + strbuf_addf(&buf, "ref:%s ", update->old_target);
2460 + else
2461 + strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid));
2462
2480 - strvec_push(&opt.args, state);
2463 + if (!(update->flags & REF_HAVE_NEW))
2464 + strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo)));
2465 + else if (update->new_target)
2466 + strbuf_addf(&buf, "ref:%s ", update->new_target);
2467 + else
2468 + strbuf_addf(&buf, "%s ", oid_to_hex(&update->new_oid));
2469
2482 - opt.feed_pipe = transaction_hook_feed_stdin;
2483 - opt.feed_pipe_ctx = transaction;
2484 - opt.feed_pipe_cb_data = &feed_ctx;
2470 + strbuf_addf(&buf, "%s\n", update->refname);
2471
2486 - strbuf_init(&feed_ctx.buf, 0);
2472 + if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
2473 + if (errno != EPIPE) {
2474 + /* Don't leak errno outside this API */
2475 + errno = 0;
2476 + ret = -1;
2477 + }
2478 + break;
2479 + }
2480 + }
2481
2488 - ret = run_hooks_opt(transaction->ref_store->repo, "reference-transaction", &opt);
2482 + close(proc.in);
2483 + sigchain_pop(SIGPIPE);
2484 + strbuf_release(&buf);
2485
2490 - strbuf_release(&feed_ctx.buf);
2486 + ret |= finish_command(&proc);
2487 return ret;
2488 }
2489
run-command.c
+24 -118
@@ -1478,32 +1478,15 @@ enum child_state {
1478 GIT_CP_WAIT_CLEANUP,
1479 };
1480
1481 -struct parallel_child {
1482 - enum child_state state;
1483 - struct child_process process;
1484 - struct strbuf err;
1485 - void *data;
1486 -};
1487 -
1488 -static int child_is_working(const struct parallel_child *pp_child)
1489 -{
1490 - return pp_child->state == GIT_CP_WORKING;
1491 -}
1492 -
1493 -static int child_is_ready_for_cleanup(const struct parallel_child *pp_child)
1494 -{
1495 - return child_is_working(pp_child) && !pp_child->process.in;
1496 -}
1497 -
1498 -static int child_is_receiving_input(const struct parallel_child *pp_child)
1499 -{
1500 - return child_is_working(pp_child) && pp_child->process.in > 0;
1501 -}
1502 -
1481 struct parallel_processes {
1482 size_t nr_processes;
1483
1506 - struct parallel_child *children;
1484 + struct {
1485 + enum child_state state;
1486 + struct child_process process;
1487 + struct strbuf err;
1488 + void *data;
1489 + } *children;
1490 /*
1491 * The struct pollfd is logically part of *children,
1492 * but the system call expects it as its own array.
@@ -1526,7 +1509,7 @@ static void kill_children(const struct parallel_processes *pp,
1509 int signo)
1510 {
1511 for (size_t i = 0; i < opts->processes; i++)
1529 - if (child_is_working(&pp->children[i]))
1512 + if (pp->children[i].state == GIT_CP_WORKING)
1513 kill(pp->children[i].process.pid, signo);
1514 }
1515
@@ -1595,10 +1578,7 @@ static void pp_cleanup(struct parallel_processes *pp,
1578 * When get_next_task added messages to the buffer in its last
1579 * iteration, the buffered output is non empty.
1580 */
1598 - if (opts->consume_output)
1599 - opts->consume_output(&pp->buffered_output, opts->data);
1600 - else
1601 - strbuf_write(&pp->buffered_output, stderr);
1581 + strbuf_write(&pp->buffered_output, stderr);
1582 strbuf_release(&pp->buffered_output);
1583
1584 sigchain_pop_common();
@@ -1672,44 +1652,6 @@ static int pp_start_one(struct parallel_processes *pp,
1652 return 0;
1653 }
1654
1675 -static void pp_buffer_stdin(struct parallel_processes *pp,
1676 - const struct run_process_parallel_opts *opts)
1677 -{
1678 - /* Buffer stdin for each pipe. */
1679 - for (size_t i = 0; i < opts->processes; i++) {
1680 - struct child_process *proc = &pp->children[i].process;
1681 - int ret;
1682 -
1683 - if (!child_is_receiving_input(&pp->children[i]))
1684 - continue;
1685 -
1686 - /*
1687 - * child input is provided via path_to_stdin when the feed_pipe cb is
1688 - * missing, so we just signal an EOF.
1689 - */
1690 - if (!opts->feed_pipe) {
1691 - close(proc->in);
1692 - proc->in = 0;
1693 - continue;
1694 - }
1695 -
1696 - /**
1697 - * Feed the pipe:
1698 - * ret < 0 means error
1699 - * ret == 0 means there is more data to be fed
1700 - * ret > 0 means feeding finished
1701 - */
1702 - ret = opts->feed_pipe(proc->in, opts->data, pp->children[i].data);
1703 - if (ret < 0)
1704 - die_errno("feed_pipe");
1705 -
1706 - if (ret) {
1707 - close(proc->in);
1708 - proc->in = 0;
1709 - }
1710 - }
1711 -}
1712 -
1655 static void pp_buffer_stderr(struct parallel_processes *pp,
1656 const struct run_process_parallel_opts *opts,
1657 int output_timeout)
@@ -1723,7 +1665,7 @@ static void pp_buffer_stderr(struct parallel_processes *pp,
1665
1666 /* Buffer output from all pipes. */
1667 for (size_t i = 0; i < opts->processes; i++) {
1726 - if (child_is_working(&pp->children[i]) &&
1668 + if (pp->children[i].state == GIT_CP_WORKING &&
1669 pp->pfd[i].revents & (POLLIN | POLLHUP)) {
1670 int n = strbuf_read_once(&pp->children[i].err,
1671 pp->children[i].process.err, 0);
@@ -1737,17 +1679,13 @@ static void pp_buffer_stderr(struct parallel_processes *pp,
1679 }
1680 }
1681
1740 -static void pp_output(const struct parallel_processes *pp,
1741 - const struct run_process_parallel_opts *opts)
1682 +static void pp_output(const struct parallel_processes *pp)
1683 {
1684 size_t i = pp->output_owner;
1685
1745 - if (child_is_working(&pp->children[i]) &&
1686 + if (pp->children[i].state == GIT_CP_WORKING &&
1687 pp->children[i].err.len) {
1747 - if (opts->consume_output)
1748 - opts->consume_output(&pp->children[i].err, opts->data);
1749 - else
1750 - strbuf_write(&pp->children[i].err, stderr);
1688 + strbuf_write(&pp->children[i].err, stderr);
1689 strbuf_reset(&pp->children[i].err);
1690 }
1691 }
@@ -1784,7 +1722,6 @@ static int pp_collect_finished(struct parallel_processes *pp,
1722 pp->children[i].state = GIT_CP_FREE;
1723 if (pp->pfd)
1724 pp->pfd[i].fd = -1;
1787 - pp->children[i].process.in = 0;
1725 child_process_init(&pp->children[i].process);
1726
1727 if (opts->ungroup) {
@@ -1795,15 +1732,11 @@ static int pp_collect_finished(struct parallel_processes *pp,
1732 } else {
1733 const size_t n = opts->processes;
1734
1798 - /* Output errors, then all other finished child processes */
1799 - if (opts->consume_output) {
1800 - opts->consume_output(&pp->children[i].err, opts->data);
1801 - opts->consume_output(&pp->buffered_output, opts->data);
1802 - } else {
1803 - strbuf_write(&pp->children[i].err, stderr);
1804 - strbuf_write(&pp->buffered_output, stderr);
1805 - }
1735 + strbuf_write(&pp->children[i].err, stderr);
1736 strbuf_reset(&pp->children[i].err);
1737 +
1738 + /* Output all other finished child processes */
1739 + strbuf_write(&pp->buffered_output, stderr);
1740 strbuf_reset(&pp->buffered_output);
1741
1742 /*
@@ -1815,7 +1748,7 @@ static int pp_collect_finished(struct parallel_processes *pp,
1748 * running process time.
1749 */
1750 for (i = 0; i < n; i++)
1818 - if (child_is_working(&pp->children[(pp->output_owner + i) % n]))
1751 + if (pp->children[(pp->output_owner + i) % n].state == GIT_CP_WORKING)
1752 break;
1753 pp->output_owner = (pp->output_owner + i) % n;
1754 }
@@ -1823,27 +1756,6 @@ static int pp_collect_finished(struct parallel_processes *pp,
1756 return result;
1757 }
1758
1826 -static void pp_handle_child_IO(struct parallel_processes *pp,
1827 - const struct run_process_parallel_opts *opts,
1828 - int output_timeout)
1829 -{
1830 - /*
1831 - * First push input, if any (it might no-op), to child tasks to avoid them blocking
1832 - * after input. This also prevents deadlocks when ungrouping below, if a child blocks
1833 - * while the parent also waits for them to finish.
1834 - */
1835 - pp_buffer_stdin(pp, opts);
1836 -
1837 - if (opts->ungroup) {
1838 - for (size_t i = 0; i < opts->processes; i++)
1839 - if (child_is_ready_for_cleanup(&pp->children[i]))
1840 - pp->children[i].state = GIT_CP_WAIT_CLEANUP;
1841 - } else {
1842 - pp_buffer_stderr(pp, opts, output_timeout);
1843 - pp_output(pp, opts);
1844 - }
1845 -}
1846 -
1759 void run_processes_parallel(const struct run_process_parallel_opts *opts)
1760 {
1761 int i, code;
@@ -1863,16 +1775,6 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
1775 "max:%"PRIuMAX,
1776 (uintmax_t)opts->processes);
1777
1866 - if (opts->ungroup && opts->consume_output)
1867 - BUG("ungroup and reading output are mutualy exclusive");
1868 -
1869 - /*
1870 - * Child tasks might receive input via stdin, terminating early (or not), so
1871 - * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which
1872 - * actually writes the data to children stdin fds.
1873 - */
1874 - sigchain_push(SIGPIPE, SIG_IGN);
1875 -
1778 pp_init(&pp, opts, &pp_sig);
1779 while (1) {
1780 for (i = 0;
@@ -1890,7 +1792,13 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
1792 }
1793 if (!pp.nr_processes)
1794 break;
1893 - pp_handle_child_IO(&pp, opts, output_timeout);
1795 + if (opts->ungroup) {
1796 + for (size_t i = 0; i < opts->processes; i++)
1797 + pp.children[i].state = GIT_CP_WAIT_CLEANUP;
1798 + } else {
1799 + pp_buffer_stderr(&pp, opts, output_timeout);
1800 + pp_output(&pp);
1801 + }
1802 code = pp_collect_finished(&pp, opts);
1803 if (code) {
1804 pp.shutdown = 1;
@@ -1901,8 +1809,6 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts)
1809
1810 pp_cleanup(&pp, opts);
1811
1904 - sigchain_pop(SIGPIPE);
1905 -
1812 if (do_trace2)
1813 trace2_region_leave(tr2_category, tr2_label, NULL);
1814 }
run-command.h
-38
@@ -420,32 +420,6 @@ typedef int (*start_failure_fn)(struct strbuf *out,
420 void *pp_cb,
421 void *pp_task_cb);
422
423 -/**
424 - * This callback is repeatedly called on every child process who requests
425 - * start_command() to create a pipe by setting child_process.in < 0.
426 - *
427 - * pp_cb is the callback cookie as passed into run_processes_parallel, and
428 - * pp_task_cb is the callback cookie as passed into get_next_task_fn.
429 - *
430 - * Returns < 0 for error
431 - * Returns == 0 when there is more data to be fed (will be called again)
432 - * Returns > 0 when finished (child closed fd or no more data to be fed)
433 - */
434 -typedef int (*feed_pipe_fn)(int child_in,
435 - void *pp_cb,
436 - void *pp_task_cb);
437 -
438 -/**
439 - * If this callback is provided, output is collated into a new pipe instead
440 - * of the process stderr. Then `consume_output_fn` will be called repeatedly
441 - * with output contained in the `output` arg. It will also be called with an
442 - * empty `output` to allow for keepalives or similar operations if necessary.
443 - *
444 - * pp_cb is the callback cookie as passed into run_processes_parallel.
445 - * No task cookie is provided because the callback receives collated output.
446 - */
447 -typedef void (*consume_output_fn)(struct strbuf *output, void *pp_cb);
448 -
423 /**
424 * This callback is called on every child process that finished processing.
425 *
@@ -499,18 +473,6 @@ struct run_process_parallel_opts
473 */
474 start_failure_fn start_failure;
475
502 - /*
503 - * feed_pipe: see feed_pipe_fn() above. This can be NULL to omit any
504 - * special handling.
505 - */
506 - feed_pipe_fn feed_pipe;
507 -
508 - /*
509 - * consume_output: see consume_output_fn() above. This can be NULL
510 - * to omit any special handling.
511 - */
512 - consume_output_fn consume_output;
513 -
476 /**
477 * task_finished: See task_finished_fn() above. This can be
478 * NULL to omit any special handling.
sequencer.c
+17 -25
@@ -1292,40 +1292,32 @@ int update_head_with_reflog(const struct commit *old_head,
1292 return ret;
1293 }
1294
1295 -static int pipe_from_strbuf(int hook_stdin_fd, void *pp_cb, void *pp_task_cb UNUSED)
1296 -{
1297 - struct hook_cb_data *hook_cb = pp_cb;
1298 - struct strbuf *to_pipe = hook_cb->options->feed_pipe_ctx;
1299 - int ret;
1300 -
1301 - if (!to_pipe)
1302 - BUG("pipe_from_strbuf called without feed_pipe_ctx");
1303 -
1304 - ret = write_in_full(hook_stdin_fd, to_pipe->buf, to_pipe->len);
1305 - if (ret < 0 && errno != EPIPE)
1306 - return ret;
1307 -
1308 - return 1; /* done writing */
1309 -}
1310 -
1295 static int run_rewrite_hook(const struct object_id *oldoid,
1296 const struct object_id *newoid)
1297 {
1314 - struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
1298 + struct child_process proc = CHILD_PROCESS_INIT;
1299 int code;
1300 struct strbuf sb = STRBUF_INIT;
1301 + const char *hook_path = find_hook(the_repository, "post-rewrite");
1302
1318 - strbuf_addf(&sb, "%s %s\n", oid_to_hex(oldoid), oid_to_hex(newoid));
1319 -
1320 - opt.feed_pipe_ctx = &sb;
1321 - opt.feed_pipe = pipe_from_strbuf;
1322 -
1323 - strvec_push(&opt.args, "amend");
1303 + if (!hook_path)
1304 + return 0;
1305
1325 - code = run_hooks_opt(the_repository, "post-rewrite", &opt);
1306 + strvec_pushl(&proc.args, hook_path, "amend", NULL);
1307 + proc.in = -1;
1308 + proc.stdout_to_stderr = 1;
1309 + proc.trace2_hook_name = "post-rewrite";
1310
1311 + code = start_command(&proc);
1312 + if (code)
1313 + return code;
1314 + strbuf_addf(&sb, "%s %s\n", oid_to_hex(oldoid), oid_to_hex(newoid));
1315 + sigchain_push(SIGPIPE, SIG_IGN);
1316 + write_in_full(proc.in, sb.buf, sb.len);
1317 + close(proc.in);
1318 strbuf_release(&sb);
1328 - return code;
1319 + sigchain_pop(SIGPIPE);
1320 + return finish_command(&proc);
1321 }
1322
1323 void commit_post_rewrite(struct repository *r,
t/helper/test-run-command.c
+2 -65
@@ -23,26 +23,19 @@ static int number_callbacks;
23 static int parallel_next(struct child_process *cp,
24 struct strbuf *err,
25 void *cb,
26 - void **task_cb)
26 + void **task_cb UNUSED)
27 {
28 struct child_process *d = cb;
29 if (number_callbacks >= 4)
30 return 0;
31
32 strvec_pushv(&cp->args, d->args.v);
33 - cp->in = d->in;
34 - cp->no_stdin = d->no_stdin;
33 if (err)
34 strbuf_addstr(err, "preloaded output of a child\n");
35 else
36 fprintf(stderr, "preloaded output of a child\n");
37
38 number_callbacks++;
41 -
42 - /* test_stdin callback will use this to count remaining lines */
43 - *task_cb = xmalloc(sizeof(int));
44 - *(int*)(*task_cb) = 2;
45 -
39 return 1;
40 }
41
@@ -58,61 +51,18 @@ static int no_job(struct child_process *cp UNUSED,
51 return 0;
52 }
53
61 -static void test_divert_output(struct strbuf *output, void *cb UNUSED)
62 -{
63 - FILE *output_file;
64 -
65 - output_file = fopen("./output_file", "a");
66 -
67 - strbuf_write(output, output_file);
68 - fclose(output_file);
69 -}
70 -
54 static int task_finished(int result UNUSED,
55 struct strbuf *err,
56 void *pp_cb UNUSED,
74 - void *pp_task_cb)
57 + void *pp_task_cb UNUSED)
58 {
59 if (err)
60 strbuf_addstr(err, "asking for a quick stop\n");
61 else
62 fprintf(stderr, "asking for a quick stop\n");
80 -
81 - FREE_AND_NULL(pp_task_cb);
82 -
63 return 1;
64 }
65
86 -static int task_finished_quiet(int result UNUSED,
87 - struct strbuf *err UNUSED,
88 - void *pp_cb UNUSED,
89 - void *pp_task_cb)
90 -{
91 - FREE_AND_NULL(pp_task_cb);
92 - return 0;
93 -}
94 -
95 -static int test_stdin_pipe_feed(int hook_stdin_fd, void *cb UNUSED, void *task_cb)
96 -{
97 - int *lines_remaining = task_cb;
98 -
99 - if (*lines_remaining) {
100 - struct strbuf buf = STRBUF_INIT;
101 - strbuf_addf(&buf, "sample stdin %d\n", --(*lines_remaining));
102 - if (write_in_full(hook_stdin_fd, buf.buf, buf.len) < 0) {
103 - if (errno == EPIPE) {
104 - /* child closed stdin, nothing more to do */
105 - strbuf_release(&buf);
106 - return 1;
107 - }
108 - die_errno("write");
109 - }
110 - strbuf_release(&buf);
111 - }
112 -
113 - return !(*lines_remaining);
114 -}
115 -
66 struct testsuite {
67 struct string_list tests, failed;
68 int next;
@@ -207,8 +157,6 @@ static int testsuite(int argc, const char **argv)
157 struct run_process_parallel_opts opts = {
158 .get_next_task = next_test,
159 .start_failure = test_failed,
210 - .feed_pipe = test_stdin_pipe_feed,
211 - .consume_output = test_divert_output,
160 .task_finished = test_finished,
161 .data = &suite,
162 };
@@ -512,23 +460,12 @@ int cmd__run_command(int argc, const char **argv)
460
461 if (!strcmp(argv[1], "run-command-parallel")) {
462 opts.get_next_task = parallel_next;
515 - opts.task_finished = task_finished_quiet;
463 } else if (!strcmp(argv[1], "run-command-abort")) {
464 opts.get_next_task = parallel_next;
465 opts.task_finished = task_finished;
466 } else if (!strcmp(argv[1], "run-command-no-jobs")) {
467 opts.get_next_task = no_job;
468 opts.task_finished = task_finished;
522 - } else if (!strcmp(argv[1], "run-command-stdin")) {
523 - proc.in = -1;
524 - proc.no_stdin = 0;
525 - opts.get_next_task = parallel_next;
526 - opts.task_finished = task_finished_quiet;
527 - opts.feed_pipe = test_stdin_pipe_feed;
528 - } else if (!strcmp(argv[1], "run-command-divert-output")) {
529 - opts.get_next_task = parallel_next;
530 - opts.consume_output = test_divert_output;
531 - opts.task_finished = task_finished_quiet;
469 } else {
470 ret = 1;
471 fprintf(stderr, "check usage\n");
t/t0061-run-command.sh
-38
@@ -164,44 +164,6 @@ test_expect_success 'run_command runs ungrouped in parallel with more tasks than
164 test_line_count = 4 err
165 '
166
167 -test_expect_success 'run_command can divert output' '
168 - test_when_finished rm output_file &&
169 - test-tool run-command run-command-divert-output 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
170 - test_must_be_empty actual &&
171 - test_cmp expect output_file
172 -'
173 -
174 -test_expect_success 'run_command listens to stdin' '
175 - cat >expect <<-\EOF &&
176 - preloaded output of a child
177 - listening for stdin:
178 - sample stdin 1
179 - sample stdin 0
180 - preloaded output of a child
181 - listening for stdin:
182 - sample stdin 1
183 - sample stdin 0
184 - preloaded output of a child
185 - listening for stdin:
186 - sample stdin 1
187 - sample stdin 0
188 - preloaded output of a child
189 - listening for stdin:
190 - sample stdin 1
191 - sample stdin 0
192 - EOF
193 -
194 - write_script stdin-script <<-\EOF &&
195 - echo "listening for stdin:"
196 - while read line
197 - do
198 - echo "$line"
199 - done
200 - EOF
201 - test-tool run-command run-command-stdin 2 ./stdin-script 2>actual &&
202 - test_cmp expect actual
203 -'
204 -
167 cat >expect <<-EOF
168 preloaded output of a child
169 asking for a quick stop
transport.c
+44 -45
@@ -1316,66 +1316,65 @@ static void die_with_unpushed_submodules(struct string_list *needs_pushing)
1316 die(_("Aborting."));
1317 }
1318
1319 -struct feed_pre_push_hook_data {
1319 +static int run_pre_push_hook(struct transport *transport,
1320 + struct ref *remote_refs)
1321 +{
1322 + int ret = 0, x;
1323 + struct ref *r;
1324 + struct child_process proc = CHILD_PROCESS_INIT;
1325 struct strbuf buf;
1321 - const struct ref *refs;
1322 -};
1326 + const char *hook_path = find_hook(the_repository, "pre-push");
1327
1324 -static int pre_push_hook_feed_stdin(int hook_stdin_fd, void *pp_cb UNUSED, void *pp_task_cb)
1325 -{
1326 - struct feed_pre_push_hook_data *data = pp_task_cb;
1327 - const struct ref *r = data->refs;
1328 - int ret = 0;
1328 + if (!hook_path)
1329 + return 0;
1330
1330 - if (!r)
1331 - return 1; /* no more refs */
1331 + strvec_push(&proc.args, hook_path);
1332 + strvec_push(&proc.args, transport->remote->name);
1333 + strvec_push(&proc.args, transport->url);
1334
1333 - data->refs = r->next;
1335 + proc.in = -1;
1336 + proc.trace2_hook_name = "pre-push";
1337
1335 - switch (r->status) {
1336 - case REF_STATUS_REJECT_NONFASTFORWARD:
1337 - case REF_STATUS_REJECT_REMOTE_UPDATED:
1338 - case REF_STATUS_REJECT_STALE:
1339 - case REF_STATUS_UPTODATE:
1340 - return 0; /* skip refs which won't be pushed */
1341 - default:
1342 - break;
1338 + if (start_command(&proc)) {
1339 + finish_command(&proc);
1340 + return -1;
1341 }
1342
1345 - if (!r->peer_ref)
1346 - return 0;
1347 -
1348 - strbuf_reset(&data->buf);
1349 - strbuf_addf(&data->buf, "%s %s %s %s\n",
1350 - r->peer_ref->name, oid_to_hex(&r->new_oid),
1351 - r->name, oid_to_hex(&r->old_oid));
1343 + sigchain_push(SIGPIPE, SIG_IGN);
1344
1353 - ret = write_in_full(hook_stdin_fd, data->buf.buf, data->buf.len);
1354 - if (ret < 0 && errno != EPIPE)
1355 - return ret; /* We do not mind if a hook does not read all refs. */
1345 + strbuf_init(&buf, 256);
1346
1357 - return 0;
1358 -}
1347 + for (r = remote_refs; r; r = r->next) {
1348 + if (!r->peer_ref) continue;
1349 + if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
1350 + if (r->status == REF_STATUS_REJECT_STALE) continue;
1351 + if (r->status == REF_STATUS_REJECT_REMOTE_UPDATED) continue;
1352 + if (r->status == REF_STATUS_UPTODATE) continue;
1353
1360 -static int run_pre_push_hook(struct transport *transport,
1361 - struct ref *remote_refs)
1362 -{
1363 - struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
1364 - struct feed_pre_push_hook_data data;
1365 - int ret = 0;
1354 + strbuf_reset(&buf);
1355 + strbuf_addf( &buf, "%s %s %s %s\n",
1356 + r->peer_ref->name, oid_to_hex(&r->new_oid),
1357 + r->name, oid_to_hex(&r->old_oid));
1358
1367 - strvec_push(&opt.args, transport->remote->name);
1368 - strvec_push(&opt.args, transport->url);
1359 + if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
1360 + /* We do not mind if a hook does not read all refs. */
1361 + if (errno != EPIPE)
1362 + ret = -1;
1363 + break;
1364 + }
1365 + }
1366
1370 - strbuf_init(&data.buf, 0);
1371 - data.refs = remote_refs;
1367 + strbuf_release(&buf);
1368
1373 - opt.feed_pipe = pre_push_hook_feed_stdin;
1374 - opt.feed_pipe_cb_data = &data;
1369 + x = close(proc.in);
1370 + if (!ret)
1371 + ret = x;
1372
1376 - ret = run_hooks_opt(the_repository, "pre-push", &opt);
1373 + sigchain_pop(SIGPIPE);
1374
1378 - strbuf_release(&data.buf);
1375 + x = finish_command(&proc);
1376 + if (!ret)
1377 + ret = x;
1378
1379 return ret;
1380 }