Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2006 Franck Bui-Huu |
| 3 | */ |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 4 | #include "cache.h" |
| 5 | #include "builtin.h" |
| 6 | #include "archive.h" |
| 7 | #include "pkt-line.h" |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 8 | #include "sideband.h" |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 9 | #include "run-command.h" |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 10 | |
| 11 | static const char upload_archive_usage[] = |
Stephan Beyer | 1b1dd23 | 2008-07-13 15:36:15 +0200 | [diff] [blame] | 12 | "git upload-archive <repo>"; |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 13 | |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 14 | static const char deadchild[] = |
Stephan Beyer | 1b1dd23 | 2008-07-13 15:36:15 +0200 | [diff] [blame] | 15 | "git upload-archive: archiver died with error"; |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 16 | |
Rene Scharfe | 7f4d051 | 2008-07-25 12:41:23 +0200 | [diff] [blame] | 17 | #define MAX_ARGS (64) |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 18 | |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 19 | int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 20 | { |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 21 | const char *sent_argv[MAX_ARGS]; |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 22 | const char *arg_cmd = "argument "; |
| 23 | char *p, buf[4096]; |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 24 | int sent_argc; |
| 25 | int len; |
| 26 | |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 27 | if (argc != 2) |
| 28 | usage(upload_archive_usage); |
| 29 | |
| 30 | if (strlen(argv[1]) + 1 > sizeof(buf)) |
| 31 | die("insanely long repository name"); |
| 32 | |
| 33 | strcpy(buf, argv[1]); /* enter-repo smudges its argument */ |
| 34 | |
| 35 | if (!enter_repo(buf, 0)) |
| 36 | die("'%s' does not appear to be a git repository", buf); |
| 37 | |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 38 | /* put received options in sent_argv[] */ |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 39 | sent_argc = 1; |
| 40 | sent_argv[0] = "git-upload-archive"; |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 41 | for (p = buf;;) { |
| 42 | /* This will die if not enough free space in buf */ |
| 43 | len = packet_read_line(0, p, (buf + sizeof buf) - p); |
| 44 | if (len == 0) |
| 45 | break; /* got a flush */ |
| 46 | if (sent_argc > MAX_ARGS - 2) |
Rene Scharfe | 7f4d051 | 2008-07-25 12:41:23 +0200 | [diff] [blame] | 47 | die("Too many options (>%d)", MAX_ARGS - 2); |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 48 | |
| 49 | if (p[len-1] == '\n') { |
| 50 | p[--len] = 0; |
| 51 | } |
| 52 | if (len < strlen(arg_cmd) || |
| 53 | strncmp(arg_cmd, p, strlen(arg_cmd))) |
| 54 | die("'argument' token or flush expected"); |
| 55 | |
| 56 | len -= strlen(arg_cmd); |
| 57 | memmove(p, p + strlen(arg_cmd), len); |
| 58 | sent_argv[sent_argc++] = p; |
| 59 | p += len; |
| 60 | *p++ = 0; |
| 61 | } |
| 62 | sent_argv[sent_argc] = NULL; |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 63 | |
| 64 | /* parse all options sent by the client */ |
| 65 | return write_archive(sent_argc, sent_argv, prefix, 0, NULL, 1); |
Franck Bui-Huu | 39345a2 | 2006-09-07 15:12:05 +0200 | [diff] [blame] | 66 | } |
| 67 | |
Tarmigan Casebolt | 28bea9e | 2009-11-14 13:33:13 -0800 | [diff] [blame] | 68 | __attribute__((format (printf, 1, 2))) |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 69 | static void error_clnt(const char *fmt, ...) |
| 70 | { |
| 71 | char buf[1024]; |
| 72 | va_list params; |
| 73 | int len; |
| 74 | |
| 75 | va_start(params, fmt); |
| 76 | len = vsprintf(buf, fmt, params); |
| 77 | va_end(params); |
| 78 | send_sideband(1, 3, buf, len, LARGE_PACKET_MAX); |
| 79 | die("sent error to the client: %s", buf); |
| 80 | } |
| 81 | |
René Scharfe | 1b19fa4 | 2009-06-17 12:11:10 +0200 | [diff] [blame] | 82 | static ssize_t process_input(int child_fd, int band) |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 83 | { |
| 84 | char buf[16384]; |
| 85 | ssize_t sz = read(child_fd, buf, sizeof(buf)); |
| 86 | if (sz < 0) { |
Andy Whitcroft | 93d26e4 | 2007-01-08 15:58:08 +0000 | [diff] [blame] | 87 | if (errno != EAGAIN && errno != EINTR) |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 88 | error_clnt("read error: %s\n", strerror(errno)); |
René Scharfe | 1b19fa4 | 2009-06-17 12:11:10 +0200 | [diff] [blame] | 89 | return sz; |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 90 | } |
| 91 | send_sideband(1, band, buf, sz, LARGE_PACKET_MAX); |
René Scharfe | 1b19fa4 | 2009-06-17 12:11:10 +0200 | [diff] [blame] | 92 | return sz; |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 93 | } |
| 94 | |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 95 | int cmd_upload_archive(int argc, const char **argv, const char *prefix) |
| 96 | { |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 97 | struct child_process writer = { argv }; |
| 98 | |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 99 | /* |
| 100 | * Set up sideband subprocess. |
| 101 | * |
| 102 | * We (parent) monitor and read from child, sending its fd#1 and fd#2 |
| 103 | * multiplexed out to our fd#1. If the child dies, we tell the other |
| 104 | * end over channel #3. |
| 105 | */ |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 106 | argv[0] = "upload-archive--writer"; |
| 107 | writer.out = writer.err = -1; |
| 108 | writer.git_cmd = 1; |
| 109 | if (start_command(&writer)) { |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 110 | int err = errno; |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 111 | packet_write(1, "NACK unable to spawn subprocess\n"); |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 112 | die("upload-archive: %s", strerror(err)); |
| 113 | } |
Junio C Hamano | f0c7fd4 | 2011-11-15 15:39:33 -0800 | [diff] [blame] | 114 | |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 115 | packet_write(1, "ACK\n"); |
| 116 | packet_flush(1); |
| 117 | |
| 118 | while (1) { |
| 119 | struct pollfd pfd[2]; |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 120 | |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 121 | pfd[0].fd = writer.out; |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 122 | pfd[0].events = POLLIN; |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 123 | pfd[1].fd = writer.err; |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 124 | pfd[1].events = POLLIN; |
| 125 | if (poll(pfd, 2, -1) < 0) { |
| 126 | if (errno != EINTR) { |
| 127 | error("poll failed resuming: %s", |
| 128 | strerror(errno)); |
| 129 | sleep(1); |
| 130 | } |
| 131 | continue; |
| 132 | } |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 133 | if (pfd[1].revents & POLLIN) |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 134 | /* Status stream ready */ |
Nicolas Pitre | 6b59f51 | 2009-11-11 17:24:42 -0500 | [diff] [blame] | 135 | if (process_input(pfd[1].fd, 2)) |
| 136 | continue; |
| 137 | if (pfd[0].revents & POLLIN) |
| 138 | /* Data stream ready */ |
| 139 | if (process_input(pfd[0].fd, 1)) |
| 140 | continue; |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 141 | |
Jeff King | 1bc01ef | 2011-11-19 02:40:04 -0500 | [diff] [blame] | 142 | if (finish_command(&writer)) |
Junio C Hamano | d3788e1 | 2006-09-12 00:26:57 -0700 | [diff] [blame] | 143 | error_clnt("%s", deadchild); |
Junio C Hamano | 23d6d11 | 2006-09-10 03:33:34 -0700 | [diff] [blame] | 144 | packet_flush(1); |
| 145 | break; |
| 146 | } |
| 147 | return 0; |
| 148 | } |