mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-10-31 19:49:16 +00:00 
			
		
		
		
	Introduce core.safecrlf handling
This commit is contained in:
		
							parent
							
								
									5f74c47693
								
							
						
					
					
						commit
						855c66de66
					
				| @ -68,6 +68,7 @@ static struct map_data _cvar_maps[] = { | ||||
| 	{"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT }, | ||||
| 	{"core.abbrev", _cvar_map_int, 1, GIT_ABBREV_DEFAULT }, | ||||
| 	{"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT }, | ||||
| 	{"core.safecrlf", NULL, 0, GIT_SAFE_CRLF_DEFAULT}, | ||||
| }; | ||||
| 
 | ||||
| int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar) | ||||
|  | ||||
							
								
								
									
										34
									
								
								src/crlf.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/crlf.c
									
									
									
									
									
								
							| @ -21,6 +21,7 @@ struct crlf_attrs { | ||||
| 	int crlf_action; | ||||
| 	int eol; | ||||
| 	int auto_crlf; | ||||
| 	int safe_crlf; | ||||
| }; | ||||
| 
 | ||||
| struct crlf_filter { | ||||
| @ -123,6 +124,9 @@ static int crlf_apply_to_odb( | ||||
| 	const git_buf *from, | ||||
| 	const git_filter_source *src) | ||||
| { | ||||
| 	git_buf safe = GIT_BUF_INIT; | ||||
| 	int error = 0; | ||||
| 
 | ||||
| 	/* Empty file? Nothing to do */ | ||||
| 	if (!git_buf_len(from)) | ||||
| 		return 0; | ||||
| @ -154,12 +158,31 @@ static int crlf_apply_to_odb( | ||||
| 				return GIT_PASSTHROUGH; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!stats.cr) | ||||
| 		if (!stats.cr && !ca->safe_crlf) | ||||
| 			return GIT_PASSTHROUGH; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Actually drop the carriage returns */ | ||||
| 	return git_buf_text_crlf_to_lf(to, from); | ||||
| 	if ((error = git_buf_text_crlf_to_lf(to, from)) < 0) | ||||
| 		return error; | ||||
| 
 | ||||
| 	/* If safecrlf is enabled, sanity-check the result. */ | ||||
| 	if (ca->safe_crlf) { | ||||
| 		if ((error = git_buf_grow(&safe, max(from->size, to->size))) < 0 || | ||||
| 			(error = git_buf_text_lf_to_crlf(&safe, to)) < 0) | ||||
| 			goto done; | ||||
| 
 | ||||
| 		if (git_buf_cmp(from, &safe) != 0) { | ||||
| 			giterr_set(GITERR_FILTER, "LF would be replaced by CRLF in '%s'", | ||||
| 				git_filter_source_path(src)); | ||||
| 			error = -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| done: | ||||
| 	git_buf_free(&safe); | ||||
| 
 | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static const char *line_ending(struct crlf_attrs *ca) | ||||
| @ -272,6 +295,13 @@ static int crlf_check( | ||||
| 			return GIT_PASSTHROUGH; | ||||
| 	} | ||||
| 
 | ||||
| 	if (git_filter_source_mode(src) == GIT_FILTER_CLEAN) { | ||||
| 		error = git_repository__cvar( | ||||
| 			&ca.safe_crlf, git_filter_source_repo(src), GIT_CVAR_SAFE_CRLF); | ||||
| 		if (error < 0) | ||||
| 			return error; | ||||
| 	} | ||||
| 
 | ||||
| 	*payload = git__malloc(sizeof(ca)); | ||||
| 	GITERR_CHECK_ALLOC(*payload); | ||||
| 	memcpy(*payload, &ca, sizeof(ca)); | ||||
|  | ||||
| @ -38,6 +38,7 @@ typedef enum { | ||||
| 	GIT_CVAR_TRUSTCTIME,    /* core.trustctime */ | ||||
| 	GIT_CVAR_ABBREV,        /* core.abbrev */ | ||||
| 	GIT_CVAR_PRECOMPOSE,    /* core.precomposeunicode */ | ||||
| 	GIT_CVAR_SAFE_CRLF,		/* core.safecrlf */ | ||||
| 	GIT_CVAR_CACHE_MAX | ||||
| } git_cvar_cached; | ||||
| 
 | ||||
| @ -89,7 +90,8 @@ typedef enum { | ||||
| 	GIT_ABBREV_DEFAULT = 7, | ||||
| 	/* core.precomposeunicode */ | ||||
| 	GIT_PRECOMPOSE_DEFAULT = GIT_CVAR_FALSE, | ||||
| 
 | ||||
| 	/* core.safecrlf */ | ||||
| 	GIT_SAFE_CRLF_DEFAULT = GIT_CVAR_FALSE, | ||||
| } git_cvar_value; | ||||
| 
 | ||||
| /* internal repository init flags */ | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| #include "clar_libgit2.h" | ||||
| #include "git2/sys/filter.h" | ||||
| #include "buffer.h" | ||||
| 
 | ||||
| static git_repository *g_repo = NULL; | ||||
| 
 | ||||
| @ -69,3 +70,82 @@ void test_filter_crlf__to_odb(void) | ||||
| 	git_filter_list_free(fl); | ||||
| 	git_buf_free(&out); | ||||
| } | ||||
| 
 | ||||
| void test_filter_crlf__with_safecrlf(void) | ||||
| { | ||||
| 	git_filter_list *fl; | ||||
| 	git_filter *crlf; | ||||
| 	git_buf in = {0}, out = GIT_BUF_INIT; | ||||
| 
 | ||||
| 	cl_repo_set_bool(g_repo, "core.safecrlf", true); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); | ||||
| 
 | ||||
| 	crlf = git_filter_lookup(GIT_FILTER_CRLF); | ||||
| 	cl_assert(crlf != NULL); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_push(fl, crlf, NULL)); | ||||
| 
 | ||||
| 	/* Normalized \r\n succeeds with safecrlf */ | ||||
| 	in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr); | ||||
| 
 | ||||
| 	/* Mix of line endings fails with safecrlf */ | ||||
| 	in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_fail(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_i(giterr_last()->klass, GITERR_FILTER); | ||||
| 
 | ||||
| 	/* Normalized \n fails with safecrlf */ | ||||
| 	in.ptr = "Normal\nLF\nonly\nline-endings.\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_fail(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_i(giterr_last()->klass, GITERR_FILTER); | ||||
| 
 | ||||
| 	git_filter_list_free(fl); | ||||
| 	git_buf_free(&out); | ||||
| } | ||||
| 
 | ||||
| void test_filter_crlf__no_safecrlf(void) | ||||
| { | ||||
| 	git_filter_list *fl; | ||||
| 	git_filter *crlf; | ||||
| 	git_buf in = {0}, out = GIT_BUF_INIT; | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); | ||||
| 
 | ||||
| 	crlf = git_filter_lookup(GIT_FILTER_CRLF); | ||||
| 	cl_assert(crlf != NULL); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_push(fl, crlf, NULL)); | ||||
| 
 | ||||
| 	/* Normalized \r\n succeeds with safecrlf */ | ||||
| 	in.ptr = "Normal\r\nCRLF\r\nline-endings.\r\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_s("Normal\nCRLF\nline-endings.\n", out.ptr); | ||||
| 
 | ||||
| 	/* Mix of line endings fails with safecrlf */ | ||||
| 	in.ptr = "Mixed\nup\r\nLF\nand\r\nCRLF\nline-endings.\r\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_s("Mixed\nup\nLF\nand\nCRLF\nline-endings.\n", out.ptr); | ||||
| 
 | ||||
| 	/* Normalized \n fails with safecrlf */ | ||||
| 	in.ptr = "Normal\nLF\nonly\nline-endings.\n"; | ||||
| 	in.size = strlen(in.ptr); | ||||
| 
 | ||||
| 	cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); | ||||
| 	cl_assert_equal_s("Normal\nLF\nonly\nline-endings.\n", out.ptr); | ||||
| 
 | ||||
| 	git_filter_list_free(fl); | ||||
| 	git_buf_free(&out); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Edward Thomson
						Edward Thomson