completion: Get rid of tabbed indentation in comments. Replace with spaces.
[gitweb.git] / builtin-gc.c
index f99b212ca47b13741c1e087b6ec75b9861c11e38..a2014388dad65fab8c7d32baf275295a0e36b210 100644 (file)
 
 #include "builtin.h"
 #include "cache.h"
+#include "parse-options.h"
 #include "run-command.h"
 
 #define FAILED_RUN "failed to run %s"
 
-static const char builtin_gc_usage[] = "git-gc [--prune] [--aggressive]";
+static const char * const builtin_gc_usage[] = {
+       "git gc [options]",
+       NULL
+};
 
 static int pack_refs = 1;
 static int aggressive_window = -1;
 static int gc_auto_threshold = 6700;
-static int gc_auto_pack_limit = 20;
+static int gc_auto_pack_limit = 50;
+static const char *prune_expire = "2.weeks.ago";
 
 #define MAX_ADD 10
 static const char *argv_pack_refs[] = {"pack-refs", "--all", "--prune", NULL};
 static const char *argv_reflog[] = {"reflog", "expire", "--all", NULL};
 static const char *argv_repack[MAX_ADD] = {"repack", "-d", "-l", NULL};
-static const char *argv_prune[] = {"prune", NULL};
+static const char *argv_prune[] = {"prune", "--expire", NULL, NULL};
 static const char *argv_rerere[] = {"rerere", "gc", NULL};
 
-static int gc_config(const char *var, const char *value)
+static int gc_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "gc.packrefs")) {
-               if (!strcmp(value, "notbare"))
+               if (value && !strcmp(value, "notbare"))
                        pack_refs = -1;
                else
                        pack_refs = git_config_bool(var, value);
@@ -51,7 +56,15 @@ static int gc_config(const char *var, const char *value)
                gc_auto_pack_limit = git_config_int(var, value);
                return 0;
        }
-       return git_default_config(var, value);
+       if (!strcmp(var, "gc.pruneexpire")) {
+               if (value && strcmp(value, "now")) {
+                       unsigned long now = approxidate("now");
+                       if (approxidate(value) >= now)
+                               return error("Invalid %s: '%s'", var, value);
+               }
+               return git_config_string(&prune_expire, var, value);
+       }
+       return git_default_config(var, value, cb);
 }
 
 static void append_option(const char **cmd, const char *opt, int max_length)
@@ -118,19 +131,9 @@ static int too_many_packs(void)
 
        prepare_packed_git();
        for (cnt = 0, p = packed_git; p; p = p->next) {
-               char path[PATH_MAX];
-               size_t len;
-               int keep;
-
                if (!p->pack_local)
                        continue;
-               len = strlen(p->pack_name);
-               if (PATH_MAX <= len + 1)
-                       continue; /* oops, give up */
-               memcpy(path, p->pack_name, len-5);
-               memcpy(path + len - 5, ".keep", 6);
-               keep = access(p->pack_name, F_OK) && (errno == ENOENT);
-               if (keep)
+               if (p->pack_keep)
                        continue;
                /*
                 * Perhaps check the size of the pack and count only
@@ -144,10 +147,10 @@ static int too_many_packs(void)
 static int need_to_gc(void)
 {
        /*
-        * Setting gc.auto and gc.autopacklimit to 0 or negative can
-        * disable the automatic gc.
+        * Setting gc.auto to 0 or negative can disable the
+        * automatic gc.
         */
-       if (gc_auto_threshold <= 0 && gc_auto_pack_limit <= 0)
+       if (gc_auto_threshold <= 0)
                return 0;
 
        /*
@@ -157,69 +160,66 @@ static int need_to_gc(void)
         * there is no need.
         */
        if (too_many_packs())
-               append_option(argv_repack, "-A", MAX_ADD);
+               append_option(argv_repack,
+                             !strcmp(prune_expire, "now") ? "-a" : "-A",
+                             MAX_ADD);
        else if (!too_many_loose_objects())
                return 0;
+
+       if (run_hook(NULL, "pre-auto-gc", NULL))
+               return 0;
        return 1;
 }
 
 int cmd_gc(int argc, const char **argv, const char *prefix)
 {
-       int i;
        int prune = 0;
+       int aggressive = 0;
        int auto_gc = 0;
+       int quiet = 0;
        char buf[80];
 
-       git_config(gc_config);
+       struct option builtin_gc_options[] = {
+               OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced objects (deprecated)"),
+               OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
+               OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
+               OPT_BOOLEAN('q', "quiet", &quiet, "suppress progress reports"),
+               OPT_END()
+       };
+
+       git_config(gc_config, NULL);
 
        if (pack_refs < 0)
                pack_refs = !is_bare_repository();
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (!strcmp(arg, "--prune")) {
-                       prune = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--aggressive")) {
-                       append_option(argv_repack, "-f", MAX_ADD);
-                       if (aggressive_window > 0) {
-                               sprintf(buf, "--window=%d", aggressive_window);
-                               append_option(argv_repack, buf, MAX_ADD);
-                       }
-                       continue;
-               }
-               if (!strcmp(arg, "--auto")) {
-                       auto_gc = 1;
-                       continue;
+       argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
+       if (argc > 0)
+               usage_with_options(builtin_gc_usage, builtin_gc_options);
+
+       if (aggressive) {
+               append_option(argv_repack, "-f", MAX_ADD);
+               if (aggressive_window > 0) {
+                       sprintf(buf, "--window=%d", aggressive_window);
+                       append_option(argv_repack, buf, MAX_ADD);
                }
-               break;
        }
-       if (i != argc)
-               usage(builtin_gc_usage);
+       if (quiet)
+               append_option(argv_repack, "-q", MAX_ADD);
 
        if (auto_gc) {
                /*
                 * Auto-gc should be least intrusive as possible.
                 */
-               prune = 0;
                if (!need_to_gc())
                        return 0;
-               fprintf(stderr, "Packing your repository for optimum "
-                       "performance. If you would rather run\n"
-                       "\"git gc\" by hand, run \"git config gc.auto 0\" "
-                       "to disable automatic cleanup.\n");
-       } else {
-               /*
-                * Use safer (for shared repos) "-A" option to
-                * repack when not pruning. Auto-gc makes its
-                * own decision.
-                */
-               if (prune)
-                       append_option(argv_repack, "-a", MAX_ADD);
-               else
-                       append_option(argv_repack, "-A", MAX_ADD);
-       }
+               fprintf(stderr, "Auto packing your repository for optimum "
+                       "performance. You may also\n"
+                       "run \"git gc\" manually. See "
+                       "\"git help gc\" for more information.\n");
+       } else
+               append_option(argv_repack,
+                             !strcmp(prune_expire, "now") ? "-a" : "-A",
+                             MAX_ADD);
 
        if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
                return error(FAILED_RUN, argv_pack_refs[0]);
@@ -230,7 +230,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
                return error(FAILED_RUN, argv_repack[0]);
 
-       if (prune && run_command_v_opt(argv_prune, RUN_GIT_CMD))
+       argv_prune[2] = prune_expire;
+       if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
                return error(FAILED_RUN, argv_prune[0]);
 
        if (run_command_v_opt(argv_rerere, RUN_GIT_CMD))