@@ -44,6 +44,7 @@ static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
4444static struct argv_array rerere = ARGV_ARRAY_INIT ;
4545
4646static struct tempfile pidfile ;
47+ static struct lock_file log_lock ;
4748
4849static void git_config_date_string (const char * key , const char * * output )
4950{
@@ -56,6 +57,28 @@ static void git_config_date_string(const char *key, const char **output)
5657 }
5758}
5859
60+ static void process_log_file (void )
61+ {
62+ struct stat st ;
63+ if (!fstat (get_lock_file_fd (& log_lock ), & st ) && st .st_size )
64+ commit_lock_file (& log_lock );
65+ else
66+ rollback_lock_file (& log_lock );
67+ }
68+
69+ static void process_log_file_at_exit (void )
70+ {
71+ fflush (stderr );
72+ process_log_file ();
73+ }
74+
75+ static void process_log_file_on_signal (int signo )
76+ {
77+ process_log_file ();
78+ sigchain_pop (signo );
79+ raise (signo );
80+ }
81+
5982static void gc_config (void )
6083{
6184 const char * value ;
@@ -241,6 +264,24 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
241264 return NULL ;
242265}
243266
267+ static int report_last_gc_error (void )
268+ {
269+ struct strbuf sb = STRBUF_INIT ;
270+ int ret ;
271+
272+ ret = strbuf_read_file (& sb , git_path ("gc.log" ), 0 );
273+ if (ret > 0 )
274+ return error (_ ("The last gc run reported the following. "
275+ "Please correct the root cause\n"
276+ "and remove %s.\n"
277+ "Automatic cleanup will not be performed "
278+ "until the file is removed.\n\n"
279+ "%s" ),
280+ git_path ("gc.log" ), sb .buf );
281+ strbuf_release (& sb );
282+ return 0 ;
283+ }
284+
244285static int gc_before_repack (void )
245286{
246287 if (pack_refs && run_command_v_opt (pack_refs_cmd .argv , RUN_GIT_CMD ))
@@ -262,6 +303,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
262303 int force = 0 ;
263304 const char * name ;
264305 pid_t pid ;
306+ int daemonized = 0 ;
265307
266308 struct option builtin_gc_options [] = {
267309 OPT__QUIET (& quiet , N_ ("suppress progress reporting" )),
@@ -318,13 +360,16 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
318360 fprintf (stderr , _ ("See \"git help gc\" for manual housekeeping.\n" ));
319361 }
320362 if (detach_auto ) {
363+ if (report_last_gc_error ())
364+ return -1 ;
365+
321366 if (gc_before_repack ())
322367 return -1 ;
323368 /*
324369 * failure to daemonize is ok, we'll continue
325370 * in foreground
326371 */
327- daemonize ();
372+ daemonized = ! daemonize ();
328373 }
329374 } else
330375 add_repack_all_option ();
@@ -337,6 +382,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
337382 name , (uintmax_t )pid );
338383 }
339384
385+ if (daemonized ) {
386+ hold_lock_file_for_update (& log_lock ,
387+ git_path ("gc.log" ),
388+ LOCK_DIE_ON_ERROR );
389+ dup2 (get_lock_file_fd (& log_lock ), 2 );
390+ sigchain_push_common (process_log_file_on_signal );
391+ atexit (process_log_file_at_exit );
392+ }
393+
340394 if (gc_before_repack ())
341395 return -1 ;
342396
0 commit comments