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
}