git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: hsed@unimetic.com
To: Git <git@vger.kernel.org>
Cc: Jeff King <peff@peff.net>, Kevin Daudt <me@ikke.info>
Subject: [PATCH V2] config: add --expiry-date
Date: Mon, 13 Nov 2017 17:53:46 +0000	[thread overview]
Message-ID: <d4c5023dad8a7593373141a04a406b4d@unimetic.com> (raw)
In-Reply-To: <f9d6d1cfcad17c93a0131cf69c3d7705@unimetic.com>

Description:
This patch adds a new option to the config command.

Enables flag --expiry-date as a data-type to covert date-strings to
timestamps when reading from config files (GET).
This flag is ignored on write (SET) because the date-string is stored in
config without performing any normalization.

A few test cases are also created since this is a new feature.

Motivation:
A parse_expiry_date() function already existed for api calls,
this patch simply allows the function to be used from the command line.

Update:
Added suggestions, documentation, relative time test case and test
helper function to print out timestamps for comparison. Updated reflog.c
to avoid function duplication.

Signed-off-by: Haaris <hsed@unimetic.com>
---
  Documentation/git-config.txt |  5 +++++
  builtin/config.c             | 10 +++++++++-
  builtin/reflog.c             | 14 ++------------
  config.c                     |  9 +++++++++
  config.h                     |  1 +
  t/helper/test-date.c         | 12 ++++++++++++
  t/t1300-repo-config.sh       | 30 ++++++++++++++++++++++++++++++
  7 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 4edd09fc6..14da5fc15 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -180,6 +180,11 @@ See also <<FILES>>.
  	value (but you can use `git config section.variable ~/`
  	from the command line to let your shell do the expansion).

+--expiry-date::
+	`git config` will ensure that the output is converted from
+	a fixed or relative date-string to a timestamp. This option
+	has no effect when setting the value.
+
  -z::
  --null::
  	For all options that output values and/or keys, always
diff --git a/builtin/config.c b/builtin/config.c
index d13daeeb5..afdb02191 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -52,6 +52,7 @@ static int show_origin;
  #define TYPE_INT (1<<1)
  #define TYPE_BOOL_OR_INT (1<<2)
  #define TYPE_PATH (1<<3)
