Merge branch 'jc/prune-all'
authorJunio C Hamano <gitster@pobox.com>
Wed, 29 May 2013 21:23:03 +0000 (14:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 29 May 2013 21:23:04 +0000 (14:23 -0700)
We used the approxidate() parser for "--expire=<timestamp>" options
of various commands, but it is better to treat --expire=all and
--expire=now a bit more specially than using the current timestamp.
Update "git gc" and "git reflog" with a new parsing function for
expiry dates.

* jc/prune-all:
prune: introduce OPT_EXPIRY_DATE() and use it
api-parse-options.txt: document "no-" for non-boolean options
git-gc.txt, git-reflog.txt: document new expiry options
date.c: add parse_expiry_date()

Documentation/git-gc.txt
Documentation/git-reflog.txt
Documentation/technical/api-parse-options.txt
builtin/prune.c
builtin/reflog.c
cache.h
date.c
parse-options-cb.c
parse-options.h
index b370b025b89ffad0664171a03527b9a775172dee..2402ed68280ded314c340e394da64b3372038113 100644 (file)
@@ -62,8 +62,9 @@ automatic consolidation of packs.
 
 --prune=<date>::
        Prune loose objects older than date (default is 2 weeks ago,
-       overridable by the config variable `gc.pruneExpire`).  This
-       option is on by default.
+       overridable by the config variable `gc.pruneExpire`).
+       --prune=all prunes loose objects regardless of their age.
+       --prune is on by default.
 
 --no-prune::
        Do not prune any loose objects.
index fb8697ea4c390154b63dd88612ddf1effcb57ffe..70791b9fd88b4c64260523a5fcadcb46ce504f8f 100644 (file)
@@ -67,14 +67,19 @@ them.
 --expire=<time>::
        Entries older than this time are pruned.  Without the
        option it is taken from configuration `gc.reflogExpire`,
-       which in turn defaults to 90 days.
+       which in turn defaults to 90 days.  --expire=all prunes
+       entries regardless of their age; --expire=never turns off
+       pruning of reachable entries (but see --expire-unreachable).
 
 --expire-unreachable=<time>::
        Entries older than this time and not reachable from
        the current tip of the branch are pruned.  Without the
        option it is taken from configuration
        `gc.reflogExpireUnreachable`, which in turn defaults to
-       30 days.
+       30 days.  --expire-unreachable=all prunes unreachable
+       entries regardless of their age; --expire-unreachable=never
+       turns off early pruning of unreachable entries (but see
+       --expire).
 
 --all::
        Instead of listing <refs> explicitly, prune all refs.
index 32ddc1cf13741bea4b809e98508df3b5e71fc828..1317db4d6ca798c0ffa5150a7373c37b5599ecd9 100644 (file)
@@ -41,6 +41,8 @@ The parse-options API allows:
 * Boolean long options can be 'negated' (or 'unset') by prepending
   `no-`, e.g. `--no-abbrev` instead of `--abbrev`. Conversely,
   options that begin with `no-` can be 'negated' by removing it.
+  Other long options can be unset (e.g., set string to NULL, set
+  integer to 0) by prepending `no-`.
 
 * Options and non-option arguments can clearly be separated using the `--`
   option, e.g. `-a -b --option -- --this-is-a-file` indicates that
@@ -174,6 +176,10 @@ There are some macros to easily define options:
        Introduce an option with date argument, see `approxidate()`.
        The timestamp is put into `int_var`.
 
+`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
+       Introduce an option with expiry date argument, see `parse_expiry_date()`.
+       The timestamp is put into `int_var`.
+
 `OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
        Introduce an option with argument.
        The argument will be fed into the function given by `func_ptr`
index 85843d4f1728a907aafab9938b4c827990a7695f..b90e5cc361eb41064eaee242d8b13ceabe4335bc 100644 (file)
@@ -132,8 +132,8 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
                OPT__VERBOSE(&verbose, N_("report pruned objects")),
                OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
-               OPT_DATE(0, "expire", &expire,
-                        N_("expire objects older than <time>")),
+               OPT_EXPIRY_DATE(0, "expire", &expire,
+                               N_("expire objects older than <time>")),
                OPT_END()
        };
        char *s;
