diff --git a/Documentation/config.txt b/Documentation/config.txt index 040197b10ea5a46e6ba643b28de17d2100cb129b..02776e51c8c1abfc151d245259f61546e4ff598c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1175,6 +1175,10 @@ gc.autopacklimit:: --auto` consolidates them into one larger pack. The default value is 50. Setting this to 0 disables it. +gc.autodetach:: + Make `git gc --auto` return immediately andrun in background + if the system supports it. Default is true. + gc.packrefs:: Running `git pack-refs` in a repository renders it unclonable by Git versions prior to 1.5.1.2 over dumb diff --git a/builtin/gc.c b/builtin/gc.c index 5bbb5e3cc6e3c75ad41a0a92594006a659459634..63d400bcb2092b1751427994b35057f72b04de17 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -29,6 +29,7 @@ static int pack_refs = 1; static int aggressive_window = 250; static int gc_auto_threshold = 6700; static int gc_auto_pack_limit = 50; +static int detach_auto = 1; static const char *prune_expire = "2.weeks.ago"; static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT; @@ -73,6 +74,10 @@ static int gc_config(const char *var, const char *value, void *cb) gc_auto_pack_limit = git_config_int(var, value); return 0; } + if (!strcmp(var, "gc.autodetach")) { + detach_auto = git_config_bool(var, value); + return 0; + } if (!strcmp(var, "gc.pruneexpire")) { if (value && strcmp(value, "now")) { unsigned long now = approxidate("now"); @@ -302,11 +307,19 @@ int cmd_gc(int argc, const char **argv, const char *prefix) */ if (!need_to_gc()) return 0; - if (!quiet) - fprintf(stderr, - _("Auto packing the repository for optimum performance. You may also\n" - "run \"git gc\" manually. See " - "\"git help gc\" for more information.\n")); + if (!quiet) { + if (detach_auto) + fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n")); + else + fprintf(stderr, _("Auto packing the repository for optimum performance.\n")); + fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n")); + } + if (detach_auto) + /* + * failure to daemonize is ok, we'll continue + * in foreground + */ + daemonize(); } else add_repack_all_option(); diff --git a/cache.h b/cache.h index db223e8048a50d9f37d523226dfdda05a4f5dd8e..b7d82e5d52bb09aed15e43d34e89871e3735df5c 100644 --- a/cache.h +++ b/cache.h @@ -433,6 +433,7 @@ extern int set_git_dir_init(const char *git_dir, const char *real_git_dir, int); extern int init_db(const char *template_dir, unsigned int flags); extern void sanitize_stdfds(void); +extern int daemonize(void); #define alloc_nr(x) (((x)+16)*3/2) diff --git a/daemon.c b/daemon.c index 503e03906c5c7f921e4d67a53835f771ea695d0c..eba12556848e975cd6f1a55ae25760823e90cdc8 100644 --- a/daemon.c +++ b/daemon.c @@ -1056,11 +1056,6 @@ static void drop_privileges(struct credentials *cred) /* nothing */ } -static void daemonize(void) -{ - die("--detach not supported on this platform"); -} - static struct credentials *prepare_credentials(const char *user_name, const char *group_name) { @@ -1102,24 +1097,6 @@ static struct credentials *prepare_credentials(const char *user_name, return &c; } - -static void daemonize(void) -{ - switch (fork()) { - case 0: - break; - case -1: - die_errno("fork failed"); - default: - exit(0); - } - if (setsid() == -1) - die_errno("setsid failed"); - close(0); - close(1); - close(2); - sanitize_stdfds(); -} #endif static void store_pid(const char *path) @@ -1333,9 +1310,10 @@ int main(int argc, char **argv) if (inetd_mode || serve_mode) return execute(); - if (detach) - daemonize(); - else + if (detach) { + if (daemonize()) + die("--detach not supported on this platform"); + } else sanitize_stdfds(); if (pid_file) diff --git a/setup.c b/setup.c index cffb6d605e7893a3f9ff83f427732f6b7f3443ff..613e3b3c13b3f09bce07c54dc440d03c0b5beb0c 100644 --- a/setup.c +++ b/setup.c @@ -841,3 +841,27 @@ void sanitize_stdfds(void) if (fd > 2) close(fd); } + +int daemonize(void) +{ +#ifdef NO_POSIX_GOODIES + errno = ENOSYS; + return -1; +#else + switch (fork()) { + case 0: + break; + case -1: + die_errno("fork failed"); + default: + exit(0); + } + if (setsid() == -1) + die_errno("setsid failed"); + close(0); + close(1); + close(2); + sanitize_stdfds(); + return 0; +#endif +} diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 129fc88bd28e8ea85e81310aec860df808949447..0736bcbcd52a76ef3400c046e7d3558dd1a866c7 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -164,6 +164,7 @@ test_expect_success 'receive-pack runs auto-gc in remote repo' ' # Set the child to auto-pack if more than one pack exists cd child && git config gc.autopacklimit 1 && + git config gc.autodetach false && git branch test_auto_gc && # And create a file that follows the temporary object naming # convention for the auto-gc to remove