Skip to content

Commit

Permalink
upload-archive: use start_command instead of fork
Browse files Browse the repository at this point in the history
The POSIX-function fork is not supported on Windows. Use our
start_command API instead, respawning ourselves in a special
"writer" mode to follow the alternate code path.

Remove the NOT_MINGW-prereq for t5000, as git-archive --remote
now works.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
peff authored and gitster committed Nov 21, 2011
1 parent f56ef11 commit 1bc01ef
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 36 deletions.
1 change: 1 addition & 0 deletions builtin.h
Expand Up @@ -133,6 +133,7 @@ extern int cmd_update_index(int argc, const char **argv, const char *prefix);
extern int cmd_update_ref(int argc, const char **argv, const char *prefix); extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
extern int cmd_update_server_info(int argc, const char **argv, const char *prefix); extern int cmd_update_server_info(int argc, const char **argv, const char *prefix);
extern int cmd_upload_archive(int argc, const char **argv, const char *prefix); extern int cmd_upload_archive(int argc, const char **argv, const char *prefix);
extern int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix);
extern int cmd_upload_tar(int argc, const char **argv, const char *prefix); extern int cmd_upload_tar(int argc, const char **argv, const char *prefix);
extern int cmd_var(int argc, const char **argv, const char *prefix); extern int cmd_var(int argc, const char **argv, const char *prefix);
extern int cmd_verify_tag(int argc, const char **argv, const char *prefix); extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
Expand Down
43 changes: 12 additions & 31 deletions builtin/upload-archive.c
Expand Up @@ -6,19 +6,17 @@
#include "archive.h" #include "archive.h"
#include "pkt-line.h" #include "pkt-line.h"
#include "sideband.h" #include "sideband.h"
#include "run-command.h"


static const char upload_archive_usage[] = static const char upload_archive_usage[] =
"git upload-archive <repo>"; "git upload-archive <repo>";


static const char deadchild[] = static const char deadchild[] =
"git upload-archive: archiver died with error"; "git upload-archive: archiver died with error";


static const char lostchild[] =
"git upload-archive: archiver process was lost";

#define MAX_ARGS (64) #define MAX_ARGS (64)


