@@ -33,6 +33,8 @@ static int aggressive_window = 250;
3333static int gc_auto_threshold = 6700 ;
3434static int gc_auto_pack_limit = 50 ;
3535static int detach_auto = 1 ;
36+ static unsigned long gc_log_expire_time ;
37+ static const char * gc_log_expire = "1.day.ago" ;
3638static const char * prune_expire = "2.weeks.ago" ;
3739static const char * prune_worktrees_expire = "3.months.ago" ;
3840
@@ -76,10 +78,28 @@ static void git_config_date_string(const char *key, const char **output)
7678static void process_log_file (void )
7779{
7880 struct stat st ;
79- if (!fstat (get_lock_file_fd (& log_lock ), & st ) && st .st_size )
81+ if (fstat (get_lock_file_fd (& log_lock ), & st )) {
82+ /*
83+ * Perhaps there was an i/o error or another
84+ * unlikely situation. Try to make a note of
85+ * this in gc.log along with any existing
86+ * messages.
87+ */
88+ int saved_errno = errno ;
89+ fprintf (stderr , _ ("Failed to fstat %s: %s" ),
90+ get_tempfile_path (& log_lock .tempfile ),
91+ strerror (saved_errno ));
92+ fflush (stderr );
8093 commit_lock_file (& log_lock );
81- else
94+ errno = saved_errno ;
95+ } else if (st .st_size ) {
96+ /* There was some error recorded in the lock file */
97+ commit_lock_file (& log_lock );
98+ } else {
99+ /* No error, clean up any old gc.log */
100+ unlink (git_path ("gc.log" ));
82101 rollback_lock_file (& log_lock );
102+ }
83103}
84104
85105static void process_log_file_at_exit (void )
@@ -113,6 +133,8 @@ static void gc_config(void)
113133 git_config_get_bool ("gc.autodetach" , & detach_auto );
114134 git_config_date_string ("gc.pruneexpire" , & prune_expire );
115135 git_config_date_string ("gc.worktreepruneexpire" , & prune_worktrees_expire );
136+ git_config_date_string ("gc.logexpiry" , & gc_log_expire );
137+
116138 git_config (git_default_config , NULL );
117139}
118140
@@ -290,19 +312,34 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
290312static int report_last_gc_error (void )
291313{
292314 struct strbuf sb = STRBUF_INIT ;
293- int ret ;
315+ int ret = 0 ;
316+ struct stat st ;
317+ char * gc_log_path = git_pathdup ("gc.log" );
294318
295- ret = strbuf_read_file (& sb , git_path ("gc.log" ), 0 );
319+ if (stat (gc_log_path , & st )) {
320+ if (errno == ENOENT )
321+ goto done ;
322+
323+ ret = error_errno (_ ("Can't stat %s" ), gc_log_path );
324+ goto done ;
325+ }
326+
327+ if (st .st_mtime < gc_log_expire_time )
328+ goto done ;
329+
330+ ret = strbuf_read_file (& sb , gc_log_path , 0 );
296331 if (ret > 0 )
297- return error (_ ("The last gc run reported the following. "
332+ ret = error (_ ("The last gc run reported the following. "
298333 "Please correct the root cause\n"
299334 "and remove %s.\n"
300335 "Automatic cleanup will not be performed "
301336 "until the file is removed.\n\n"
302337 "%s" ),
303- git_path ( "gc.log" ) , sb .buf );
338+ gc_log_path , sb .buf );
304339 strbuf_release (& sb );
305- return 0 ;
340+ done :
341+ free (gc_log_path );
342+ return ret ;
306343}
307344
308345static int gc_before_repack (void )
@@ -349,7 +386,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
349386 argv_array_pushl (& prune_worktrees , "worktree" , "prune" , "--expire" , NULL );
350387 argv_array_pushl (& rerere , "rerere" , "gc" , NULL );
351388
389+ /* default expiry time, overwritten in gc_config */
352390 gc_config ();
391+ if (parse_expiry_date (gc_log_expire , & gc_log_expire_time ))
392+ die (_ ("Failed to parse gc.logexpiry value %s" ), gc_log_expire );
353393
354394 if (pack_refs < 0 )
355395 pack_refs = !is_bare_repository ();
@@ -448,5 +488,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
448488 warning (_ ("There are too many unreachable loose objects; "
449489 "run 'git prune' to remove them." ));
450490
491+ if (!daemonized )
492+ unlink (git_path ("gc.log" ));
493+
451494 return 0 ;
452495}
0 commit comments