git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/6] accept non-integer for "this many days" expiry specification

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 22, 2017, 21:46 UTC
Message-ID
<20170822214652.31626-1-gitster@pobox.com>
In-Reply-To
<20170819203013.3053-1-gitster@pobox.com>
About a month ago, we wondered why
	[gc]
		rerereResolved = 5.days
does not work and if we want to do something better.  

This is an update to my first attempt. It turns out that I needed more patches to clean up the tests before I can write new tests for this feature.

The implementation of the feature itself has not changed much, except that it now lives in config.c for easier reuse by other codepaths in the future.

Junio C Hamano (6):
  t4200: give us a clean slate after "rerere gc" tests
  t4200: make "rerere gc" test more robust
  t4200: gather "rerere gc" together
  t4200: parameterize "rerere gc" custom expiry test
  rerere: represent time duration in timestamp_t internally
  rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolved
 Documentation/config.txt |  2 ++
 config.c                 | 22 +++++++++++++++++++
 config.h                 |  3 +++
 rerere.c                 | 26 +++++++++++-----------
 t/t4200-rerere.sh        | 57 +++++++++++++++++++++++++++++++++---------------
 5 files changed, 79 insertions(+), 31 deletions(-)

The interdiff between the original one and this version looks like this.

 config.c          | 26 +++++++++++++++++++++++--
 config.h          |  6 +++---
 rerere.c          | 24 ++---------------------
 t/t4200-rerere.sh | 57 +++++++++++++++++++++++++++++++++++++------------------
 4 files changed, 68 insertions(+), 45 deletions(-)
diff --git a/config.c b/config.c
index ac9071c5cf..ffca15f594 100644
--- a/config.c
+++ b/config.c
@@ -769,7 +769,7 @@ static int parse_unit_factor(const char *end, uintmax_t *val)
 	return 0;
 }
 
