Commit 693b23c09aef65a53d4523357be44654b4533065

nulltoken 2012-06-05T14:29:10

repository: make git_repository_init() value the core.ignorecase config entry

diff --git a/src/repository.c b/src/repository.c
index 5ee64cd..7181708 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -676,7 +676,25 @@ static bool is_chmod_supported(const char *file_path)
 	return _is_supported;
 }
 
-static int repo_init_config(const char *git_dir, int is_bare)
+static bool is_filesystem_case_insensitive(const char *gitdir_path)
+{
+	git_buf path = GIT_BUF_INIT;
+	static int _is_insensitive = -1;
+
+	if (_is_insensitive > -1)
+		return _is_insensitive;
+
+	if (git_buf_joinpath(&path, gitdir_path, "CoNfIg") < 0)
+		goto cleanup;
+
+	_is_insensitive = git_path_exists(git_buf_cstr(&path));
+
+cleanup:
+	git_buf_free(&path);
+	return _is_insensitive;
+}
+
+static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
 {
 	git_buf cfg_path = GIT_BUF_INIT;
 	git_config *config = NULL;
@@ -699,6 +717,9 @@ static int repo_init_config(const char *git_dir, int is_bare)
 	SET_REPO_CONFIG(bool, "core.bare", is_bare);
 	SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
 	SET_REPO_CONFIG(bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
+	
+	if (!is_reinit && is_filesystem_case_insensitive(git_dir))
+		SET_REPO_CONFIG(bool, "core.ignorecase", true);
 	/* TODO: what other defaults? */
 
 	git_buf_free(&cfg_path);
@@ -812,30 +833,35 @@ static int repo_init_structure(const char *git_dir, int is_bare)
 int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
 {
 	git_buf repository_path = GIT_BUF_INIT;
+	bool is_reinit;
+	int result = -1;
 
 	assert(repo_out && path);
 
 	if (git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR) < 0)
-		return -1;
+		goto cleanup;
 
-	if (git_path_isdir(repository_path.ptr) == true) {
-		if (valid_repository_path(&repository_path) == true) {
-			int res = repo_init_reinit(repo_out, repository_path.ptr, is_bare);
-			git_buf_free(&repository_path);
-			return res;
-		}
+	is_reinit = git_path_isdir(repository_path.ptr) && valid_repository_path(&repository_path);
+
+	if (is_reinit) {
+		if (repo_init_reinit(repo_out, repository_path.ptr, is_bare) < 0)
+			goto cleanup;
+
+		result = repo_init_config(repository_path.ptr, is_bare, is_reinit);
 	}
 
 	if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
-		repo_init_config(repository_path.ptr, is_bare) < 0 || 
+		repo_init_config(repository_path.ptr, is_bare, is_reinit) < 0 || 
 		repo_init_createhead(repository_path.ptr) < 0 ||
 		git_repository_open(repo_out, repository_path.ptr) < 0) {
-		git_buf_free(&repository_path);
-		return -1;
+		goto cleanup;
 	}
 
+	result = 0;
+
+cleanup:
 	git_buf_free(&repository_path);
-	return 0;
+	return result;
 }
 
 int git_repository_head_detached(git_repository *repo)
diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c
index 036eec9..af54b22 100644
--- a/tests-clar/repo/init.c
+++ b/tests-clar/repo/init.c
@@ -166,23 +166,70 @@ void test_repo_init__additional_templates(void)
 	git_buf_free(&path);
 }
 
-void test_repo_init__detect_filemode(void)
+static void assert_config_entry_on_init(const char *config_key, int expected_value)
 {
 	git_config *config;
-	int filemode;
+	int current_value;
 
-	cl_set_cleanup(&cleanup_repository, "filemode");
+	cl_set_cleanup(&cleanup_repository, "config_entry");
 	
-	cl_git_pass(git_repository_init(&_repo, "filemode/filemode.git", 1));
+	cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", 1));
 	git_repository_config(&config, _repo);
 
-	cl_git_pass(git_config_get_bool(&filemode, config, "core.filemode"));
+	if (expected_value >= 0) {
+		cl_git_pass(git_config_get_bool(&current_value, config, config_key));
+
+		cl_assert_equal_i(expected_value, current_value);
+	} else {
+		int error = git_config_get_bool(&current_value, config, config_key);
+
+		cl_assert_equal_i(expected_value, error);
+	}
+
+	git_config_free(config);
+}
 
+void test_repo_init__detect_filemode(void)
+{
 #ifdef GIT_WIN32
-	cl_assert_equal_i(false, filemode);
+	assert_config_entry_on_init("core.filemode", false);
 #else
-	cl_assert_equal_i(true, filemode);
+	assert_config_entry_on_init("core.filemode", true);
 #endif
+}
+
+#define CASE_INSENSITIVE_FILESYSTEM (defined GIT_WIN32 || defined __APPLE__)
+
+void test_repo_init__detect_ignorecase(void)
+{
+#if CASE_INSENSITIVE_FILESYSTEM
+	assert_config_entry_on_init("core.ignorecase", true);
+#else
+	assert_config_entry_on_init("core.ignorecase", GIT_ENOTFOUND);
+#endif
+}
+
+void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
+{
+	git_config *config;
+	int current_value;
+
+	/* Init a new repo */
+	test_repo_init__detect_ignorecase();
+
+	/* Change the "core.ignorecase" config value to something unlikely */
+	git_repository_config(&config, _repo);
+	git_config_set_int32(config, "core.ignorecase", 42);
+	git_config_free(config);
+	git_repository_free(_repo);
+
+	/* Reinit the repository */
+	cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", 1));
+	git_repository_config(&config, _repo);
+
+	/* Ensure the "core.ignorecase" config value hasn't been updated */
+	cl_git_pass(git_config_get_int32(&current_value, config, "core.ignorecase"));
+	cl_assert_equal_i(42, current_value);
 
 	git_config_free(config);
 }