static int run_upload_archive(int argc, const char **argv, const char *prefix) int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
{ {
const char *sent_argv[MAX_ARGS]; const char *sent_argv[MAX_ARGS];
const char *arg_cmd = "argument "; const char *arg_cmd = "argument ";
Expand Down Expand Up @@ -96,48 +94,33 @@ static ssize_t process_input(int child_fd, int band)


int cmd_upload_archive(int argc, const char **argv, const char *prefix) int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{ {
pid_t writer; struct child_process writer = { argv };
int fd1[2], fd2[2];
/* /*
* Set up sideband subprocess. * Set up sideband subprocess.
* *
* We (parent) monitor and read from child, sending its fd#1 and fd#2 * We (parent) monitor and read from child, sending its fd#1 and fd#2
* multiplexed out to our fd#1. If the child dies, we tell the other * multiplexed out to our fd#1. If the child dies, we tell the other
* end over channel #3. * end over channel #3.
*/ */
if (pipe(fd1) < 0 || pipe(fd2) < 0) { argv[0] = "upload-archive--writer";
int err = errno; writer.out = writer.err = -1;
packet_write(1, "NACK pipe failed on the remote side\n"); writer.git_cmd = 1;
die("upload-archive: %s", strerror(err)); if (start_command(&writer)) {
}
writer = fork();
if (writer < 0) {
int err = errno; int err = errno;
packet_write(1, "NACK fork failed on the remote side\n"); packet_write(1, "NACK unable to spawn subprocess\n");
die("upload-archive: %s", strerror(err)); die("upload-archive: %s", strerror(err));
} }
if (!writer) {
/* child - connect fd#1 and fd#2 to the pipe */
dup2(fd1[1], 1);
dup2(fd2[1], 2);
close(fd1[1]); close(fd2[1]);
close(fd1[0]); close(fd2[0]); /* we do not read from pipe */

exit(run_upload_archive(argc, argv, prefix));
}


/* parent - read from child, multiplex and send out to fd#1 */
close(fd1[1]); close(fd2[1]); /* we do not write to pipe */
packet_write(1, "ACK\n"); packet_write(1, "ACK\n");
packet_flush(1); packet_flush(1);


while (1) { while (1) {
struct pollfd pfd[2]; struct pollfd pfd[2];
int status;


pfd[0].fd = fd1[0]; pfd[0].fd = writer.out;
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
pfd[1].fd = fd2[0]; pfd[1].fd = writer.err;
pfd[1].events = POLLIN; pfd[1].events = POLLIN;
if (poll(pfd, 2, -1) < 0) { if (poll(pfd, 2, -1) < 0) {
if (errno != EINTR) { if (errno != EINTR) {
Expand All @@ -156,9 +139,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
if (process_input(pfd[0].fd, 1)) if (process_input(pfd[0].fd, 1))
continue; continue;


if (waitpid(writer, &status, 0) < 0) if (finish_command(&writer))
error_clnt("%s", lostchild);
else if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
error_clnt("%s", deadchild); error_clnt("%s", deadchild);
packet_flush(1); packet_flush(1);
break; break;
Expand Down
1 change: 1 addition & 0 deletions git.c
Expand Up @@ -434,6 +434,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "update-ref", cmd_update_ref, RUN_SETUP }, { "update-ref", cmd_update_ref, RUN_SETUP },
{ "update-server-info", cmd_update_server_info, RUN_SETUP }, { "update-server-info", cmd_update_server_info, RUN_SETUP },
{ "upload-archive", cmd_upload_archive }, { "upload-archive", cmd_upload_archive },
{ "upload-archive--writer", cmd_upload_archive_writer },
{ "var", cmd_var, RUN_SETUP_GENTLY }, { "var", cmd_var, RUN_SETUP_GENTLY },
{ "verify-pack", cmd_verify_pack }, { "verify-pack", cmd_verify_pack },
{ "verify-tag", cmd_verify_tag, RUN_SETUP }, { "verify-tag", cmd_verify_tag, RUN_SETUP },
Expand Down
10 changes: 5 additions & 5 deletions t/t5000-tar-tree.sh
Expand Up @@ -96,7 +96,7 @@ test_expect_success 'git archive with --output' \
'git archive --output=b4.tar HEAD && 'git archive --output=b4.tar HEAD &&
test_cmp b.tar b4.tar' test_cmp b.tar b4.tar'


test_expect_success NOT_MINGW 'git archive --remote' \ test_expect_success 'git archive --remote' \
'git archive --remote=. HEAD >b5.tar && 'git archive --remote=. HEAD >b5.tar &&
test_cmp b.tar b5.tar' test_cmp b.tar b5.tar'


Expand Down Expand Up @@ -266,7 +266,7 @@ test_expect_success 'archive --list mentions user filter' '
grep "^bar\$" output grep "^bar\$" output
' '


test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' ' test_expect_success 'archive --list shows only enabled remote filters' '
git archive --list --remote=. >output && git archive --list --remote=. >output &&
! grep "^tar\.foo\$" output && ! grep "^tar\.foo\$" output &&
grep "^bar\$" output grep "^bar\$" output
Expand Down Expand Up @@ -298,7 +298,7 @@ test_expect_success 'extension matching requires dot' '
test_cmp b.tar config-implicittar.foo test_cmp b.tar config-implicittar.foo
' '


test_expect_success NOT_MINGW 'only enabled filters are available remotely' ' test_expect_success 'only enabled filters are available remotely' '
test_must_fail git archive --remote=. --format=tar.foo HEAD \ test_must_fail git archive --remote=. --format=tar.foo HEAD \
>remote.tar.foo && >remote.tar.foo &&
git archive --remote=. --format=bar >remote.bar HEAD && git archive --remote=. --format=bar >remote.bar HEAD &&
Expand Down Expand Up @@ -341,12 +341,12 @@ test_expect_success GZIP,GUNZIP 'extract tgz file' '
test_cmp b.tar j.tar test_cmp b.tar j.tar
' '


test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' ' test_expect_success GZIP 'remote tar.gz is allowed by default' '
git archive --remote=. --format=tar.gz HEAD >remote.tar.gz && git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
test_cmp j.tgz remote.tar.gz test_cmp j.tgz remote.tar.gz
' '


test_expect_success GZIP,NOT_MINGW 'remote tar.gz can be disabled' ' test_expect_success GZIP 'remote tar.gz can be disabled' '
git config tar.tar.gz.remote false && git config tar.tar.gz.remote false &&
test_must_fail git archive --remote=. --format=tar.gz HEAD \ test_must_fail git archive --remote=. --format=tar.gz HEAD \
>remote.tar.gz >remote.tar.gz
Expand Down

0 comments on commit 1bc01ef

Please sign in to comment.