index 72a0af70c3dcd7d108887cd289bc7b3c606226aa..54184b3d133bb66db272fd21ad3cad53a4a9a5cb 100644 (file)
@@ -496,11 +496,9 @@ static int parse_expire_cfg_value(const char *var, const char *value, unsigned l
 {
        if (!value)
                return config_error_nonbool(var);
-       if (!strcmp(value, "never") || !strcmp(value, "false")) {
-               *expire = 0;
-               return 0;
-       }
-       *expire = approxidate(value);
+       if (parse_expiry_date(value, expire))
+               return error(_("%s' for '%s' is not a valid timestamp"),
+                            value, var);
        return 0;
 }
 
@@ -614,11 +612,13 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
                        cb.dry_run = 1;
                else if (!prefixcmp(arg, "--expire=")) {
-                       cb.expire_total = approxidate(arg + 9);
+                       if (parse_expiry_date(arg + 9, &cb.expire_total))
+                               die(_("'%s' is not a valid timestamp"), arg);
                        explicit_expiry |= EXPIRE_TOTAL;
                }
                else if (!prefixcmp(arg, "--expire-unreachable=")) {
-                       cb.expire_unreachable = approxidate(arg + 21);
+                       if (parse_expiry_date(arg + 21, &cb.expire_unreachable))
+                               die(_("'%s' is not a valid timestamp"), arg);
                        explicit_expiry |= EXPIRE_UNREACH;
                }
                else if (!strcmp(arg, "--stale-fix"))
diff --git a/cache.h b/cache.h
index 94ca1acf704bd2dfdc561b6b2d3d64740b975f61..7ce90611373ba9f0b3d7ab12eef53639458d241e 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -910,6 +910,7 @@ void show_date_relative(unsigned long time, int tz, const struct timeval *now,
                        struct strbuf *timebuf);
 int parse_date(const char *date, char *buf, int bufsize);
 int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
+int parse_expiry_date(const char *date, unsigned long *timestamp);
 void datestamp(char *buf, int bufsize);
 #define approxidate(s) approxidate_careful((s), NULL)
 unsigned long approxidate_careful(const char *, int *);
diff --git a/date.c b/date.c
index df20d0ba1d9c5d9fa03316968c1b7038659add05..29f15404feab0d98f377b312a3fcf5d8888fdb0a 100644 (file)
--- a/date.c
+++ b/date.c
@@ -711,6 +711,28 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
        return 0; /* success */
 }
 
+int parse_expiry_date(const char *date, unsigned long *timestamp)
+{
+       int errors = 0;
+
+       if (!strcmp(date, "never") || !strcmp(date, "false"))
+               *timestamp = 0;
+       else if (!strcmp(date, "all") || !strcmp(date, "now"))
+               /*
+                * We take over "now" here, which usually translates
+                * to the current timestamp.  This is because the user
+                * really means to expire everything she has done in
+                * the past, and by definition reflogs are the record
+                * of the past, and there is nothing from the future
+                * to be kept.
+                */
+               *timestamp = ULONG_MAX;
+       else
+               *timestamp = approxidate_careful(date, &errors);
+
+       return errors;
+}
+
 int parse_date(const char *date, char *result, int maxlen)
 {
        unsigned long timestamp;
index 0de5fb168a5c1b86c50be0d0c3f2d7228e7159a1..be8c413cfebb414bcbb7815cf4fe42bc31444d65 100644 (file)
@@ -33,6 +33,12 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
        return 0;
 }
 
+int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
+                            int unset)
+{
+       return parse_expiry_date(arg, (unsigned long *)opt->value);
+}
+
 int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
                            int unset)
 {
index 1c8bd8d5a0894d9deda1e849165ff38e8d594a4d..c378b75b13317d27f05232c7a035ddad2374a87e 100644 (file)
@@ -140,6 +140,9 @@ struct option {
 #define OPT_DATE(s, l, v, h) \
        { OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0,    \
          parse_opt_approxidate_cb }
+#define OPT_EXPIRY_DATE(s, l, v, h) \
+       { OPTION_CALLBACK, (s), (l), (v), N_("expiry date"),(h), 0,     \
+         parse_opt_expiry_date_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
        { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
 #define OPT_NUMBER_CALLBACK(v, h, f) \
@@ -219,6 +222,7 @@ extern int parse_options_concat(struct option *dst, size_t, struct option *src);
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
+extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 extern int parse_opt_with_commit(const struct option *, const char *, int);