Skip to content

Commit 76d44c8

Browse files
committed
Merge branch 'sp/maint-push-sideband' into sp/push-sideband
* sp/maint-push-sideband: receive-pack: Send hook output over side band #2 receive-pack: Wrap status reports inside side-band-64k receive-pack: Refactor how capabilities are shown to the client send-pack: demultiplex a sideband stream with status data run-command: support custom fd-set in async run-command: Allow stderr to be a caller supplied pipe Update git fsck --full short description to mention packs Conflicts: run-command.c
2 parents b0883aa + 6d525d3 commit 76d44c8

11 files changed

+290
-90
lines changed

Documentation/technical/api-run-command.txt

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ The functions above do the following:
6464
`start_async`::
6565

6666
Run a function asynchronously. Takes a pointer to a `struct
67-
async` that specifies the details and returns a pipe FD
68-
from which the caller reads. See below for details.
67+
async` that specifies the details and returns a set of pipe FDs
68+
for communication with the function. See below for details.
6969

7070
`finish_async`::
7171

@@ -135,7 +135,7 @@ stderr as follows:
135135

136136
.in: The FD must be readable; it becomes child's stdin.
137137
.out: The FD must be writable; it becomes child's stdout.
138-
.err > 0 is not supported.
138+
.err: The FD must be writable; it becomes child's stderr.
139139

140140
The specified FD is closed by start_command(), even if it fails to
141141
run the sub-process!
@@ -180,17 +180,47 @@ The caller:
180180
struct async variable;
181181
2. initializes .proc and .data;
182182
3. calls start_async();
183-
4. processes the data by reading from the fd in .out;
184-
5. closes .out;
183+
4. processes communicates with proc through .in and .out;
184+
5. closes .in and .out;
185185
6. calls finish_async().
186186

187+
The members .in, .out are used to provide a set of fd's for
188+
communication between the caller and the callee as follows:
189+
190+
. Specify 0 to have no file descriptor passed. The callee will
191+
receive -1 in the corresponding argument.
192+
193+
. Specify < 0 to have a pipe allocated; start_async() replaces
194+
with the pipe FD in the following way:
195+
196+
.in: Returns the writable pipe end into which the caller
197+
writes; the readable end of the pipe becomes the function's
198+
in argument.
199+
200+
.out: Returns the readable pipe end from which the caller
201+
reads; the writable end of the pipe becomes the function's
202+
out argument.
203+
204+
The caller of start_async() must close the returned FDs after it
205+
has completed reading from/writing from them.
206+
207+
. Specify a file descriptor > 0 to be used by the function:
208+
209+
.in: The FD must be readable; it becomes the function's in.
210+
.out: The FD must be writable; it becomes the function's out.
211+
212+
The specified FD is closed by start_async(), even if it fails to
213+
run the function.
214+
187215
The function pointer in .proc has the following signature:
188216

189-
int proc(int fd, void *data);
217+
int proc(int in, int out, void *data);
190218

191-
. fd specifies a writable file descriptor to which the function must
192-
write the data that it produces. The function *must* close this
193-
descriptor before it returns.
219+
. in, out specifies a set of file descriptors to which the function
220+
must read/write the data that it needs/produces. The function
221+
*must* close these descriptors before it returns. A descriptor
222+
may be -1 if the caller did not configure a descriptor for that
223+
direction.
194224

195225
. data is the value that the caller has specified in the .data member
196226
of struct async.
@@ -205,8 +235,8 @@ because this facility is implemented by a pipe to a forked process on
205235
UNIX, but by a thread in the same address space on Windows:
206236

207237
. It cannot change the program's state (global variables, environment,
208-
etc.) in a way that the caller notices; in other words, .out is the
209-
only communication channel to the caller.
238+
etc.) in a way that the caller notices; in other words, .in and .out
239+
are the only communication channels to the caller.
210240

211241
. It must not change the program's state that the caller of the
212242
facility also uses.

builtin-fetch-pack.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,12 +586,12 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
586586
return retval;
587587
}
588588

589-
static int sideband_demux(int fd, void *data)
589+
static int sideband_demux(int in, int out, void *data)
590590
{
591591
int *xd = data;
592592

593-
int ret = recv_sideband("fetch-pack", xd[0], fd);
594-
close(fd);
593+
int ret = recv_sideband("fetch-pack", xd[0], out);
594+
close(out);
595595
return ret;
596596
}
597597

@@ -613,6 +613,7 @@ static int get_pack(int xd[2], char **pack_lockfile)
613613
*/
614614
demux.proc = sideband_demux;
615615
demux.data = xd;
616+
demux.out = -1;
616617
if (start_async(&demux))
617618
die("fetch-pack: unable to fork off sideband"
618619
" demultiplexer");

builtin-fsck.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ static struct option fsck_opts[] = {
578578
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
579579
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
580580
OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"),
581-
OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"),
581+
OPT_BOOLEAN(0, "full", &check_full, "also consider packs and alternate objects"),
582582
OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
583583
OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
584584
"write dangling objects in .git/lost-found"),

builtin-receive-pack.c

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "pack.h"
33
#include "refs.h"
44
#include "pkt-line.h"
5+
#include "sideband.h"
56
#include "run-command.h"
67
#include "exec_cmd.h"
78
#include "commit.h"
@@ -27,11 +28,12 @@ static int receive_unpack_limit = -1;
2728
static int transfer_unpack_limit = -1;
2829
static int unpack_limit = 100;
2930
static int report_status;
31+
static int use_sideband;
3032
static int prefer_ofs_delta = 1;
3133
static int auto_update_server_info;
3234
static int auto_gc = 1;
3335
static const char *head_name;
34-
static char *capabilities_to_send;
36+
static int sent_capabilities;
3537

3638
static enum deny_action parse_deny_action(const char *var, const char *value)
3739
{
@@ -105,19 +107,21 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
105107

106108
static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
107109
{
108-
if (!capabilities_to_send)
110+
if (sent_capabilities)
109111
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
110112
else
111-
packet_write(1, "%s %s%c%s\n",
112-
sha1_to_hex(sha1), path, 0, capabilities_to_send);
113-
capabilities_to_send = NULL;
113+
packet_write(1, "%s %s%c%s%s\n",
114+
sha1_to_hex(sha1), path, 0,
115+
" report-status delete-refs side-band-64k",
116+
prefer_ofs_delta ? " ofs-delta" : "");
117+
sent_capabilities = 1;
114118
return 0;
115119
}
116120

117121
static void write_head_info(void)
118122
{
119123
for_each_ref(show_ref, NULL);
120-
if (capabilities_to_send)
124+
if (!sent_capabilities)
121125
show_ref("capabilities^{}", null_sha1, 0, NULL);
122126

123127
}
@@ -135,11 +139,25 @@ static struct command *commands;
135139
static const char pre_receive_hook[] = "hooks/pre-receive";
136140
static const char post_receive_hook[] = "hooks/post-receive";
137141

142+
static int copy_to_sideband(int in, int out, void *arg)
143+
{
144+
char data[128];
145+
while (1) {
146+
ssize_t sz = xread(in, data, sizeof(data));
147+
if (sz <= 0)
148+
break;
149+
send_sideband(1, 2, data, sz, use_sideband);
150+
}
151+
close(in);
152+
return 0;
153+
}
154+
138155
static int run_receive_hook(const char *hook_name)
139156
{
140157
static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
141158
struct command *cmd;
142159
struct child_process proc;
160+
struct async muxer;
143161
const char *argv[2];
144162
int have_input = 0, code;
145163

@@ -159,9 +177,23 @@ static int run_receive_hook(const char *hook_name)
159177
proc.in = -1;
160178
proc.stdout_to_stderr = 1;
161179

180+
if (use_sideband) {
181+
memset(&muxer, 0, sizeof(muxer));
182+
muxer.proc = copy_to_sideband;
183+
muxer.in = -1;
184+
code = start_async(&muxer);
185+
if (code)
186+
return code;
187+
proc.err = muxer.in;
188+
}
189+
162190
code = start_command(&proc);
163-
if (code)
191+
if (code) {
192+
if (use_sideband)
193+
finish_async(&muxer);
164194
return code;
195+
}
196+
165197
for (cmd = commands; cmd; cmd = cmd->next) {
166198
if (!cmd->error_string) {
167199
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -173,13 +205,17 @@ static int run_receive_hook(const char *hook_name)
173205
}
174206
}
175207
close(proc.in);
208+
if (use_sideband)
209+
finish_async(&muxer);
176210
return finish_command(&proc);
177211
}
178212

179213
static int run_update_hook(struct command *cmd)
180214
{
181215
static const char update_hook[] = "hooks/update";
182216
const char *argv[5];
217+
struct child_process proc;
218+
int code;
183219

184220
if (access(update_hook, X_OK) < 0)
185221
return 0;
@@ -190,8 +226,18 @@ static int run_update_hook(struct command *cmd)
190226
argv[3] = sha1_to_hex(cmd->new_sha1);
191227
argv[4] = NULL;
192228

193-
return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
194-
RUN_COMMAND_STDOUT_TO_STDERR);
229+
memset(&proc, 0, sizeof(proc));
230+
proc.no_stdin = 1;
231+
proc.stdout_to_stderr = 1;
232+
proc.err = use_sideband ? -1 : 0;
233+
proc.argv = argv;
234+
235+
code = start_command(&proc);
236+
if (code)
237+
return code;
238+
if (use_sideband)
239+
copy_to_sideband(proc.err, -1, NULL);
240+
return finish_command(&proc);
195241
}
196242

197243
static int is_ref_checked_out(const char *ref)
@@ -368,8 +414,9 @@ static char update_post_hook[] = "hooks/post-update";
368414
static void run_update_post_hook(struct command *cmd)
369415
{
370416
struct command *cmd_p;
371-
int argc, status;
417+
int argc;
372418
const char **argv;
419+
struct child_process proc;
373420

374421
for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
375422
if (cmd_p->error_string)
@@ -391,8 +438,18 @@ static void run_update_post_hook(struct command *cmd)
391438
argc++;
392439
}
393440
argv[argc] = NULL;
394-
status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
395-
| RUN_COMMAND_STDOUT_TO_STDERR);
441+
442+
memset(&proc, 0, sizeof(proc));
443+
proc.no_stdin = 1;
444+
proc.stdout_to_stderr = 1;
445+
proc.err = use_sideband ? -1 : 0;
446+
proc.argv = argv;
447+
448+
if (!start_command(&proc)) {
449+
if (use_sideband)
450+
copy_to_sideband(proc.err, -1, NULL);
451+
finish_command(&proc);
452+
}
396453
}
397454

398455
static void execute_commands(const char *unpacker_error)
@@ -452,6 +509,8 @@ static void read_head_info(void)
452509
if (reflen + 82 < len) {
453510
if (strstr(refname + reflen + 1, "report-status"))
454511
report_status = 1;
512+
if (strstr(refname + reflen + 1, "side-band-64k"))
513+
use_sideband = LARGE_PACKET_MAX;
455514
}
456515
cmd = xmalloc(sizeof(struct command) + len - 80);
457516
hashcpy(cmd->old_sha1, old_sha1);
@@ -551,17 +610,25 @@ static const char *unpack(void)
551610
static void report(const char *unpack_status)
552611
{
553612
struct command *cmd;
554-
packet_write(1, "unpack %s\n",
555-
unpack_status ? unpack_status : "ok");
613+
struct strbuf buf = STRBUF_INIT;
614+
615+
packet_buf_write(&buf, "unpack %s\n",
616+
unpack_status ? unpack_status : "ok");
556617
for (cmd = commands; cmd; cmd = cmd->next) {
557618
if (!cmd->error_string)
558-
packet_write(1, "ok %s\n",
559-
cmd->ref_name);
619+
packet_buf_write(&buf, "ok %s\n",
620+
cmd->ref_name);
560621
else
561-
packet_write(1, "ng %s %s\n",
562-
cmd->ref_name, cmd->error_string);
622+
packet_buf_write(&buf, "ng %s %s\n",
623+
cmd->ref_name, cmd->error_string);
563624
}
564-
packet_flush(1);
625+
packet_buf_flush(&buf);
626+
627+
if (use_sideband)
628+
send_sideband(1, 1, buf.buf, buf.len, use_sideband);
629+
else
630+
safe_write(1, buf.buf, buf.len);
631+
strbuf_release(&buf);
565632
}
566633

567634
static int delete_only(struct command *cmd)
@@ -658,10 +725,6 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
658725
else if (0 <= receive_unpack_limit)
659726
unpack_limit = receive_unpack_limit;
660727

661-
capabilities_to_send = (prefer_ofs_delta) ?
662-
" report-status delete-refs ofs-delta " :
663-
" report-status delete-refs ";
664-
665728
if (advertise_refs || !stateless_rpc) {
666729
add_alternate_refs();
667730
write_head_info();
@@ -695,5 +758,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
695758
if (auto_update_server_info)
696759
update_server_info(0);
697760
}
761+
if (use_sideband)
762+
packet_flush(1);
698763
return 0;
699764
}

0 commit comments

Comments
 (0)