-int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
+static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
 {
 	if (value && *value) {
 		char *end;
@@ -799,7 +799,7 @@ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
 	return 0;
 }
 
-int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
+static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
 {
 	if (value && *value) {
 		char *end;
@@ -2066,6 +2066,28 @@ int git_config_get_expiry(const char *key, const char **output)
 	return ret;
 }
 
+int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)
+{
+	char *expiry_string;
+	intmax_t days;
+	timestamp_t when;
+
+	if (git_config_get_string(key, &expiry_string))
+		return 1; /* no such thing */
+
+	if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {
+		const int scale = 86400;
+		*expiry = now - days * scale;
+		return 0;
+	}
+
+	if (!parse_expiry_date(expiry_string, &when)) {
+		*expiry = when;
+		return 0;
+	}
+	return -1; /* thing exists but cannot be parsed */
+}
+
 int git_config_get_untracked_cache(void)
 {
 	int val = -1;
diff --git a/config.h b/config.h
index 039a9295de..34ddd3eb8d 100644
--- a/config.h
+++ b/config.h
@@ -205,6 +205,9 @@ extern int git_config_get_max_percent_split_change(void);
 /* This dies if the configured or default date is in the future */
 extern int git_config_get_expiry(const char *key, const char **output);
 
+/* parse either "this many days" integer, or "5.days.ago" approxidate */
+extern int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);
+
 struct key_value_info {
 	const char *filename;
 	int linenr;
@@ -215,7 +218,4 @@ struct key_value_info {
 extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
 extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
 
-int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max);
-int git_parse_signed(const char *value, intmax_t *ret, intmax_t max);
-
 #endif /* CONFIG_H */
diff --git a/rerere.c b/rerere.c
index 8bbdfe8569..d77235645e 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1176,26 +1176,6 @@ static void prune_one(struct rerere_id *id,
 		unlink_rr_item(id);
 }
 
-static void config_get_expiry(const char *key, timestamp_t *cutoff, timestamp_t now)
-{
-	char *expiry_string;
-	intmax_t days;
-	timestamp_t when;
-
-	if (git_config_get_string(key, &expiry_string))
-		return;
-
-	if (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {
-		const int scale = 86400;
-		*cutoff = now - days * scale;
-		return;
-	}
-
-	if (!parse_expiry_date(expiry_string, &when)) {
-		*cutoff = when;
-	}
-}
-
 void rerere_gc(struct string_list *rr)
 {
 	struct string_list to_remove = STRING_LIST_INIT_DUP;
@@ -1209,8 +1189,8 @@ void rerere_gc(struct string_list *rr)
 	if (setup_rerere(rr, 0) < 0)
 		return;
 
-	config_get_expiry("gc.rerereresolved", &cutoff_resolve, now);
-	config_get_expiry("gc.rerereunresolved", &cutoff_noresolve, now);
+	git_config_get_expiry_in_days("gc.rerereresolved", &cutoff_resolve, now);
+	git_config_get_expiry_in_days("gc.rerereunresolved", &cutoff_noresolve, now);
 	git_config(git_default_config, NULL);
 	dir = opendir(git_path("rr-cache"));
 	if (!dir)
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 1a080e7823..d97d2bebc9 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -239,6 +239,43 @@ test_expect_success 'old records rest in peace' '
 	! test -f $rr2/preimage
 '
 
+rerere_gc_custom_expiry_test () {
+	five_days="$1" right_now="$2"
+	test_expect_success "rerere gc with custom expiry ($five_days, $right_now)" '
+		rm -fr .git/rr-cache &&
+		rr=.git/rr-cache/$_z40 &&
+		mkdir -p "$rr" &&
+		>"$rr/preimage" &&
+		>"$rr/postimage" &&
+
+		two_days_ago=$((-2*86400)) &&
+		test-chmtime =$two_days_ago "$rr/preimage" &&
+		test-chmtime =$two_days_ago "$rr/postimage" &&
+
+		find .git/rr-cache -type f | sort >original &&
+
+		git -c "gc.rerereresolved=$five_days" \
+		    -c "gc.rerereunresolved=$five_days" rerere gc &&
+		find .git/rr-cache -type f | sort >actual &&
+		test_cmp original actual &&
+
+		git -c "gc.rerereresolved=$five_days" \
+		    -c "gc.rerereunresolved=$right_now" rerere gc &&
+		find .git/rr-cache -type f | sort >actual &&
+		test_cmp original actual &&
+
+		git -c "gc.rerereresolved=$right_now" \
+		    -c "gc.rerereunresolved=$right_now" rerere gc &&
+		find .git/rr-cache -type f | sort >actual &&
+		>expect &&
+		test_cmp expect actual
+	'
+}
+
+rerere_gc_custom_expiry_test 5 0
+
+rerere_gc_custom_expiry_test 5.days.ago now
+
 test_expect_success 'setup: file2 added differently in two branches' '
 	git reset --hard &&
 
@@ -419,24 +456,6 @@ count_pre_post () {
 	test_line_count = "$2" actual
 }
 
-test_expect_success 'rerere gc' '
-	find .git/rr-cache -type f >original &&
-	xargs test-chmtime -172800 <original &&
-
-	git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc &&
-	find .git/rr-cache -type f >actual &&
-	test_cmp original actual &&
-
-	git -c gc.rerereresolved=5 -c gc.rerereunresolved=0 rerere gc &&
-	find .git/rr-cache -type f >actual &&
-	test_cmp original actual &&
-
-	git -c gc.rerereresolved=0 -c gc.rerereunresolved=0 rerere gc &&
-	find .git/rr-cache -type f >actual &&
-	>expect &&
-	test_cmp expect actual
-'
-
 merge_conflict_resolve () {
 	git reset --hard &&
 	test_must_fail git merge six.1 &&
@@ -446,6 +465,8 @@ merge_conflict_resolve () {
 }
 
 test_expect_success 'multiple identical conflicts' '
+	rm -fr .git/rr-cache &&
+	mkdir .git/rr-cache &&
 	git reset --hard &&
 
 	test_seq 1 6 >early &&
Previous: Junio C HamanoNext: Junio C Hamano
Message 10 of 16 in “fatal: bad numeric config value '60 days' for 'gc.rerereresolved': invalid unit”
  1. Uwe HausbrandJul 21, 2017
  2. Martin ÅgrenJul 21, 2017
  3. Junio C HamanoJul 21, 2017
  4. Uwe HausbrandJul 21, 2017
  5. 0/2 accept non-integer for "this many days" expiry specificationJunio C Hamano, Aug 19, 2017
  6. 2/2 rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolvedJunio C Hamano, Aug 19, 2017
  7. Ramsay JonesAug 20, 2017
  8. Junio C HamanoAug 21, 2017
  9. 1/2 rerere: represent time duration in timestamp_t internallyJunio C Hamano, Aug 19, 2017
  10. 0/6 accept non-integer for "this many days" expiry specificationJunio C Hamano, Aug 22, 2017
  11. 1/6 t4200: give us a clean slate after "rerere gc" testsJunio C Hamano, Aug 22, 2017
  12. 3/6 t4200: gather "rerere gc" togetherJunio C Hamano, Aug 22, 2017
  13. 2/6 t4200: make "rerere gc" test more robustJunio C Hamano, Aug 22, 2017
  14. 4/6 t4200: parameterize "rerere gc" custom expiry testJunio C Hamano, Aug 22, 2017
  15. 5/6 rerere: represent time duration in timestamp_t internallyJunio C Hamano, Aug 22, 2017
  16. 6/6 rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolvedJunio C Hamano, Aug 22, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.