mirror of
https://github.com/git/git.git
synced 2024-11-13 20:53:02 +01:00
Merge branch 'js/run-command'
* js/run-command: start_command(), if .in/.out > 0, closes file descriptors, not the callers start_command(), .in/.out/.err = -1: Callers must close the file descriptor
This commit is contained in:
commit
f79ff5c975
8 changed files with 58 additions and 22 deletions
|
@ -538,8 +538,10 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
||||||
cmd.git_cmd = 1;
|
cmd.git_cmd = 1;
|
||||||
if (start_command(&cmd))
|
if (start_command(&cmd))
|
||||||
die("fetch-pack: unable to fork off %s", argv[0]);
|
die("fetch-pack: unable to fork off %s", argv[0]);
|
||||||
if (do_keep && pack_lockfile)
|
if (do_keep && pack_lockfile) {
|
||||||
*pack_lockfile = index_pack_lockfile(cmd.out);
|
*pack_lockfile = index_pack_lockfile(cmd.out);
|
||||||
|
close(cmd.out);
|
||||||
|
}
|
||||||
|
|
||||||
if (finish_command(&cmd))
|
if (finish_command(&cmd))
|
||||||
die("%s failed", argv[0]);
|
die("%s failed", argv[0]);
|
||||||
|
|
|
@ -71,6 +71,7 @@ static int pack_objects(int fd, struct ref *refs)
|
||||||
refs = refs->next;
|
refs = refs->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(po.in);
|
||||||
if (finish_command(&po))
|
if (finish_command(&po))
|
||||||
return error("pack-objects died with strange error");
|
return error("pack-objects died with strange error");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -403,12 +404,15 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||||
if (!remote_tail)
|
if (!remote_tail)
|
||||||
remote_tail = &remote_refs;
|
remote_tail = &remote_refs;
|
||||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||||
nr_refspec, refspec, flags))
|
nr_refspec, refspec, flags)) {
|
||||||
|
close(out);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!remote_refs) {
|
if (!remote_refs) {
|
||||||
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
|
||||||
"Perhaps you should specify a branch such as 'master'.\n");
|
"Perhaps you should specify a branch such as 'master'.\n");
|
||||||
|
close(out);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,11 +499,10 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
|
||||||
|
|
||||||
packet_flush(out);
|
packet_flush(out);
|
||||||
if (new_refs && !args.dry_run) {
|
if (new_refs && !args.dry_run) {
|
||||||
if (pack_objects(out, remote_refs) < 0) {
|
if (pack_objects(out, remote_refs) < 0)
|
||||||
close(out);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
close(out);
|
close(out);
|
||||||
|
|
||||||
if (expect_status_report)
|
if (expect_status_report)
|
||||||
|
@ -648,7 +651,7 @@ int send_pack(struct send_pack_args *my_args,
|
||||||
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
|
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
|
||||||
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
|
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
|
||||||
close(fd[0]);
|
close(fd[0]);
|
||||||
close(fd[1]);
|
/* do_send_pack always closes fd[1] */
|
||||||
ret |= finish_connect(conn);
|
ret |= finish_connect(conn);
|
||||||
return !!ret;
|
return !!ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,12 +226,13 @@ static int do_sign(struct strbuf *buffer)
|
||||||
|
|
||||||
if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
|
if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
|
||||||
close(gpg.in);
|
close(gpg.in);
|
||||||
|
close(gpg.out);
|
||||||
finish_command(&gpg);
|
finish_command(&gpg);
|
||||||
return error("gpg did not accept the tag data");
|
return error("gpg did not accept the tag data");
|
||||||
}
|
}
|
||||||
close(gpg.in);
|
close(gpg.in);
|
||||||
gpg.close_in = 0;
|
|
||||||
len = strbuf_read(buffer, gpg.out, 1024);
|
len = strbuf_read(buffer, gpg.out, 1024);
|
||||||
|
close(gpg.out);
|
||||||
|
|
||||||
if (finish_command(&gpg) || !len || len < 0)
|
if (finish_command(&gpg) || !len || len < 0)
|
||||||
return error("gpg failed to sign the tag");
|
return error("gpg failed to sign the tag");
|
||||||
|
|
|
@ -45,14 +45,12 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
|
||||||
memset(&gpg, 0, sizeof(gpg));
|
memset(&gpg, 0, sizeof(gpg));
|
||||||
gpg.argv = args_gpg;
|
gpg.argv = args_gpg;
|
||||||
gpg.in = -1;
|
gpg.in = -1;
|
||||||
gpg.out = 1;
|
|
||||||
args_gpg[2] = path;
|
args_gpg[2] = path;
|
||||||
if (start_command(&gpg))
|
if (start_command(&gpg))
|
||||||
return error("could not run gpg.");
|
return error("could not run gpg.");
|
||||||
|
|
||||||
write_in_full(gpg.in, buf, len);
|
write_in_full(gpg.in, buf, len);
|
||||||
close(gpg.in);
|
close(gpg.in);
|
||||||
gpg.close_in = 0;
|
|
||||||
ret = finish_command(&gpg);
|
ret = finish_command(&gpg);
|
||||||
|
|
||||||
unlink(path);
|
unlink(path);
|
||||||
|
|
6
bundle.c
6
bundle.c
|
@ -333,10 +333,12 @@ int create_bundle(struct bundle_header *header, const char *path,
|
||||||
write_or_die(rls.in, sha1_to_hex(object->sha1), 40);
|
write_or_die(rls.in, sha1_to_hex(object->sha1), 40);
|
||||||
write_or_die(rls.in, "\n", 1);
|
write_or_die(rls.in, "\n", 1);
|
||||||
}
|
}
|
||||||
|
close(rls.in);
|
||||||
if (finish_command(&rls))
|
if (finish_command(&rls))
|
||||||
return error ("pack-objects died");
|
return error ("pack-objects died");
|
||||||
|
if (!bundle_to_stdout)
|
||||||
return bundle_to_stdout ? close(bundle_fd) : commit_lock_file(&lock);
|
commit_lock_file(&lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unbundle(struct bundle_header *header, int bundle_fd)
|
int unbundle(struct bundle_header *header, int bundle_fd)
|
||||||
|
|
|
@ -132,6 +132,7 @@ static int run_hook(const char *hook_name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(proc.in);
|
||||||
return hook_status(finish_command(&proc), hook_name);
|
return hook_status(finish_command(&proc), hook_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +415,7 @@ static const char *unpack(void)
|
||||||
if (start_command(&ip))
|
if (start_command(&ip))
|
||||||
return "index-pack fork failed";
|
return "index-pack fork failed";
|
||||||
pack_lockfile = index_pack_lockfile(ip.out);
|
pack_lockfile = index_pack_lockfile(ip.out);
|
||||||
|
close(ip.out);
|
||||||
status = finish_command(&ip);
|
status = finish_command(&ip);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
reprepare_packed_git();
|
reprepare_packed_git();
|
||||||
|
|
|
@ -20,12 +20,19 @@ int start_command(struct child_process *cmd)
|
||||||
int need_in, need_out, need_err;
|
int need_in, need_out, need_err;
|
||||||
int fdin[2], fdout[2], fderr[2];
|
int fdin[2], fdout[2], fderr[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case of errors we must keep the promise to close FDs
|
||||||
|
* that have been passed in via ->in and ->out.
|
||||||
|
*/
|
||||||
|
|
||||||
need_in = !cmd->no_stdin && cmd->in < 0;
|
need_in = !cmd->no_stdin && cmd->in < 0;
|
||||||
if (need_in) {
|
if (need_in) {
|
||||||
if (pipe(fdin) < 0)
|
if (pipe(fdin) < 0) {
|
||||||
|
if (cmd->out > 0)
|
||||||
|
close(cmd->out);
|
||||||
return -ERR_RUN_COMMAND_PIPE;
|
return -ERR_RUN_COMMAND_PIPE;
|
||||||
|
}
|
||||||
cmd->in = fdin[1];
|
cmd->in = fdin[1];
|
||||||
cmd->close_in = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
need_out = !cmd->no_stdout
|
need_out = !cmd->no_stdout
|
||||||
|
@ -35,10 +42,11 @@ int start_command(struct child_process *cmd)
|
||||||
if (pipe(fdout) < 0) {
|
if (pipe(fdout) < 0) {
|
||||||
if (need_in)
|
if (need_in)
|
||||||
close_pair(fdin);
|
close_pair(fdin);
|
||||||
|
else if (cmd->in)
|
||||||
|
close(cmd->in);
|
||||||
return -ERR_RUN_COMMAND_PIPE;
|
return -ERR_RUN_COMMAND_PIPE;
|
||||||
}
|
}
|
||||||
cmd->out = fdout[0];
|
cmd->out = fdout[0];
|
||||||
cmd->close_out = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
need_err = !cmd->no_stderr && cmd->err < 0;
|
need_err = !cmd->no_stderr && cmd->err < 0;
|
||||||
|
@ -46,8 +54,12 @@ int start_command(struct child_process *cmd)
|
||||||
if (pipe(fderr) < 0) {
|
if (pipe(fderr) < 0) {
|
||||||
if (need_in)
|
if (need_in)
|
||||||
close_pair(fdin);
|
close_pair(fdin);
|
||||||
|
else if (cmd->in)
|
||||||
|
close(cmd->in);
|
||||||
if (need_out)
|
if (need_out)
|
||||||
close_pair(fdout);
|
close_pair(fdout);
|
||||||
|
else if (cmd->out)
|
||||||
|
close(cmd->out);
|
||||||
return -ERR_RUN_COMMAND_PIPE;
|
return -ERR_RUN_COMMAND_PIPE;
|
||||||
}
|
}
|
||||||
cmd->err = fderr[0];
|
cmd->err = fderr[0];
|
||||||
|
@ -57,8 +69,12 @@ int start_command(struct child_process *cmd)
|
||||||
if (cmd->pid < 0) {
|
if (cmd->pid < 0) {
|
||||||
if (need_in)
|
if (need_in)
|
||||||
close_pair(fdin);
|
close_pair(fdin);
|
||||||
|
else if (cmd->in)
|
||||||
|
close(cmd->in);
|
||||||
if (need_out)
|
if (need_out)
|
||||||
close_pair(fdout);
|
close_pair(fdout);
|
||||||
|
else if (cmd->out)
|
||||||
|
close(cmd->out);
|
||||||
if (need_err)
|
if (need_err)
|
||||||
close_pair(fderr);
|
close_pair(fderr);
|
||||||
return -ERR_RUN_COMMAND_FORK;
|
return -ERR_RUN_COMMAND_FORK;
|
||||||
|
@ -120,7 +136,7 @@ int start_command(struct child_process *cmd)
|
||||||
|
|
||||||
if (need_out)
|
if (need_out)
|
||||||
close(fdout[1]);
|
close(fdout[1]);
|
||||||
else if (cmd->out > 1)
|
else if (cmd->out)
|
||||||
close(cmd->out);
|
close(cmd->out);
|
||||||
|
|
||||||
if (need_err)
|
if (need_err)
|
||||||
|
@ -157,10 +173,6 @@ static int wait_or_whine(pid_t pid)
|
||||||
|
|
||||||
int finish_command(struct child_process *cmd)
|
int finish_command(struct child_process *cmd)
|
||||||
{
|
{
|
||||||
if (cmd->close_in)
|
|
||||||
close(cmd->in);
|
|
||||||
if (cmd->close_out)
|
|
||||||
close(cmd->out);
|
|
||||||
return wait_or_whine(cmd->pid);
|
return wait_or_whine(cmd->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,29 @@ enum {
|
||||||
struct child_process {
|
struct child_process {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
/*
|
||||||
|
* Using .in, .out, .err:
|
||||||
|
* - Specify 0 for no redirections (child inherits stdin, stdout,
|
||||||
|
* stderr from parent).
|
||||||
|
* - Specify -1 to have a pipe allocated as follows:
|
||||||
|
* .in: returns the writable pipe end; parent writes to it,
|
||||||
|
* the readable pipe end becomes child's stdin
|
||||||
|
* .out, .err: returns the readable pipe end; parent reads from
|
||||||
|
* it, the writable pipe end becomes child's stdout/stderr
|
||||||
|
* The caller of start_command() must close the returned FDs
|
||||||
|
* after it has completed reading from/writing to it!
|
||||||
|
* - Specify > 0 to set a channel to a particular FD as follows:
|
||||||
|
* .in: a readable FD, becomes child's stdin
|
||||||
|
* .out: a writable FD, becomes child's stdout/stderr
|
||||||
|
* .err > 0 not supported
|
||||||
|
* The specified FD is closed by start_command(), even in case
|
||||||
|
* of errors!
|
||||||
|
*/
|
||||||
int in;
|
int in;
|
||||||
int out;
|
int out;
|
||||||
int err;
|
int err;
|
||||||
const char *dir;
|
const char *dir;
|
||||||
const char *const *env;
|
const char *const *env;
|
||||||
unsigned close_in:1;
|
|
||||||
unsigned close_out:1;
|
|
||||||
unsigned no_stdin:1;
|
unsigned no_stdin:1;
|
||||||
unsigned no_stdout:1;
|
unsigned no_stdout:1;
|
||||||
unsigned no_stderr:1;
|
unsigned no_stderr:1;
|
||||||
|
|
Loading…
Reference in a new issue