mirror of
https://github.com/git/git.git
synced 2026-03-13 10:23:30 +01:00
Merge commit 'mingw/master' into work/towards-mingw
Conflicts: compat/mingw.c exec_cmd.c git-compat-util.h run-command.c spawn-pipe.c
This commit is contained in:
2
Makefile
2
Makefile
@@ -294,7 +294,6 @@ LIB_H = \
|
||||
diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
|
||||
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
|
||||
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
|
||||
spawn-pipe.h \
|
||||
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
|
||||
mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
|
||||
|
||||
@@ -308,7 +307,6 @@ LIB_OBJS = \
|
||||
date.o diff-delta.o entry.o exec_cmd.o ident.o \
|
||||
pretty.o interpolate.o hash.o \
|
||||
lockfile.o \
|
||||
spawn-pipe.o \
|
||||
patch-ids.o \
|
||||
object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
|
||||
sideband.o reachable.o reflog-walk.o \
|
||||
|
||||
@@ -463,34 +463,12 @@ static int sideband_demux(int fd, void *data)
|
||||
{
|
||||
int *xd = data;
|
||||
|
||||
close(xd[1]);
|
||||
return recv_sideband("fetch-pack", xd[0], fd, 2);
|
||||
}
|
||||
|
||||
static void setup_sideband(int fd[2], int xd[2], struct async *demux)
|
||||
{
|
||||
if (!use_sideband) {
|
||||
fd[0] = xd[0];
|
||||
fd[1] = xd[1];
|
||||
return;
|
||||
}
|
||||
/* xd[] is talking with upload-pack; subprocess reads from
|
||||
* xd[0], spits out band#2 to stderr, and feeds us band#1
|
||||
* through demux->out.
|
||||
*/
|
||||
demux->proc = sideband_demux;
|
||||
demux->data = xd;
|
||||
if (start_async(demux))
|
||||
die("fetch-pack: unable to fork off sideband demultiplexer");
|
||||
close(xd[0]);
|
||||
fd[0] = demux->out;
|
||||
fd[1] = xd[1];
|
||||
}
|
||||
|
||||
static int get_pack(int xd[2], char **pack_lockfile)
|
||||
{
|
||||
struct async demux;
|
||||
int fd[2];
|
||||
const char *argv[20];
|
||||
char keep_arg[256];
|
||||
char hdr_arg[256];
|
||||
@@ -498,7 +476,20 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
||||
int do_keep = args.keep_pack;
|
||||
struct child_process cmd;
|
||||
|
||||
setup_sideband(fd, xd, &demux);
|
||||
memset(&demux, 0, sizeof(demux));
|
||||
if (use_sideband) {
|
||||
/* xd[] is talking with upload-pack; subprocess reads from
|
||||
* xd[0], spits out band#2 to stderr, and feeds us band#1
|
||||
* through demux->out.
|
||||
*/
|
||||
demux.proc = sideband_demux;
|
||||
demux.data = xd;
|
||||
if (start_async(&demux))
|
||||
die("fetch-pack: unable to fork off sideband"
|
||||
" demultiplexer");
|
||||
}
|
||||
else
|
||||
demux.out = xd[0];
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.argv = argv;
|
||||
@@ -507,7 +498,7 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
||||
if (!args.keep_pack && unpack_limit) {
|
||||
struct pack_header header;
|
||||
|
||||
if (read_pack_header(fd[0], &header))
|
||||
if (read_pack_header(demux.out, &header))
|
||||
die("protocol error: bad pack header");
|
||||
snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
|
||||
ntohl(header.hdr_version), ntohl(header.hdr_entries));
|
||||
@@ -543,11 +534,10 @@ static int get_pack(int xd[2], char **pack_lockfile)
|
||||
*av++ = hdr_arg;
|
||||
*av++ = NULL;
|
||||
|
||||
cmd.in = fd[0];
|
||||
cmd.in = demux.out;
|
||||
cmd.git_cmd = 1;
|
||||
if (start_command(&cmd))
|
||||
die("fetch-pack: unable to fork off %s", argv[0]);
|
||||
close(fd[1]);
|
||||
if (do_keep && pack_lockfile)
|
||||
*pack_lockfile = index_pack_lockfile(cmd.out);
|
||||
|
||||
@@ -574,7 +564,6 @@ static struct ref *do_fetch_pack(int fd[2],
|
||||
fprintf(stderr, "Server supports multi_ack\n");
|
||||
multi_ack = 1;
|
||||
}
|
||||
#ifndef __MINGW32__
|
||||
if (server_supports("side-band-64k")) {
|
||||
if (args.verbose)
|
||||
fprintf(stderr, "Server supports side-band-64k\n");
|
||||
@@ -585,7 +574,6 @@ static struct ref *do_fetch_pack(int fd[2],
|
||||
fprintf(stderr, "Server supports side-band\n");
|
||||
use_sideband = 1;
|
||||
}
|
||||
#endif
|
||||
if (!ref) {
|
||||
packet_flush(fd[1]);
|
||||
die("no matching remote head");
|
||||
|
||||
104
compat/mingw.c
104
compat/mingw.c
@@ -235,7 +235,7 @@ int pipe(int filedes[2])
|
||||
CloseHandle(h[0]);
|
||||
return -1;
|
||||
}
|
||||
fd = _open_osfhandle( (int) h[0], O_NOINHERIT);
|
||||
fd = _open_osfhandle((int)h[0], O_NOINHERIT);
|
||||
if (fd < 0) {
|
||||
close(filedes[0]);
|
||||
close(filedes[1]);
|
||||
@@ -245,7 +245,7 @@ int pipe(int filedes[2])
|
||||
}
|
||||
close(filedes[0]);
|
||||
filedes[0] = fd;
|
||||
fd = _open_osfhandle( (int) h[1], O_NOINHERIT);
|
||||
fd = _open_osfhandle((int)h[1], O_NOINHERIT);
|
||||
if (fd < 0) {
|
||||
close(filedes[0]);
|
||||
close(filedes[1]);
|
||||
@@ -259,7 +259,62 @@ int pipe(int filedes[2])
|
||||
|
||||
int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
|
||||
{
|
||||
return -1;
|
||||
int i, pending;
|
||||
|
||||
if (timeout != -1)
|
||||
return errno = EINVAL, error("poll timeout not supported");
|
||||
|
||||
/* When there is only one fd to wait for, then we pretend that
|
||||
* input is available and let the actual wait happen when the
|
||||
* caller invokes read().
|
||||
*/
|
||||
if (nfds == 1) {
|
||||
if (!(ufds[0].events & POLLIN))
|
||||
return errno = EINVAL, error("POLLIN not set");
|
||||
ufds[0].revents = POLLIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat:
|
||||
pending = 0;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
DWORD avail = 0;
|
||||
HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return -1; /* errno was set */
|
||||
|
||||
if (!(ufds[i].events & POLLIN))
|
||||
return errno = EINVAL, error("POLLIN not set");
|
||||
|
||||
/* this emulation works only for pipes */
|
||||
if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
|
||||
int err = GetLastError();
|
||||
if (err == ERROR_BROKEN_PIPE) {
|
||||
ufds[i].revents = POLLHUP;
|
||||
pending++;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return error("PeekNamedPipe failed,"
|
||||
" GetLastError: %u", err);
|
||||
}
|
||||
} else if (avail) {
|
||||
ufds[i].revents = POLLIN;
|
||||
pending++;
|
||||
} else
|
||||
ufds[i].revents = 0;
|
||||
}
|
||||
if (!pending) {
|
||||
/* The only times that we spin here is when the process
|
||||
* that is connected through the pipes is waiting for
|
||||
* its own input data to become available. But since
|
||||
* the process (pack-objects) is itself CPU intensive,
|
||||
* it will happily pick up the time slice that we are
|
||||
* relinguishing here.
|
||||
*/
|
||||
Sleep(0);
|
||||
goto repeat;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <time.h>
|
||||
@@ -537,6 +592,45 @@ void mingw_execvp(const char *cmd, char *const *argv)
|
||||
mingw_free_path_split(path);
|
||||
}
|
||||
|
||||
char **copy_environ()
|
||||
{
|
||||
return copy_env(environ);
|
||||
}
|
||||
|
||||
char **copy_env(char **env)
|
||||
{
|
||||
char **s;
|
||||
int n = 1;
|
||||
for (s = env; *s; s++)
|
||||
n++;
|
||||
s = xmalloc(n*sizeof(char *));
|
||||
memcpy(s, env, n*sizeof(char *));
|
||||
return s;
|
||||
}
|
||||
|
||||
void env_unsetenv(char **env, const char *name)
|
||||
{
|
||||
int src, dst;
|
||||
size_t nmln;
|
||||
|
||||
nmln = strlen(name);
|
||||
|
||||
for (src = dst = 0; env[src]; ++src) {
|
||||
size_t enln;
|
||||
enln = strlen(env[src]);
|
||||
if (enln > nmln) {
|
||||
/* might match, and can test for '=' safely */
|
||||
if (0 == strncmp (env[src], name, nmln)
|
||||
&& '=' == env[src][nmln])
|
||||
/* matches, so skip */
|
||||
continue;
|
||||
}
|
||||
env[dst] = env[src];
|
||||
++dst;
|
||||
}
|
||||
env[dst] = NULL;
|
||||
}
|
||||
|
||||
int mingw_socket(int domain, int type, int protocol)
|
||||
{
|
||||
SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);
|
||||
@@ -666,10 +760,10 @@ static int start_timer_thread(void)
|
||||
timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
|
||||
if (!timer_thread )
|
||||
return errno = ENOMEM,
|
||||
error("cannot create progress indicator");
|
||||
error("cannot start timer thread");
|
||||
} else
|
||||
return errno = ENOMEM,
|
||||
error("cannot allocate resources for progress indicator");
|
||||
error("cannot allocate resources timer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "refs.h"
|
||||
#include "run-command.h"
|
||||
#include "remote.h"
|
||||
#include "spawn-pipe.h"
|
||||
|
||||
static char *server_capabilities;
|
||||
|
||||
|
||||
28
exec_cmd.c
28
exec_cmd.c
@@ -1,7 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "quote.h"
|
||||
#include "spawn-pipe.h"
|
||||
#define MAX_ARGS 32
|
||||
|
||||
extern char **environ;
|
||||
@@ -155,30 +154,3 @@ int execl_git_cmd(const char *cmd,...)
|
||||
argv[argc] = NULL;
|
||||
return execv_git_cmd(argv);
|
||||
}
|
||||
|
||||
int spawnv_git_cmd(const char **argv, int pin[2], int pout[2])
|
||||
{
|
||||
pid_t pid;
|
||||
struct strbuf cmd;
|
||||
const char *tmp;
|
||||
|
||||
strbuf_init(&cmd, 0);
|
||||
strbuf_addf(&cmd, "git-%s", argv[0]);
|
||||
|
||||
/* argv[0] must be the git command, but the argv array
|
||||
* belongs to the caller. Save argv[0] and
|
||||
* restore it later.
|
||||
*/
|
||||
|
||||
tmp = argv[0];
|
||||
argv[0] = cmd.buf;
|
||||
|
||||
trace_argv_printf(argv, -1, "trace: exec:");
|
||||
|
||||
pid = spawnvpe_pipe(cmd.buf, argv, (const char **)environ,
|
||||
pin, pout);
|
||||
|
||||
argv[0] = tmp;
|
||||
return pid;
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ extern const char* git_exec_path(void);
|
||||
extern void setup_path(const char *);
|
||||
extern int execv_git_cmd(const char **argv); /* NULL terminated */
|
||||
extern int execl_git_cmd(const char *cmd, ...);
|
||||
extern int spawnv_git_cmd(const char **argv, int pin[2], int pout[2]);
|
||||
|
||||
|
||||
#endif /* GIT_EXEC_CMD_H */
|
||||
|
||||
@@ -480,6 +480,10 @@ static inline int waitpid(pid_t pid, unsigned *status, unsigned options)
|
||||
#define SIGCHLD 0
|
||||
#define SIGPIPE 0
|
||||
|
||||
char **copy_environ();
|
||||
char **copy_env(char **env);
|
||||
void env_unsetenv(char **env, const char *name);
|
||||
|
||||
unsigned int sleep (unsigned int __seconds);
|
||||
const char *inet_ntop(int af, const void *src,
|
||||
char *dst, size_t cnt);
|
||||
|
||||
161
run-command.c
161
run-command.c
@@ -1,7 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "run-command.h"
|
||||
#include "exec_cmd.h"
|
||||
#include "spawn-pipe.h"
|
||||
|
||||
static inline void close_pair(int fd[2])
|
||||
{
|
||||
@@ -9,13 +8,17 @@ static inline void close_pair(int fd[2])
|
||||
close(fd[1]);
|
||||
}
|
||||
|
||||
static inline void dup_devnull(int to)
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
dup2(fd, to);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int start_command(struct child_process *cmd)
|
||||
{
|
||||
int need_in, need_out, need_err;
|
||||
int fdin[2] = { -1, -1 };
|
||||
int fdout[2] = { -1, -1 };
|
||||
int fderr[2] = { -1, -1 };
|
||||
const char **env = (const char **)environ;
|
||||
int fdin[2], fdout[2], fderr[2];
|
||||
|
||||
need_in = !cmd->no_stdin && cmd->in < 0;
|
||||
if (need_in) {
|
||||
@@ -50,53 +53,150 @@ int start_command(struct child_process *cmd)
|
||||
cmd->err = fderr[0];
|
||||
}
|
||||
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
cmd->pid = fork();
|
||||
if (!cmd->pid) {
|
||||
if (cmd->no_stdin)
|
||||
fdin[0] = open("/dev/null", O_RDWR);
|
||||
dup_devnull(0);
|
||||
else if (need_in) {
|
||||
/* nothing */
|
||||
dup2(fdin[0], 0);
|
||||
close_pair(fdin);
|
||||
} else if (cmd->in) {
|
||||
fdin[0] = cmd->in;
|
||||
dup2(cmd->in, 0);
|
||||
close(cmd->in);
|
||||
}
|
||||
|
||||
if (cmd->no_stdout)
|
||||
fdout[1] = open("/dev/null", O_RDWR);
|
||||
dup_devnull(1);
|
||||
else if (cmd->stdout_to_stderr)
|
||||
fdout[1] = dup(2);
|
||||
dup2(2, 1);
|
||||
else if (need_out) {
|
||||
/* nothing */
|
||||
dup2(fdout[1], 1);
|
||||
close_pair(fdout);
|
||||
} else if (cmd->out > 1) {
|
||||
fdout[1] = cmd->out;
|
||||
dup2(cmd->out, 1);
|
||||
close(cmd->out);
|
||||
}
|
||||
|
||||
if (cmd->no_stderr)
|
||||
fderr[1] = open("/dev/null", O_RDWR);
|
||||
dup_devnull(2);
|
||||
else if (need_err) {
|
||||
/* nothing */
|
||||
dup2(fderr[1], 2);
|
||||
close_pair(fderr);
|
||||
}
|
||||
|
||||
if (cmd->dir)
|
||||
die("chdir in start_command() not implemented");
|
||||
if (cmd->dir && chdir(cmd->dir))
|
||||
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
|
||||
cmd->dir, strerror(errno));
|
||||
if (cmd->env) {
|
||||
if (cmd->git_cmd)
|
||||
die("modifying environment for git_cmd in start_command() not implemented");
|
||||
env = copy_environ();
|
||||
for (; *cmd->env; cmd->env++) {
|
||||
if (strchr(*cmd->env, '='))
|
||||
die("setting environment in start_command() not implemented");
|
||||
putenv((char*)*cmd->env);
|
||||
else
|
||||
env_unsetenv(env, *cmd->env);
|
||||
unsetenv(*cmd->env);
|
||||
}
|
||||
}
|
||||
if (cmd->git_cmd) {
|
||||
cmd->pid = spawnv_git_cmd(cmd->argv, fdin, fdout);
|
||||
execv_git_cmd(cmd->argv);
|
||||
} else {
|
||||
cmd->pid = spawnvpe_pipe(cmd->argv[0], cmd->argv, env, fdin, fdout);
|
||||
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
||||
}
|
||||
die("exec %s failed.", cmd->argv[0]);
|
||||
}
|
||||
#else
|
||||
int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
|
||||
const char *sargv0 = cmd->argv[0];
|
||||
char **env = environ;
|
||||
struct strbuf git_cmd;
|
||||
|
||||
if (cmd->no_stdin) {
|
||||
s0 = dup(0);
|
||||
dup_devnull(0);
|
||||
} else if (need_in) {
|
||||
s0 = dup(0);
|
||||
dup2(fdin[0], 0);
|
||||
} else if (cmd->in) {
|
||||
s0 = dup(0);
|
||||
dup2(cmd->in, 0);
|
||||
}
|
||||
|
||||
if (cmd->no_stdout) {
|
||||
s1 = dup(1);
|
||||
dup_devnull(1);
|
||||
} else if (cmd->stdout_to_stderr) {
|
||||
s1 = dup(1);
|
||||
dup2(2, 1);
|
||||
} else if (need_out) {
|
||||
s1 = dup(1);
|
||||
dup2(fdout[1], 1);
|
||||
} else if (cmd->out > 1) {
|
||||
s1 = dup(1);
|
||||
dup2(cmd->out, 1);
|
||||
}
|
||||
|
||||
if (cmd->no_stderr) {
|
||||
s2 = dup(2);
|
||||
dup_devnull(2);
|
||||
} else if (need_err) {
|
||||
s2 = dup(2);
|
||||
dup2(fderr[1], 2);
|
||||
}
|
||||
|
||||
if (cmd->dir)
|
||||
die("chdir in start_command() not implemented");
|
||||
if (cmd->env) {
|
||||
env = copy_environ();
|
||||
for (; *cmd->env; cmd->env++) {
|
||||
if (strchr(*cmd->env, '='))
|
||||
die("setting environment in start_command() not implemented");
|
||||
else
|
||||
env_unsetenv(env, *cmd->env);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->git_cmd) {
|
||||
strbuf_init(&git_cmd, 0);
|
||||
strbuf_addf(&git_cmd, "git-%s", cmd->argv[0]);
|
||||
cmd->argv[0] = git_cmd.buf;
|
||||
}
|
||||
|
||||
char **path = mingw_get_path_split();
|
||||
const char *argv0 = cmd->argv[0];
|
||||
const char **qargv;
|
||||
char *prog = mingw_path_lookup(argv0, path);
|
||||
const char *interpr = parse_interpreter(prog);
|
||||
int argc;
|
||||
|
||||
for (argc = 0; cmd->argv[argc];) argc++;
|
||||
qargv = xmalloc((argc+2)*sizeof(char*));
|
||||
if (!interpr) {
|
||||
quote_argv(qargv, cmd->argv);
|
||||
cmd->pid = spawnve(_P_NOWAIT, prog, qargv, (const char **)env);
|
||||
} else {
|
||||
qargv[0] = interpr;
|
||||
cmd->argv[0] = prog;
|
||||
quote_argv(&qargv[1], cmd->argv);
|
||||
cmd->pid = spawnvpe(_P_NOWAIT, interpr, qargv, (const char **)env);
|
||||
}
|
||||
|
||||
free(qargv); /* TODO: quoted args should be freed, too */
|
||||
free(prog);
|
||||
|
||||
mingw_free_path_split(path);
|
||||
/* TODO: if (cmd->env) free env; */
|
||||
|
||||
if (cmd->git_cmd)
|
||||
strbuf_release(&git_cmd);
|
||||
|
||||
cmd->argv[0] = sargv0;
|
||||
if (s0 >= 0)
|
||||
dup2(s0, 0), close(s0);
|
||||
if (s1 >= 0)
|
||||
dup2(s1, 1), close(s1);
|
||||
if (s2 >= 0)
|
||||
dup2(s2, 2), close(s2);
|
||||
#endif
|
||||
|
||||
if (cmd->pid < 0) {
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
@@ -107,6 +207,19 @@ int start_command(struct child_process *cmd)
|
||||
return -ERR_RUN_COMMAND_FORK;
|
||||
}
|
||||
|
||||
if (need_in)
|
||||
close(fdin[0]);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
|
||||
if (need_out)
|
||||
close(fdout[1]);
|
||||
else if (cmd->out > 1)
|
||||
close(cmd->out);
|
||||
|
||||
if (need_err)
|
||||
close(fderr[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
169
spawn-pipe.c
169
spawn-pipe.c
@@ -1,169 +0,0 @@
|
||||
#include "git-compat-util.h"
|
||||
#include "spawn-pipe.h"
|
||||
|
||||
|
||||
/* cmd specifies the command to invoke.
|
||||
* argv specifies its arguments; argv[0] will be replaced by the basename of cmd.
|
||||
* env specifies the environment.
|
||||
* pin and pout specify pipes; the read end of pin is made the standard input
|
||||
* of the spawned process, and the write end of pout is mad the standard output.
|
||||
* The respective unused ends of the pipes are closed both in the parent
|
||||
* process as well as in the child process.
|
||||
* Anyone of pin or pout can be NULL, or any one of the ends can be -1 to
|
||||
* indicate that no processing shall occur.
|
||||
*/
|
||||
int spawnvpe_pipe(const char *cmd, const char **argv, const char **env,
|
||||
int pin[], int pout[])
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
char **path = mingw_get_path_split();
|
||||
|
||||
pid_t pid = spawnvppe_pipe(cmd, argv, env, path, pin, pout);
|
||||
|
||||
mingw_free_path_split(path);
|
||||
#else
|
||||
pid_t pid = spawnvppe_pipe(cmd, argv, env, NULL, pin, pout);
|
||||
#endif
|
||||
return pid;
|
||||
}
|
||||
|
||||
int spawnvppe_pipe(const char *cmd, const char **argv, const char **env,
|
||||
char **path,
|
||||
int pin[], int pout[])
|
||||
{
|
||||
const char *cmd_basename = strrchr(cmd, '/');
|
||||
const char *argv0 = argv[0];
|
||||
pid_t pid;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
int s0 = -1, s1 = -1, argc;
|
||||
char *prog;
|
||||
const char **qargv, *interpr;
|
||||
|
||||
if (!cmd_basename)
|
||||
cmd_basename = strrchr(cmd, '\\');
|
||||
#endif
|
||||
|
||||
if (!cmd_basename)
|
||||
cmd_basename = cmd;
|
||||
else
|
||||
cmd_basename++;
|
||||
argv[0] = cmd_basename;
|
||||
|
||||
#ifndef __MINGW32__
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
die("unable to fork");
|
||||
if (!pid) {
|
||||
if (pin) {
|
||||
if (pin[0] >= 0) {
|
||||
dup2(pin[0], 0);
|
||||
close(pin[0]);
|
||||
}
|
||||
if (pin[1] >= 0)
|
||||
close(pin[1]);
|
||||
}
|
||||
if (pout) {
|
||||
if (pout[1] >= 0) {
|
||||
dup2(pout[1], 1);
|
||||
close(pout[1]);
|
||||
}
|
||||
if (pout[0] >= 0)
|
||||
close(pout[0]);
|
||||
}
|
||||
environ = env;
|
||||
execvp(cmd, argv);
|
||||
die("exec failed");
|
||||
}
|
||||
|
||||
if (pin && pin[0] >= 0)
|
||||
close(pin[0]);
|
||||
if (pout && pout[1] >= 1)
|
||||
close(pout[1]);
|
||||
#else
|
||||
if (pin) {
|
||||
if (pin[0] >= 0) {
|
||||
s0 = dup(0);
|
||||
dup2(pin[0], 0);
|
||||
close(pin[0]);
|
||||
}
|
||||
}
|
||||
if (pout) {
|
||||
if (pout[1] >= 0) {
|
||||
s1 = dup(1);
|
||||
dup2(pout[1], 1);
|
||||
close(pout[1]);
|
||||
}
|
||||
}
|
||||
|
||||
prog = mingw_path_lookup(cmd, path);
|
||||
interpr = parse_interpreter(prog);
|
||||
|
||||
for (argc = 0; argv[argc];) argc++;
|
||||
qargv = xmalloc((argc+2)*sizeof(char*));
|
||||
if (!interpr) {
|
||||
quote_argv(qargv, argv);
|
||||
pid = spawnve(_P_NOWAIT, prog, qargv, env);
|
||||
} else {
|
||||
qargv[0] = interpr;
|
||||
argv[0] = prog;
|
||||
quote_argv(&qargv[1], argv);
|
||||
pid = spawnvpe(_P_NOWAIT, interpr, qargv, env);
|
||||
}
|
||||
|
||||
free(qargv); /* TODO: quoted args should be freed, too */
|
||||
free(prog);
|
||||
|
||||
if (s0 >= 0) {
|
||||
dup2(s0, 0);
|
||||
close(s0);
|
||||
}
|
||||
if (s1 >= 0) {
|
||||
dup2(s1, 1);
|
||||
close(s1);
|
||||
}
|
||||
#endif
|
||||
|
||||
argv[0] = argv0;
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
const char **copy_environ()
|
||||
{
|
||||
return copy_env( (const char**)environ);
|
||||
}
|
||||
|
||||
const char **copy_env(const char **env)
|
||||
{
|
||||
const char **s;
|
||||
int n = 1;
|
||||
for (s = env; *s; s++)
|
||||
n++;
|
||||
s = xmalloc(n*sizeof(const char *));
|
||||
memcpy(s, env, n*sizeof(const char *));
|
||||
return s;
|
||||
}
|
||||
|
||||
void env_unsetenv(const char **env, const char *name)
|
||||
{
|
||||
int src, dst;
|
||||
size_t nmln;
|
||||
|
||||
nmln = strlen(name);
|
||||
|
||||
for (src = dst = 0; env[src]; ++src) {
|
||||
size_t enln;
|
||||
enln = strlen(env[src]);
|
||||
if (enln > nmln) {
|
||||
/* might match, and can test for '=' safely */
|
||||
if (0 == strncmp (env[src], name, nmln)
|
||||
&& '=' == env[src][nmln])
|
||||
/* matches, so skip */
|
||||
continue;
|
||||
}
|
||||
env[dst] = env[src];
|
||||
++dst;
|
||||
}
|
||||
env[dst] = NULL;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
int spawnvppe_pipe(const char *cmd, const char **argv, const char **env, char **path, int pin[], int pout[]);
|
||||
int spawnvpe_pipe(const char *cmd, const char **argv, const char **env, int pin[], int pout[]);
|
||||
const char **copy_environ();
|
||||
const char **copy_env(const char **env);
|
||||
void env_unsetenv(const char **env, const char *name);
|
||||
@@ -142,10 +142,7 @@ static void create_pack_file(void)
|
||||
struct async rev_list;
|
||||
struct child_process pack_objects;
|
||||
int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
|
||||
char data[8193];
|
||||
#ifndef __MINGW32__
|
||||
char progress[128];
|
||||
#endif
|
||||
char data[8193], progress[128];
|
||||
char abort_msg[] = "aborting due to possible repository "
|
||||
"corruption on the remote side.";
|
||||
int buffered = -1;
|
||||
@@ -177,7 +174,6 @@ static void create_pack_file(void)
|
||||
if (start_command(&pack_objects))
|
||||
die("git-upload-pack: unable to fork git-pack-objects");
|
||||
|
||||
#ifndef __MINGW32__
|
||||
/* We read from pack_objects.err to capture stderr output for
|
||||
* progress bar, and pack_objects.out to capture the pack data.
|
||||
*/
|
||||
@@ -268,41 +264,6 @@ static void create_pack_file(void)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#else
|
||||
char *cp;
|
||||
|
||||
/* We read from pack_objects.out to capture the pack data. */
|
||||
|
||||
while ((sz = xread(pack_objects.out, data+1, sizeof(data)-1)) > 0) {
|
||||
cp = data+1;
|
||||
/* Data ready; we keep the last byte to ourselves in case we
|
||||
* detect broken rev-list, so that we can leave the stream
|
||||
* corrupted. This is unfortunate -- unpack-objects would
|
||||
* happily accept a valid pack data with trailing garbage, so
|
||||
* appending garbage after we pass all the pack data is not
|
||||
* good enough to signal breakage to downstream.
|
||||
*/
|
||||
if (0 <= buffered) {
|
||||
*--cp = buffered;
|
||||
sz++;
|
||||
}
|
||||
if (1 < sz) {
|
||||
buffered = cp[sz-1] & 0xFF;
|
||||
sz--;
|
||||
}
|
||||
else
|
||||
buffered = -1;
|
||||
sz = send_client_data(1, cp, sz);
|
||||
if (sz < 0)
|
||||
goto fail;
|
||||
}
|
||||
if (sz == 0) {
|
||||
close(pack_objects.out);
|
||||
pack_objects.out = -1;
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if (finish_command(&pack_objects)) {
|
||||
error("git-upload-pack: git-pack-objects died with error.");
|
||||
@@ -524,12 +485,10 @@ static void receive_needs(void)
|
||||
use_thin_pack = 1;
|
||||
if (strstr(line+45, "ofs-delta"))
|
||||
use_ofs_delta = 1;
|
||||
#ifndef __MINGW32__
|
||||
if (strstr(line+45, "side-band-64k"))
|
||||
use_sideband = LARGE_PACKET_MAX;
|
||||
else if (strstr(line+45, "side-band"))
|
||||
use_sideband = DEFAULT_PACKET_MAX;
|
||||
#endif
|
||||
if (strstr(line+45, "no-progress"))
|
||||
no_progress = 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user