Skip to content

Commit 329e6e8

Browse files
pcloudsgitster
authored andcommitted
gc: save log from daemonized gc --auto and print it next time
While commit 9f673f9 (gc: config option for running --auto in background - 2014-02-08) helps reduce some complaints about 'gc --auto' hogging the terminal, it creates another set of problems. The latest in this set is, as the result of daemonizing, stderr is closed and all warnings are lost. This warning at the end of cmd_gc() is particularly important because it tells the user how to avoid "gc --auto" running repeatedly. Because stderr is closed, the user does not know, naturally they complain about 'gc --auto' wasting CPU. Daemonized gc now saves stderr to $GIT_DIR/gc.log. Following gc --auto will not run and gc.log printed out until the user removes gc.log. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ecad27c commit 329e6e8

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

builtin/gc.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ static struct argv_array prune = ARGV_ARRAY_INIT;
4141
static struct argv_array rerere = ARGV_ARRAY_INIT;
4242

4343
static char *pidfile;
44+
static struct lock_file log_lock;
4445

4546
static void remove_pidfile(void)
4647
{
@@ -55,6 +56,28 @@ static void remove_pidfile_on_signal(int signo)
5556
raise(signo);
5657
}
5758

59+
static void process_log_file(void)
60+
{
61+
struct stat st;
62+
if (!fstat(log_lock.fd, &st) && st.st_size)
63+
commit_lock_file(&log_lock);
64+
else
65+
rollback_lock_file(&log_lock);
66+
}
67+
68+
static void process_log_file_at_exit(void)
69+
{
70+
fflush(stderr);
71+
process_log_file();
72+
}
73+
74+
static void process_log_file_on_signal(int signo)
75+
{
76+
process_log_file();
77+
sigchain_pop(signo);
78+
raise(signo);
79+
}
80+
5881
static void gc_config(void)
5982
{
6083
const char *value;
@@ -248,6 +271,24 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
248271
return NULL;
249272
}
250273

274+
static int report_last_gc_error(void)
275+
{
276+
struct strbuf sb = STRBUF_INIT;
277+
int ret;
278+
279+
ret = strbuf_read_file(&sb, git_path("gc.log"), 0);
280+
if (ret > 0)
281+
return error(_("The last gc run reported the following. "
282+
"Please correct the root cause\n"
283+
"and remove %s.\n"
284+
"Automatic cleanup will not be performed "
285+
"until the file is removed.\n\n"
286+
"%s"),
287+
git_path("gc.log"), sb.buf);
288+
strbuf_release(&sb);
289+
return 0;
290+
}
291+
251292
static int gc_before_repack(void)
252293
{
253294
if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
@@ -269,6 +310,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
269310
int force = 0;
270311
const char *name;
271312
pid_t pid;
313+
int daemonized = 0;
272314

273315
struct option builtin_gc_options[] = {
274316
OPT__QUIET(&quiet, N_("suppress progress reporting")),
@@ -324,13 +366,16 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
324366
fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
325367
}
326368
if (detach_auto) {
369+
if (report_last_gc_error())
370+
return -1;
371+
327372
if (gc_before_repack())
328373
return -1;
329374
/*
330375
* failure to daemonize is ok, we'll continue
331376
* in foreground
332377
*/
333-
daemonize();
378+
daemonized = !daemonize();
334379
}
335380
} else
336381
add_repack_all_option();
@@ -343,6 +388,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
343388
name, (uintmax_t)pid);
344389
}
345390

391+
if (daemonized) {
392+
hold_lock_file_for_update(&log_lock,
393+
git_path("gc.log"),
394+
LOCK_DIE_ON_ERROR);
395+
dup2(log_lock.fd, 2);
396+
sigchain_push_common(process_log_file_on_signal);
397+
atexit(process_log_file_at_exit);
398+
}
399+
346400
if (gc_before_repack())
347401
return -1;
348402

0 commit comments

Comments
 (0)