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" testsmaint
						commit
						96352ef9b4
					
				|  | @ -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:: | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								config.c
								
								
								
								
							
							
						
						
									
										22
									
								
								config.c
								
								
								
								
							|  | @ -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; | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								config.h
								
								
								
								
							
							
						
						
									
										3
									
								
								config.h
								
								
								
								
							|  | @ -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; | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								rerere.c
								
								
								
								
							
							
						
						
									
										26
									
								
								rerere.c
								
								
								
								
							|  | @ -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; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -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 && | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano