66#include "archive.h"
77#include "pkt-line.h"
88#include "sideband.h"
9- #include "run-command.h"
109
1110static const char upload_archive_usage [] =
1211 "git upload-archive <repo>" ;
@@ -19,17 +18,28 @@ static const char lostchild[] =
1918
2019#define MAX_ARGS (64)
2120
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 )
2322{
23+ const char * sent_argv [MAX_ARGS ];
2424 const char * arg_cmd = "argument " ;
2525 char * p , buf [4096 ];
2626 int sent_argc ;
2727 int len ;
2828
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+
2940 /* 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" ;
3343 for (p = buf ;;) {
3444 /* This will die if not enough free space in buf */
3545 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)
5262 * p ++ = 0 ;
5363 }
5464 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 );
5568}
5669
5770__attribute__((format (printf , 1 , 2 )))
@@ -83,35 +96,48 @@ static ssize_t process_input(int child_fd, int band)
8396
8497int cmd_upload_archive (int argc , const char * * argv , const char * prefix )
8598{
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 ) {
99115 int err = errno ;
100116 packet_write (1 , "NACK fork failed on the remote side\n" );
101117 die ("upload-archive: %s" , strerror (err ));
102118 }
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+ }
103128
104129 /* parent - read from child, multiplex and send out to fd#1 */
130+ close (fd1 [1 ]); close (fd2 [1 ]); /* we do not write to pipe */
105131 packet_write (1 , "ACK\n" );
106132 packet_flush (1 );
107133
108134 while (1 ) {
109135 struct pollfd pfd [2 ];
110136 int status ;
111137
112- pfd [0 ].fd = cld . out ;
138+ pfd [0 ].fd = fd1 [ 0 ] ;
113139 pfd [0 ].events = POLLIN ;
114- pfd [1 ].fd = cld . err ;
140+ pfd [1 ].fd = fd2 [ 0 ] ;
115141 pfd [1 ].events = POLLIN ;
116142 if (poll (pfd , 2 , -1 ) < 0 ) {
117143 if (errno != EINTR ) {
@@ -130,7 +156,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
130156 if (process_input (pfd [0 ].fd , 1 ))
131157 continue ;
132158
133- if (waitpid (cld . pid , & status , 0 ) < 0 )
159+ if (waitpid (writer , & status , 0 ) < 0 )
134160 error_clnt ("%s" , lostchild );
135161 else if (!WIFEXITED (status ) || WEXITSTATUS (status ) > 0 )
136162 error_clnt ("%s" , deadchild );
0 commit comments