Skip to content

Commit 6cddb73

Browse files
committed
Merge branch 'hm/config-parse-expiry-date'
"git config --expiry-date gc.reflogexpire" can read "2.weeks" from the configuration and report it as a timestamp, just like "--int" would read "1k" and report 1024, to help consumption by scripts. * hm/config-parse-expiry-date: config: add --expiry-date
2 parents 0186e9e + 5f96742 commit 6cddb73

File tree

7 files changed

+69
-13
lines changed

7 files changed

+69
-13
lines changed

Documentation/git-config.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ See also <<FILES>>.
180180
value (but you can use `git config section.variable ~/`
181181
from the command line to let your shell do the expansion).
182182

183+
--expiry-date::
184+
`git config` will ensure that the output is converted from
185+
a fixed or relative date-string to a timestamp. This option
186+
has no effect when setting the value.
187+
183188
-z::
184189
--null::
185190
For all options that output values and/or keys, always

builtin/config.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static int show_origin;
5252
#define TYPE_INT (1<<1)
5353
#define TYPE_BOOL_OR_INT (1<<2)
5454
#define TYPE_PATH (1<<3)
55+
#define TYPE_EXPIRY_DATE (1<<4)
5556

5657
static struct option builtin_config_options[] = {
5758
OPT_GROUP(N_("Config file location")),
@@ -80,6 +81,7 @@ static struct option builtin_config_options[] = {
8081
OPT_BIT(0, "int", &types, N_("value is decimal number"), TYPE_INT),
8182
OPT_BIT(0, "bool-or-int", &types, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
8283
OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH),
84+
OPT_BIT(0, "expiry-date", &types, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
8385
OPT_GROUP(N_("Other")),
8486
OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
8587
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
@@ -159,6 +161,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
159161
return -1;
160162
strbuf_addstr(buf, v);
161163
free((char *)v);
164+
} else if (types == TYPE_EXPIRY_DATE) {
165+
timestamp_t t;
166+
if (git_config_expiry_date(&t, key_, value_) < 0)
167+
return -1;
168+
strbuf_addf(buf, "%"PRItime, t);
162169
} else if (value_) {
163170
strbuf_addstr(buf, value_);
164171
} else {
@@ -273,12 +280,13 @@ static char *normalize_value(const char *key, const char *value)
273280
if (!value)
274281
return NULL;
275282

276-
if (types == 0 || types == TYPE_PATH)
283+
if (types == 0 || types == TYPE_PATH || types == TYPE_EXPIRY_DATE)
277284
/*
278285
* We don't do normalization for TYPE_PATH here: If
279286
* the path is like ~/foobar/, we prefer to store
280287
* "~/foobar/" in the config file, and to expand the ~
281288
* when retrieving the value.
289+
* Also don't do normalization for expiry dates.
282290
*/
283291
return xstrdup(value);
284292
if (types == TYPE_INT)

builtin/reflog.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -416,16 +416,6 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
416416
return ent;
417417
}
418418

419-
static int parse_expire_cfg_value(const char *var, const char *value, timestamp_t *expire)
420-
{
421-
if (!value)
422-
return config_error_nonbool(var);
423-
if (parse_expiry_date(value, expire))
424-
return error(_("'%s' for '%s' is not a valid timestamp"),
425-
value, var);
426-
return 0;
427-
}
428-
429419
/* expiry timer slot */
430420
#define EXPIRE_TOTAL 01
431421
#define EXPIRE_UNREACH 02
@@ -443,11 +433,11 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
443433

444434
if (!strcmp(key, "reflogexpire")) {
445435
slot = EXPIRE_TOTAL;
446-
if (parse_expire_cfg_value(var, value, &expire))
436+
if (git_config_expiry_date(&expire, var, value))
447437
return -1;
448438
} else if (!strcmp(key, "reflogexpireunreachable")) {
449439
slot = EXPIRE_UNREACH;
450-
if (parse_expire_cfg_value(var, value, &expire))
440+
if (git_config_expiry_date(&expire, var, value))
451441
return -1;
452442
} else
453443
return git_default_config(var, value, cb);

config.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,16 @@ int git_config_pathname(const char **dest, const char *var, const char *value)
990990
return 0;
991991
}
992992

993+
int git_config_expiry_date(timestamp_t *timestamp, const char *var, const char *value)
994+
{
995+
if (!value)
996+
return config_error_nonbool(var);
997+
if (parse_expiry_date(value, timestamp))
998+
return error(_("'%s' for '%s' is not a valid timestamp"),
999+
value, var);
1000+
return 0;
1001+
}
1002+
9931003
static int git_default_core_config(const char *var, const char *value)
9941004
{
9951005
/* This needs a better name */

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ extern int git_config_bool_or_int(const char *, const char *, int *);
5858
extern int git_config_bool(const char *, const char *);
5959
extern int git_config_string(const char **, const char *, const char *);
6060
extern int git_config_pathname(const char **, const char *, const char *);
61+
extern int git_config_expiry_date(timestamp_t *, const char *, const char *);
6162
extern int git_config_set_in_file_gently(const char *, const char *, const char *);
6263
extern void git_config_set_in_file(const char *, const char *, const char *);
6364
extern int git_config_set_gently(const char *, const char *);

t/helper/test-date.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ static const char *usage_msg = "\n"
55
" test-date show:<format> [time_t]...\n"
66
" test-date parse [date]...\n"
77
" test-date approxidate [date]...\n"
8+
" test-date timestamp [date]...\n"
89
" test-date is64bit\n"
910
" test-date time_t-is64bit\n";
1011

@@ -71,6 +72,15 @@ static void parse_approxidate(const char **argv, struct timeval *now)
7172
}
7273
}
7374

