@@ -78,6 +78,13 @@ static long nonce_stamp_slop;
7878static unsigned long nonce_stamp_slop_limit ;
7979static struct ref_transaction * transaction ;
8080
81+ static enum {
82+ KEEPALIVE_NEVER = 0 ,
83+ KEEPALIVE_AFTER_NUL ,
84+ KEEPALIVE_ALWAYS
85+ } use_keepalive ;
86+ static int keepalive_in_sec = 5 ;
87+
8188static enum deny_action parse_deny_action (const char * var , const char * value )
8289{
8390 if (value ) {
@@ -200,6 +207,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
200207 return 0 ;
201208 }
202209
210+ if (strcmp (var , "receive.keepalive" ) == 0 ) {
211+ keepalive_in_sec = git_config_int (var , value );
212+ return 0 ;
213+ }
214+
203215 return git_default_config (var , value , cb );
204216}
205217
@@ -328,10 +340,60 @@ static void rp_error(const char *err, ...)
328340static int copy_to_sideband (int in , int out , void * arg )
329341{
330342 char data [128 ];
343+ int keepalive_active = 0 ;
344+
345+ if (keepalive_in_sec <= 0 )
346+ use_keepalive = KEEPALIVE_NEVER ;
347+ if (use_keepalive == KEEPALIVE_ALWAYS )
348+ keepalive_active = 1 ;
349+
331350 while (1 ) {
332- ssize_t sz = xread (in , data , sizeof (data ));
351+ ssize_t sz ;
352+
353+ if (keepalive_active ) {
354+ struct pollfd pfd ;
355+ int ret ;
356+
357+ pfd .fd = in ;
358+ pfd .events = POLLIN ;
359+ ret = poll (& pfd , 1 , 1000 * keepalive_in_sec );
360+
361+ if (ret < 0 ) {
362+ if (errno == EINTR )
363+ continue ;
364+ else
365+ break ;
366+ } else if (ret == 0 ) {
367+ /* no data; send a keepalive packet */
368+ static const char buf [] = "0005\1" ;
369+ write_or_die (1 , buf , sizeof (buf ) - 1 );
370+ continue ;
371+ } /* else there is actual data to read */
372+ }
373+
374+ sz = xread (in , data , sizeof (data ));
333375 if (sz <= 0 )
334376 break ;
377+
378+ if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active ) {
379+ const char * p = memchr (data , '\0' , sz );
380+ if (p ) {
381+ /*
382+ * The NUL tells us to start sending keepalives. Make
383+ * sure we send any other data we read along
384+ * with it.
385+ */
386+ keepalive_active = 1 ;
387+ send_sideband (1 , 2 , data , p - data , use_sideband );
388+ send_sideband (1 , 2 , p + 1 , sz - (p - data + 1 ), use_sideband );
389+ continue ;
390+ }
391+ }
392+
393+ /*
394+ * Either we're not looking for a NUL signal, or we didn't see
395+ * it yet; just pass along the data.
396+ */
335397 send_sideband (1 , 2 , data , sz , use_sideband );
336398 }
337399 close (in );
@@ -761,7 +823,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
761823{
762824 static struct lock_file shallow_lock ;
763825 struct sha1_array extra = SHA1_ARRAY_INIT ;
764- const char * alt_file ;
826+ struct check_connected_options opt = CHECK_CONNECTED_INIT ;
765827 uint32_t mask = 1 << (cmd -> index % 32 );
766828 int i ;
767829
@@ -773,9 +835,8 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
773835 !delayed_reachability_test (si , i ))
774836 sha1_array_append (& extra , si -> shallow -> sha1 [i ]);
775837
776- setup_alternate_shallow (& shallow_lock , & alt_file , & extra );
777- if (check_shallow_connected (command_singleton_iterator ,
778- 0 , cmd , alt_file )) {
838+ setup_alternate_shallow (& shallow_lock , & opt .shallow_file , & extra );
839+ if (check_connected (command_singleton_iterator , cmd , & opt )) {
779840 rollback_lock_file (& shallow_lock );
780841 sha1_array_clear (& extra );
781842 return -1 ;
@@ -1184,8 +1245,8 @@ static void set_connectivity_errors(struct command *commands,
11841245 if (shallow_update && si -> shallow_ref [cmd -> index ])
11851246 /* to be checked in update_shallow_ref() */
11861247 continue ;
1187- if (!check_everything_connected (command_singleton_iterator ,
1188- 0 , & singleton ))
1248+ if (!check_connected (command_singleton_iterator , & singleton ,
1249+ NULL ))
11891250 continue ;
11901251 cmd -> error_string = "missing necessary objects" ;
11911252 }
@@ -1343,21 +1404,38 @@ static void execute_commands(struct command *commands,
13431404 struct shallow_info * si ,
13441405 const struct string_list * push_options )
13451406{
1407+ struct check_connected_options opt = CHECK_CONNECTED_INIT ;
13461408 struct command * cmd ;
13471409 unsigned char sha1 [20 ];
13481410 struct iterate_data data ;
1411+ struct async muxer ;
1412+ int err_fd = 0 ;
13491413
13501414 if (unpacker_error ) {
13511415 for (cmd = commands ; cmd ; cmd = cmd -> next )
13521416 cmd -> error_string = "unpacker error" ;
13531417 return ;
13541418 }
13551419
1420+ if (use_sideband ) {
1421+ memset (& muxer , 0 , sizeof (muxer ));
1422+ muxer .proc = copy_to_sideband ;
1423+ muxer .in = -1 ;
1424+ if (!start_async (& muxer ))
1425+ err_fd = muxer .in ;
1426+ /* ...else, continue without relaying sideband */
1427+ }
1428+
13561429 data .cmds = commands ;
13571430 data .si = si ;
1358- if (check_everything_connected (iterate_receive_command_list , 0 , & data ))
1431+ opt .err_fd = err_fd ;
1432+ opt .progress = err_fd && !quiet ;
1433+ if (check_connected (iterate_receive_command_list , & data , & opt ))
13591434 set_connectivity_errors (commands , si );
13601435
1436+ if (use_sideband )
1437+ finish_async (& muxer );
1438+
13611439 reject_updates_to_hidden (commands );
13621440
13631441 if (run_receive_hook (commands , "pre-receive" , 0 , push_options )) {
@@ -1591,6 +1669,10 @@ static const char *unpack(int err_fd, struct shallow_info *si)
15911669 (uintmax_t )getpid (),
15921670 hostname );
15931671
1672+ if (!quiet && err_fd )
1673+ argv_array_push (& child .args , "--show-resolving-progress" );
1674+ if (use_sideband )
1675+ argv_array_push (& child .args , "--report-end-of-input" );
15941676 if (fsck_objects )
15951677 argv_array_pushf (& child .args , "--strict%s" ,
15961678 fsck_msg_types .buf );
@@ -1620,6 +1702,7 @@ static const char *unpack_with_sideband(struct shallow_info *si)
16201702 if (!use_sideband )
16211703 return unpack (0 , si );
16221704
1705+ use_keepalive = KEEPALIVE_AFTER_NUL ;
16231706 memset (& muxer , 0 , sizeof (muxer ));
16241707 muxer .proc = copy_to_sideband ;
16251708 muxer .in = -1 ;
@@ -1811,6 +1894,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
18111894 unpack_status = unpack_with_sideband (& si );
18121895 update_shallow_info (commands , & si , & ref );
18131896 }
1897+ use_keepalive = KEEPALIVE_ALWAYS ;
18141898 execute_commands (commands , unpack_status , & si ,
18151899 & push_options );
18161900 if (pack_lockfile )
0 commit comments