Merge branch 'jc/cutoff-config'

"[gc] rerereResolved = 5.days" used to be invalid, as the variable
is defined to take an integer counting the number of days.  It now
is allowed.

* jc/cutoff-config:
  rerere: allow approxidate in gc.rerereResolved/gc.rerereUnresolved
  rerere: represent time duration in timestamp_t internally
  t4200: parameterize "rerere gc" custom expiry test
  t4200: gather "rerere gc" together
  t4200: make "rerere gc" test more robust
  t4200: give us a clean slate after "rerere gc" tests
maint
Junio C Hamano 2017-08-26 22:55:08 -07:00
commit 96352ef9b4
5 changed files with 79 additions and 31 deletions

View File

@ -1564,11 +1564,13 @@ gc.<pattern>.reflogExpireUnreachable::
gc.rerereResolved:: gc.rerereResolved::
Records of conflicted merge you resolved earlier are Records of conflicted merge you resolved earlier are
kept for this many days when 'git rerere gc' is run. kept for this many days when 'git rerere gc' is run.
You can also use more human-readable "1.month.ago", etc.
The default is 60 days. See linkgit:git-rerere[1]. The default is 60 days. See linkgit:git-rerere[1].


gc.rerereUnresolved:: gc.rerereUnresolved::
Records of conflicted merge you have not resolved are Records of conflicted merge you have not resolved are
kept for this many days when 'git rerere gc' is run. kept for this many days when 'git rerere gc' is run.
You can also use more human-readable "1.month.ago", etc.
The default is 15 days. See linkgit:git-rerere[1]. The default is 15 days. See linkgit:git-rerere[1].


gitcvs.commitMsgAnnotation:: gitcvs.commitMsgAnnotation::

View File

@ -2094,6 +2094,28 @@ int git_config_get_expiry(const char *key, const char **output)
return ret; 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 git_config_get_untracked_cache(void)
{ {
int val = -1; int val = -1;

View File

@ -215,6 +215,9 @@ extern int git_config_get_max_percent_split_change(void);
/* This dies if the configured or default date is in the future */ /* This dies if the configured or default date is in the future */
extern int git_config_get_expiry(const char *key, const char **output); 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 { struct key_value_info {
const char *filename; const char *filename;
int linenr; int linenr;

View File

@ -1133,14 +1133,14 @@ int rerere_forget(struct pathspec *pathspec)
* Garbage collection support * Garbage collection support
*/ */


static time_t rerere_created_at(struct rerere_id *id) static timestamp_t rerere_created_at(struct rerere_id *id)
{ {
struct stat st; struct stat st;


return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
} }


static time_t rerere_last_used_at(struct rerere_id *id) static timestamp_t rerere_last_used_at(struct rerere_id *id)
{ {
struct stat st; struct stat st;


@ -1157,11 +1157,11 @@ static void unlink_rr_item(struct rerere_id *id)
id->collection->status[id->variant] = 0; id->collection->status[id->variant] = 0;
} }


static void prune_one(struct rerere_id *id, time_t now, static void prune_one(struct rerere_id *id,
int cutoff_resolve, int cutoff_noresolve) timestamp_t cutoff_resolve, timestamp_t cutoff_noresolve)
{ {
time_t then; timestamp_t then;
int cutoff; timestamp_t cutoff;


then = rerere_last_used_at(id); then = rerere_last_used_at(id);
if (then) if (then)
@ -1172,7 +1172,7 @@ static void prune_one(struct rerere_id *id, time_t now,
return; return;
cutoff = cutoff_noresolve; cutoff = cutoff_noresolve;
} }
if (then < now - cutoff * 86400) if (then < cutoff)
unlink_rr_item(id); unlink_rr_item(id);
} }


@ -1182,15 +1182,15 @@ void rerere_gc(struct string_list *rr)
DIR *dir; DIR *dir;
struct dirent *e; struct dirent *e;
int i; int i;
time_t now = time(NULL); timestamp_t now = time(NULL);
int cutoff_noresolve = 15; timestamp_t cutoff_noresolve = now - 15 * 86400;
int cutoff_resolve = 60; timestamp_t cutoff_resolve = now - 60 * 86400;


if (setup_rerere(rr, 0) < 0) if (setup_rerere(rr, 0) < 0)
return; return;


git_config_get_int("gc.rerereresolved", &cutoff_resolve); git_config_get_expiry_in_days("gc.rerereresolved", &cutoff_resolve, now);
git_config_get_int("gc.rerereunresolved", &cutoff_noresolve); git_config_get_expiry_in_days("gc.rerereunresolved", &cutoff_noresolve, now);
git_config(git_default_config, NULL); git_config(git_default_config, NULL);
dir = opendir(git_path("rr-cache")); dir = opendir(git_path("rr-cache"));
if (!dir) if (!dir)
@ -1211,7 +1211,7 @@ void rerere_gc(struct string_list *rr)
for (id.variant = 0, id.collection = rr_dir; for (id.variant = 0, id.collection = rr_dir;
id.variant < id.collection->status_nr; id.variant < id.collection->status_nr;
id.variant++) { id.variant++) {
prune_one(&id, now, cutoff_resolve, cutoff_noresolve); prune_one(&id, cutoff_resolve, cutoff_noresolve);
if (id.collection->status[id.variant]) if (id.collection->status[id.variant])
now_empty = 0; now_empty = 0;
} }

View File

@ -239,6 +239,43 @@ test_expect_success 'old records rest in peace' '
! test -f $rr2/preimage ! 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' ' test_expect_success 'setup: file2 added differently in two branches' '
git reset --hard && git reset --hard &&


@ -419,24 +456,6 @@ count_pre_post () {
test_line_count = "$2" actual 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 () { merge_conflict_resolve () {
git reset --hard && git reset --hard &&
test_must_fail git merge six.1 && test_must_fail git merge six.1 &&
@ -446,6 +465,8 @@ merge_conflict_resolve () {
} }


test_expect_success 'multiple identical conflicts' ' test_expect_success 'multiple identical conflicts' '
rm -fr .git/rr-cache &&
mkdir .git/rr-cache &&
git reset --hard && git reset --hard &&


test_seq 1 6 >early && test_seq 1 6 >early &&