mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 13:48:41 +00:00
Add check if we need to precompose unicode on Mac
This adds initialization of core.precomposeunicode to repo init on Mac. This is necessary because when a Mac accesses a repo on a VFAT or SAMBA file system, it will return directory entries in decomposed unicode even if the filesystem entry is precomposed. This also removes caching of a number of repo properties from the repo init pipeline because these are properties of the specific filesystem on which the repo is created, not of the system as a whole.
This commit is contained in:
parent
146b4d1c5f
commit
6b7991e264
101
src/repository.c
101
src/repository.c
@ -843,10 +843,6 @@ fail:
|
||||
static bool is_chmod_supported(const char *file_path)
|
||||
{
|
||||
struct stat st1, st2;
|
||||
static int _is_supported = -1;
|
||||
|
||||
if (_is_supported > -1)
|
||||
return _is_supported;
|
||||
|
||||
if (p_stat(file_path, &st1) < 0)
|
||||
return false;
|
||||
@ -857,27 +853,19 @@ static bool is_chmod_supported(const char *file_path)
|
||||
if (p_stat(file_path, &st2) < 0)
|
||||
return false;
|
||||
|
||||
_is_supported = (st1.st_mode != st2.st_mode);
|
||||
|
||||
return _is_supported;
|
||||
return (st1.st_mode != st2.st_mode);
|
||||
}
|
||||
|
||||
static bool is_filesystem_case_insensitive(const char *gitdir_path)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
static int _is_insensitive = -1;
|
||||
int is_insensitive = -1;
|
||||
|
||||
if (_is_insensitive > -1)
|
||||
return _is_insensitive;
|
||||
if (!git_buf_joinpath(&path, gitdir_path, "CoNfIg"))
|
||||
is_insensitive = git_path_exists(git_buf_cstr(&path));
|
||||
|
||||
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;
|
||||
return is_insensitive;
|
||||
}
|
||||
|
||||
static bool are_symlinks_supported(const char *wd_path)
|
||||
@ -885,24 +873,69 @@ static bool are_symlinks_supported(const char *wd_path)
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
int fd;
|
||||
struct stat st;
|
||||
static int _symlinks_supported = -1;
|
||||
|
||||
if (_symlinks_supported > -1)
|
||||
return _symlinks_supported;
|
||||
int symlinks_supported = -1;
|
||||
|
||||
if ((fd = git_futils_mktmp(&path, wd_path)) < 0 ||
|
||||
p_close(fd) < 0 ||
|
||||
p_unlink(path.ptr) < 0 ||
|
||||
p_symlink("testing", path.ptr) < 0 ||
|
||||
p_lstat(path.ptr, &st) < 0)
|
||||
_symlinks_supported = false;
|
||||
symlinks_supported = false;
|
||||
else
|
||||
_symlinks_supported = (S_ISLNK(st.st_mode) != 0);
|
||||
symlinks_supported = (S_ISLNK(st.st_mode) != 0);
|
||||
|
||||
(void)p_unlink(path.ptr);
|
||||
git_buf_free(&path);
|
||||
|
||||
return _symlinks_supported;
|
||||
return symlinks_supported;
|
||||
}
|
||||
|
||||
static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX";
|
||||
static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX";
|
||||
|
||||
/* On Mac, HDFS always stores files using decomposed unicode, but when
|
||||
* writing to VFAT or SAMBA file systems, filenames may be kept as
|
||||
* precomposed unicode, but will be converted to decomposed form when
|
||||
* reading the directory entries. This can cause file name mismatches.
|
||||
* The solution is to convert directory entries to precomposed form if we
|
||||
* cannot look up the file from the decomposed path.
|
||||
*/
|
||||
static bool should_precompose_unicode_paths(const char *wd_path)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
int fd;
|
||||
bool need_precompose = false;
|
||||
char tmp[6];
|
||||
|
||||
/* Create a file using a precomposed path and then try to find it
|
||||
* using the decomposed name. If the lookup fails, then we will mark
|
||||
* that we should precompose unicode for this repository.
|
||||
*/
|
||||
if (git_buf_joinpath(&path, wd_path, nfc_file) < 0 ||
|
||||
(fd = p_mkstemp(path.ptr)) < 0)
|
||||
goto fail;
|
||||
p_close(fd);
|
||||
|
||||
/* record trailing digits generated by mkstemp */
|
||||
memcpy(tmp, path.ptr + path.size - sizeof(tmp), sizeof(tmp));
|
||||
|
||||
/* try to look up as NFD path */
|
||||
if (git_buf_joinpath(&path, wd_path, nfd_file) < 0)
|
||||
goto fail;
|
||||
memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
|
||||
|
||||
need_precompose = !git_path_exists(path.ptr);
|
||||
|
||||
/* remove temporary file */
|
||||
if (git_buf_joinpath(&path, wd_path, nfc_file) < 0)
|
||||
goto fail;
|
||||
memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
|
||||
|
||||
(void)p_unlink(path.ptr);
|
||||
|
||||
fail:
|
||||
git_buf_free(&path);
|
||||
return need_precompose;
|
||||
}
|
||||
|
||||
static int create_empty_file(const char *path, mode_t mode)
|
||||
@ -930,6 +963,7 @@ static int repo_init_config(
|
||||
int error = 0;
|
||||
git_buf cfg_path = GIT_BUF_INIT;
|
||||
git_config *config = NULL;
|
||||
bool is_bare = ((opts->flags & GIT_REPOSITORY_INIT_BARE) != 0);
|
||||
|
||||
#define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\
|
||||
if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \
|
||||
@ -954,17 +988,23 @@ static int repo_init_config(
|
||||
goto cleanup;
|
||||
|
||||
SET_REPO_CONFIG(
|
||||
bool, "core.bare", (opts->flags & GIT_REPOSITORY_INIT_BARE) != 0);
|
||||
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 (!(opts->flags & GIT_REPOSITORY_INIT_BARE)) {
|
||||
SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
|
||||
#if __APPLE__
|
||||
SET_REPO_CONFIG(
|
||||
bool, "core.precomposeunicode",
|
||||
should_precompose_unicode_paths(is_bare ? repo_dir : work_dir));
|
||||
#endif
|
||||
|
||||
if (!are_symlinks_supported(work_dir))
|
||||
SET_REPO_CONFIG(bool, "core.symlinks", false);
|
||||
if (!are_symlinks_supported(is_bare ? repo_dir : work_dir))
|
||||
SET_REPO_CONFIG(bool, "core.symlinks", false);
|
||||
|
||||
if (!is_bare) {
|
||||
SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
|
||||
|
||||
if (!(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
|
||||
SET_REPO_CONFIG(string, "core.worktree", work_dir);
|
||||
@ -973,9 +1013,6 @@ static int repo_init_config(
|
||||
if (git_config_delete_entry(config, "core.worktree") < 0)
|
||||
giterr_clear();
|
||||
}
|
||||
} else {
|
||||
if (!are_symlinks_supported(repo_dir))
|
||||
SET_REPO_CONFIG(bool, "core.symlinks", false);
|
||||
}
|
||||
|
||||
if (!(opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) &&
|
||||
|
@ -241,6 +241,16 @@ void test_repo_init__detect_ignorecase(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_repo_init__detect_precompose_unicode_required(void)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
/* hard to test "true" case without SAMBA or VFAT file system available */
|
||||
assert_config_entry_on_init("core.precomposeunicode", false);
|
||||
#else
|
||||
assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
|
||||
{
|
||||
git_config *config;
|
||||
|
Loading…
Reference in New Issue
Block a user