75+
static void parse_approx_timestamp(const char **argv, struct timeval *now)
76+
{
77+
for (; *argv; argv++) {
78+
timestamp_t t;
79+
t = approxidate_relative(*argv, now);
80+
printf("%s -> %"PRItime"\n", *argv, t);
81+
}
82+
}
83+
7484
int cmd_main(int argc, const char **argv)
7585
{
7686
struct timeval now;
@@ -95,6 +105,8 @@ int cmd_main(int argc, const char **argv)
95105
parse_dates(argv+1, &now);
96106
else if (!strcmp(*argv, "approxidate"))
97107
parse_approxidate(argv+1, &now);
108+
else if (!strcmp(*argv, "timestamp"))
109+
parse_approx_timestamp(argv+1, &now);
98110
else if (!strcmp(*argv, "is64bit"))
99111
return sizeof(timestamp_t) == 8 ? 0 : 1;
100112
else if (!strcmp(*argv, "time_t-is64bit"))

t/t1300-repo-config.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,36 @@ test_expect_success 'get --path barfs on boolean variable' '
901901
test_must_fail git config --get --path path.bool
902902
'
903903

904+
test_expect_success 'get --expiry-date' '
905+
rel="3.weeks.5.days.00:00" &&
906+
rel_out="$rel ->" &&
907+
cat >.git/config <<-\EOF &&
908+
[date]
909+
valid1 = "3.weeks.5.days 00:00"
910+
valid2 = "Fri Jun 4 15:46:55 2010"
911+
valid3 = "2017/11/11 11:11:11PM"
912+
valid4 = "2017/11/10 09:08:07 PM"
913+
valid5 = "never"
914+
invalid1 = "abc"
915+
EOF
916+
cat >expect <<-EOF &&
917+
$(test-date timestamp $rel)
918+
1275666415
919+
1510441871
920+
1510348087
921+
0
922+
EOF
923+
{
924+
echo "$rel_out $(git config --expiry-date date.valid1)"
925+
git config --expiry-date date.valid2 &&
926+
git config --expiry-date date.valid3 &&
927+
git config --expiry-date date.valid4 &&
928+
git config --expiry-date date.valid5
929+
} >actual &&
930+
test_cmp expect actual &&
931+
test_must_fail git config --expiry-date date.invalid1
932+
'
933+
904934
cat > expect << EOF
905935
[quote]
906936
leading = " test"

0 commit comments

Comments
 (0)