Merge branch 'jc/prune-all'

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()
This commit is contained in:
Junio C Hamano
2013-05-29 14:23:03 -07:00
9 changed files with 58 additions and 13 deletions

View File

@ -62,8 +62,9 @@ automatic consolidation of packs.
--prune=<date>:: --prune=<date>::
Prune loose objects older than date (default is 2 weeks ago, Prune loose objects older than date (default is 2 weeks ago,
overridable by the config variable `gc.pruneExpire`). This overridable by the config variable `gc.pruneExpire`).
option is on by default. --prune=all prunes loose objects regardless of their age.
--prune is on by default.
--no-prune:: --no-prune::
Do not prune any loose objects. Do not prune any loose objects.

View File

@ -67,14 +67,19 @@ them.
--expire=<time>:: --expire=<time>::
Entries older than this time are pruned. Without the Entries older than this time are pruned. Without the
option it is taken from configuration `gc.reflogExpire`, 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>:: --expire-unreachable=<time>::
Entries older than this time and not reachable from Entries older than this time and not reachable from
the current tip of the branch are pruned. Without the the current tip of the branch are pruned. Without the
option it is taken from configuration option it is taken from configuration
`gc.reflogExpireUnreachable`, which in turn defaults to `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:: --all::
Instead of listing <refs> explicitly, prune all refs. Instead of listing <refs> explicitly, prune all refs.

View File

@ -41,6 +41,8 @@ The parse-options API allows:
* Boolean long options can be 'negated' (or 'unset') by prepending * Boolean long options can be 'negated' (or 'unset') by prepending
`no-`, e.g. `--no-abbrev` instead of `--abbrev`. Conversely, `no-`, e.g. `--no-abbrev` instead of `--abbrev`. Conversely,
options that begin with `no-` can be 'negated' by removing it. 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 `--` * Options and non-option arguments can clearly be separated using the `--`
option, e.g. `-a -b --option -- --this-is-a-file` indicates that 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()`. Introduce an option with date argument, see `approxidate()`.
The timestamp is put into `int_var`. 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)`:: `OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
Introduce an option with argument. Introduce an option with argument.
The argument will be fed into the function given by `func_ptr` The argument will be fed into the function given by `func_ptr`

View 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__DRY_RUN(&show_only, N_("do not remove, show only")),
OPT__VERBOSE(&verbose, N_("report pruned objects")), OPT__VERBOSE(&verbose, N_("report pruned objects")),
OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
OPT_DATE(0, "expire", &expire, OPT_EXPIRY_DATE(0, "expire", &expire,
N_("expire objects older than <time>")), N_("expire objects older than <time>")),
OPT_END() OPT_END()
}; };
char *s; char *s;

View File

@ -496,11 +496,9 @@ static int parse_expire_cfg_value(const char *var, const char *value, unsigned l
{ {
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
if (!strcmp(value, "never") || !strcmp(value, "false")) { if (parse_expiry_date(value, expire))
*expire = 0; return error(_("%s' for '%s' is not a valid timestamp"),
return 0; value, var);
}
*expire = approxidate(value);
return 0; 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")) if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
cb.dry_run = 1; cb.dry_run = 1;
else if (!prefixcmp(arg, "--expire=")) { 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; explicit_expiry |= EXPIRE_TOTAL;
} }
else if (!prefixcmp(arg, "--expire-unreachable=")) { 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; explicit_expiry |= EXPIRE_UNREACH;
} }
else if (!strcmp(arg, "--stale-fix")) else if (!strcmp(arg, "--stale-fix"))

View File

@ -910,6 +910,7 @@ void show_date_relative(unsigned long time, int tz, const struct timeval *now,
struct strbuf *timebuf); struct strbuf *timebuf);
int parse_date(const char *date, char *buf, int bufsize); int parse_date(const char *date, char *buf, int bufsize);
int parse_date_basic(const char *date, unsigned long *timestamp, int *offset); 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); void datestamp(char *buf, int bufsize);
#define approxidate(s) approxidate_careful((s), NULL) #define approxidate(s) approxidate_careful((s), NULL)
unsigned long approxidate_careful(const char *, int *); unsigned long approxidate_careful(const char *, int *);

22
date.c
View File

@ -711,6 +711,28 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
return 0; /* success */ 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) int parse_date(const char *date, char *result, int maxlen)
{ {
unsigned long timestamp; unsigned long timestamp;

View File

@ -33,6 +33,12 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
return 0; 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 parse_opt_color_flag_cb(const struct option *opt, const char *arg,
int unset) int unset)
{ {

View File

@ -140,6 +140,9 @@ struct option {
#define OPT_DATE(s, l, v, h) \ #define OPT_DATE(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0, \ { OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0, \
parse_opt_approxidate_cb } 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) \ #define OPT_CALLBACK(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
#define OPT_NUMBER_CALLBACK(v, h, 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 -----*/ /*----- some often used options -----*/
extern int parse_opt_abbrev_cb(const struct option *, const char *, int); 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_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_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_verbosity_cb(const struct option *, const char *, int);
extern int parse_opt_with_commit(const struct option *, const char *, int); extern int parse_opt_with_commit(const struct option *, const char *, int);