+#define TYPE_EXPIRY_DATE (1<<4)

  static struct option builtin_config_options[] = {
  	OPT_GROUP(N_("Config file location")),
@@ -80,6 +81,7 @@ static struct option builtin_config_options[] = {
  	OPT_BIT(0, "int", &types, N_("value is decimal number"), TYPE_INT),
  	OPT_BIT(0, "bool-or-int", &types, N_("value is --bool or --int"), 
TYPE_BOOL_OR_INT),
  	OPT_BIT(0, "path", &types, N_("value is a path (file or directory 
name)"), TYPE_PATH),
+	OPT_BIT(0, "expiry-date", &types, N_("value is an expiry date"), 
TYPE_EXPIRY_DATE),
  	OPT_GROUP(N_("Other")),
  	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL 
byte")),
  	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
  				return -1;
  			strbuf_addstr(buf, v);
  			free((char *)v);
+		} else if (types == TYPE_EXPIRY_DATE) {
+			timestamp_t t;
+			if(git_config_expiry_date(&t, key_, value_) < 0)
+				return -1;
+			strbuf_addf(buf, "%"PRItime, t);
  		} else if (value_) {
  			strbuf_addstr(buf, value_);
  		} else {
@@ -273,12 +280,13 @@ static char *normalize_value(const char *key, 
const char *value)
  	if (!value)
  		return NULL;

-	if (types == 0 || types == TYPE_PATH)
+	if (types == 0 || types == TYPE_PATH || types == TYPE_EXPIRY_DATE)
  		/*
  		 * We don't do normalization for TYPE_PATH here: If
  		 * the path is like ~/foobar/, we prefer to store
  		 * "~/foobar/" in the config file, and to expand the ~
  		 * when retrieving the value.
+		 * Also don't do normalization for expiry dates.
  		 */
  		return xstrdup(value);
  	if (types == TYPE_INT)
diff --git a/builtin/reflog.c b/builtin/reflog.c
index ab31a3b6a..223372531 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -416,16 +416,6 @@ static struct reflog_expire_cfg *find_cfg_ent(const 
char *pattern, size_t len)
  	return ent;
  }

-static int parse_expire_cfg_value(const char *var, const char *value, 
timestamp_t *expire)
-{
-	if (!value)
-		return config_error_nonbool(var);
-	if (parse_expiry_date(value, expire))
-		return error(_("'%s' for '%s' is not a valid timestamp"),
-			     value, var);
-	return 0;
-}
-
  /* expiry timer slot */
  #define EXPIRE_TOTAL   01
  #define EXPIRE_UNREACH 02
@@ -443,11 +433,11 @@ static int reflog_expire_config(const char *var, 
const char *value, void *cb)

  	if (!strcmp(key, "reflogexpire")) {
  		slot = EXPIRE_TOTAL;
-		if (parse_expire_cfg_value(var, value, &expire))
+		if (git_config_expiry_date(&expire, var, value))
  			return -1;
  	} else if (!strcmp(key, "reflogexpireunreachable")) {
  		slot = EXPIRE_UNREACH;
-		if (parse_expire_cfg_value(var, value, &expire))
+		if (git_config_expiry_date(&expire, var, value))
  			return -1;
  	} else
  		return git_default_config(var, value, cb);
diff --git a/config.c b/config.c
index 903abf953..6ded9ce98 100644
--- a/config.c
+++ b/config.c
@@ -990,6 +990,15 @@ int git_config_pathname(const char **dest, const 
char *var, const char *value)
  	return 0;
  }

+int git_config_expiry_date(timestamp_t *timestamp, const char *var, 
const char *value)
+{
+	if (!value)
+		return config_error_nonbool(var);
+	if (parse_expiry_date(value, timestamp))
+		die(_("failed to parse date_string in: '%s'"), value);
+	return 0;
+}
+
  static int git_default_core_config(const char *var, const char *value)
  {
  	/* This needs a better name */
diff --git a/config.h b/config.h
index a49d26441..fc66c5933 100644
--- a/config.h
+++ b/config.h
@@ -58,6 +58,7 @@ extern int git_config_bool_or_int(const char *, const 
char *, int *);
  extern int git_config_bool(const char *, const char *);
  extern int git_config_string(const char **, const char *, const char 
*);
  extern int git_config_pathname(const char **, const char *, const char 
*);
+extern int git_config_expiry_date(timestamp_t *, const char *, const 
char *);
  extern int git_config_set_in_file_gently(const char *, const char *, 
const char *);
  extern void git_config_set_in_file(const char *, const char *, const 
char *);
  extern int git_config_set_gently(const char *, const char *);
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index f414a3ac6..ac8368797 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -5,6 +5,7 @@ static const char *usage_msg = "\n"
  "  test-date show:<format> [time_t]...\n"
  "  test-date parse [date]...\n"
  "  test-date approxidate [date]...\n"
+"  test-date timestamp [date]...\n"
  "  test-date is64bit\n"
  "  test-date time_t-is64bit\n";

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

+static void parse_approx_timestamp(const char **argv, struct timeval 
*now)
+{
+	for (; *argv; argv++) {
+		timestamp_t t;
+		t = approxidate_relative(*argv, now);
+		printf("%s -> %"PRItime"\n", *argv, t);
+	}
+}
+
  int cmd_main(int argc, const char **argv)
  {
  	struct timeval now;
@@ -95,6 +105,8 @@ int cmd_main(int argc, const char **argv)
  		parse_dates(argv+1, &now);
  	else if (!strcmp(*argv, "approxidate"))
  		parse_approxidate(argv+1, &now);
+	else if (!strcmp(*argv, "timestamp"))
+		parse_approx_timestamp(argv+1, &now);
  	else if (!strcmp(*argv, "is64bit"))
  		return sizeof(timestamp_t) == 8 ? 0 : 1;
  	else if (!strcmp(*argv, "time_t-is64bit"))
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 364a53700..cbeb9bebe 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -901,6 +901,36 @@ test_expect_success 'get --path barfs on boolean 
variable' '
  	test_must_fail git config --get --path path.bool
  '

+test_expect_success 'get --expiry-date' '
+	rel="3.weeks.5.days.00:00" &&
+	rel_out="$rel ->" &&
+	cat >.git/config <<-\EOF &&
+	[date]
+	valid1 = "3.weeks.5.days 00:00"
+	valid2 = "Fri Jun 4 15:46:55 2010"
+	valid3 = "2017/11/11 11:11:11PM"
+	valid4 = "2017/11/10 09:08:07 PM"
+	valid5 = "never"
+	invalid1 = "abc"
+	EOF
+	cat >expect <<-EOF &&
+	$(test-date timestamp $rel)
+	1275666415
+	1510441871
+	1510348087
+	0
+	EOF
+	{
+		echo "$rel_out $(git config --expiry-date date.valid1)"
+		git config --expiry-date date.valid2 &&
+		git config --expiry-date date.valid3 &&
+		git config --expiry-date date.valid4 &&
+		git config --expiry-date date.valid5
+	} >actual &&
+	test_cmp expect actual &&
+	test_must_fail git config --expiry-date date.invalid1
+'
+
  cat > expect << EOF
  [quote]
  	leading = " test"

       reply	other threads:[~2017-11-13 17:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <f9d6d1cfcad17c93a0131cf69c3d7705@unimetic.com>
2017-11-13 17:53 ` hsed [this message]
2017-11-12 14:55 [PATCH] config: added --expiry-date type support Jeff King
2017-11-14  2:04 ` [PATCH V2] config: add --expiry-date hsed
2017-11-14  6:21   ` Christian Couder
2017-11-14 16:03     ` Marc Branchaud
2017-11-14  6:38   ` Junio C Hamano
2017-11-15 22:10     ` hsed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d4c5023dad8a7593373141a04a406b4d@unimetic.com \
    --to=hsed@unimetic.com \
    --cc=20171112145535.gb4nafdhhdslknex@sigill.intra.peff.net \
    --cc=git@vger.kernel.org \
    --cc=me@ikke.info \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).