@@ -33,6 +33,8 @@ static int aggressive_window = 250;
33
33
static int gc_auto_threshold = 6700 ;
34
34
static int gc_auto_pack_limit = 50 ;
35
35
static int detach_auto = 1 ;
36
+ static unsigned long gc_log_expire_time ;
37
+ static const char * gc_log_expire = "1.day.ago" ;
36
38
static const char * prune_expire = "2.weeks.ago" ;
37
39
static const char * prune_worktrees_expire = "3.months.ago" ;
38
40
@@ -76,10 +78,28 @@ static void git_config_date_string(const char *key, const char **output)
76
78
static void process_log_file (void )
77
79
{
78
80
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 );
80
93
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" ));
82
101
rollback_lock_file (& log_lock );
102
+ }
83
103
}
84
104
85
105
static void process_log_file_at_exit (void )
@@ -113,6 +133,8 @@ static void gc_config(void)
113
133
git_config_get_bool ("gc.autodetach" , & detach_auto );
114
134
git_config_date_string ("gc.pruneexpire" , & prune_expire );
115
135
git_config_date_string ("gc.worktreepruneexpire" , & prune_worktrees_expire );
136
+ git_config_date_string ("gc.logexpiry" , & gc_log_expire );
137
+
116
138
git_config (git_default_config , NULL );
117
139
}
118
140
@@ -290,19 +312,34 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
290
312
static int report_last_gc_error (void )
291
313
{
292
314
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" );
294
318
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 );
296
331
if (ret > 0 )
297
- return error (_ ("The last gc run reported the following. "
332
+ ret = error (_ ("The last gc run reported the following. "
298
333
"Please correct the root cause\n"
299
334
"and remove %s.\n"
300
335
"Automatic cleanup will not be performed "
301
336
"until the file is removed.\n\n"
302
337
"%s" ),
303
- git_path ( "gc.log" ) , sb .buf );
338
+ gc_log_path , sb .buf );
304
339
strbuf_release (& sb );
305
- return 0 ;
340
+ done :
341
+ free (gc_log_path );
342
+ return ret ;
306
343
}
307
344
308
345
static int gc_before_repack (void )
@@ -349,7 +386,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
349
386
argv_array_pushl (& prune_worktrees , "worktree" , "prune" , "--expire" , NULL );
350
387
argv_array_pushl (& rerere , "rerere" , "gc" , NULL );
351
388
389
+ /* default expiry time, overwritten in gc_config */
352
390
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 );
353
393
354
394
if (pack_refs < 0 )
355
395
pack_refs = !is_bare_repository ();
@@ -448,5 +488,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
448
488
warning (_ ("There are too many unreachable loose objects; "
449
489
"run 'git prune' to remove them." ));
450
490
491
+ if (!daemonized )
492
+ unlink (git_path ("gc.log" ));
493
+
451
494
return 0 ;
452
495
}
0 commit comments