6
6
#include "archive.h"
7
7
#include "pkt-line.h"
8
8
#include "sideband.h"
9
- #include "run-command.h"
10
9
11
10
static const char upload_archive_usage [] =
12
11
"git upload-archive <repo>" ;
@@ -19,17 +18,28 @@ static const char lostchild[] =
19
18
20
19
#define MAX_ARGS (64)
21
20
22
- static void prepare_argv ( const char * * sent_argv , const char * * argv )
21
+ static int run_upload_archive ( int argc , const char * * argv , const char * prefix )
23
22
{
23
+ const char * sent_argv [MAX_ARGS ];
24
24
const char * arg_cmd = "argument " ;
25
25
char * p , buf [4096 ];
26
26
int sent_argc ;
27
27
int len ;
28
28
29
+ if (argc != 2 )
30
+ usage (upload_archive_usage );
31
+
32
+ if (strlen (argv [1 ]) + 1 > sizeof (buf ))
33
+ die ("insanely long repository name" );
34
+
35
+ strcpy (buf , argv [1 ]); /* enter-repo smudges its argument */
36
+
37
+ if (!enter_repo (buf , 0 ))
38
+ die ("'%s' does not appear to be a git repository" , buf );
39
+
29
40
/* put received options in sent_argv[] */
30
- sent_argc = 2 ;
31
- sent_argv [0 ] = "archive" ;
32
- sent_argv [1 ] = "--remote-request" ;
41
+ sent_argc = 1 ;
42
+ sent_argv [0 ] = "git-upload-archive" ;
33
43
for (p = buf ;;) {
34
44
/* This will die if not enough free space in buf */
35
45
len = packet_read_line (0 , p , (buf + sizeof buf ) - p );
@@ -52,6 +62,9 @@ static void prepare_argv(const char **sent_argv, const char **argv)
52
62
* p ++ = 0 ;
53
63
}
54
64
sent_argv [sent_argc ] = NULL ;
65
+
66
+ /* parse all options sent by the client */
67
+ return write_archive (sent_argc , sent_argv , prefix , 0 , NULL , 1 );
55
68
}
56
69
57
70
__attribute__((format (printf , 1 , 2 )))
@@ -83,35 +96,48 @@ static ssize_t process_input(int child_fd, int band)
83
96
84
97
int cmd_upload_archive (int argc , const char * * argv , const char * prefix )
85
98
{
86
- const char * sent_argv [MAX_ARGS ];
87
- struct child_process cld = { sent_argv };
88
- cld .out = cld .err = -1 ;
89
- cld .git_cmd = 1 ;
90
-
91
- if (argc != 2 )
92
- usage (upload_archive_usage );
93
-
94
- if (!enter_repo (argv [1 ], 0 ))
95
- die ("'%s' does not appear to be a git repository" , argv [1 ]);
96
-
97
- prepare_argv (sent_argv , argv );
98
- if (start_command (& cld )) {
99
+ pid_t writer ;
100
+ int fd1 [2 ], fd2 [2 ];
101
+ /*
102
+ * Set up sideband subprocess.
103
+ *
104
+ * We (parent) monitor and read from child, sending its fd#1 and fd#2
105
+ * multiplexed out to our fd#1. If the child dies, we tell the other
106
+ * end over channel #3.
107
+ */
108
+ if (pipe (fd1 ) < 0 || pipe (fd2 ) < 0 ) {
109
+ int err = errno ;
110
+ packet_write (1 , "NACK pipe failed on the remote side\n" );
111
+ die ("upload-archive: %s" , strerror (err ));
112
+ }
113
+ writer = fork ();
114
+ if (writer < 0 ) {
99
115
int err = errno ;
100
116
packet_write (1 , "NACK fork failed on the remote side\n" );
101
117
die ("upload-archive: %s" , strerror (err ));
102
118
}
119
+ if (!writer ) {
120
+ /* child - connect fd#1 and fd#2 to the pipe */
121
+ dup2 (fd1 [1 ], 1 );
122
+ dup2 (fd2 [1 ], 2 );
123
+ close (fd1 [1 ]); close (fd2 [1 ]);
124
+ close (fd1 [0 ]); close (fd2 [0 ]); /* we do not read from pipe */
125
+
126
+ exit (run_upload_archive (argc , argv , prefix ));
127
+ }
103
128
104
129
/* parent - read from child, multiplex and send out to fd#1 */
130
+ close (fd1 [1 ]); close (fd2 [1 ]); /* we do not write to pipe */
105
131
packet_write (1 , "ACK\n" );
106
132
packet_flush (1 );
107
133
108
134
while (1 ) {
109
135
struct pollfd pfd [2 ];
110
136
int status ;
111
137
112
- pfd [0 ].fd = cld . out ;
138
+ pfd [0 ].fd = fd1 [ 0 ] ;
113
139
pfd [0 ].events = POLLIN ;
114
- pfd [1 ].fd = cld . err ;
140
+ pfd [1 ].fd = fd2 [ 0 ] ;
115
141
pfd [1 ].events = POLLIN ;
116
142
if (poll (pfd , 2 , -1 ) < 0 ) {
117
143
if (errno != EINTR ) {
@@ -130,7 +156,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
130
156
if (process_input (pfd [0 ].fd , 1 ))
131
157
continue ;
132
158
133
- if (waitpid (cld . pid , & status , 0 ) < 0 )
159
+ if (waitpid (writer , & status , 0 ) < 0 )
134
160
error_clnt ("%s" , lostchild );
135
161
else if (!WIFEXITED (status ) || WEXITSTATUS (status ) > 0 )
136
162
error_clnt ("%s" , deadchild );
0 commit comments