Skip to content

Commit 71fa8d2

Browse files
tboegigitster
authored andcommitted
macOS: ls-files path fails if path of workdir is NFD
Under macOS, `git ls-files path` does not work (gives an error) if the absolute 'path' contains characters in NFD (decomposed). This happens when core.precomposeunicode is true, which is the most common case. The bug report says: $ cd somewhere # some safe place, /tmp or ~/tmp etc. $ mkdir $'u\xcc\x88' # ü in NFD $ cd ü # or cd $'u\xcc\x88' or cd $'\xc3\xbc' $ git init $ git ls-files $'/somewhere/u\xcc\x88' # NFD fatal: /somewhere/ü: '/somewhere/ü' is outside repository at '/somewhere/ü' $ git ls-files $'/somewhere/\xc3\xbc' # NFC (the same error as above) In the 'fatal:' error message, there are three ü; the 1st and 2nd are in NFC, the 3rd is in NFD. Add test cases that follows the bug report, with the simplification that the 'ü' is replaced by an 'ä', which is already used as NFD and NFC in t3910. The solution is to add a call to precompose_string_if_needed() to this code in setup.c : `work_tree = precompose_string_if_needed(get_git_work_tree());` There is, however, a limitation with this very usage of Git: The (repo) local .gitconfig file is not used, only the global "core.precomposeunicode" is taken into account, if it is set (or not). To set it to true is a good recommendation anyway, and here is the analyzes from Jun T : The problem is the_repository->config->hash_initialized is set to 1 before the_repository->commondir is set to ".git". Due to this, .git/config is never read, and precomposed_unicode is never set to 1 (remains -1). run_builtin() { setup_git_directory() { strbuf_getcwd() { # setup.c:1542 precompose_{strbuf,string}_if_needed() { # precomposed_unicode is still -1 git_congig_get_bool("core.precomposeunicode") { git_config_check_init() { repo_read_config() { git_config_init() { # !!! the_repository->config->hash_initialized=1 # !!! } # does not read .git/config since # the_repository->commondir is still NULL } } } returns without converting to NFC } returns cwd in NFD } setup_discovered_git_dir() { set_git_work_tree(".") { repo_set_worktree() { # this function indirectly calls strbuf_getcwd() # --> precompose_{strbuf,string}_if_needed() --> # {git,repo}_config_get_bool("core.precomposeunicode"), # but does not try to read .git/config since # the_repository->config->hash_initialized # is already set to 1 above. And it will not read # .git/config even if hash_initialized is 0 # since the_repository->commondir is still NULL. the_repository->worktree = NFD } } } setup_git_env() { repo_setup_gitdir() { repo_set_commondir() { # finally commondir is set here the_repository->commondir = ".git" } } } } // END setup_git_directory Reported-by: Jun T <[email protected]> Signed-off-by: Torsten Bögershausen <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 61a22dd commit 71fa8d2

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static int abspath_part_inside_repo(char *path)
4848
size_t wtlen;
4949
char *path0;
5050
int off;
51-
const char *work_tree = get_git_work_tree();
51+
const char *work_tree = precompose_string_if_needed(get_git_work_tree());
5252
struct strbuf realpath = STRBUF_INIT;
5353

5454
if (!work_tree)

t/t3910-mac-os-precompose.sh

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,27 @@ Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #50 Byte
3737
Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #250 Byte
3838
Alongc=$Alongc$AEligatu$AEligatu #254 Byte
3939

40+
41+
ls_files_nfc_nfd () {
42+
test_when_finished "git config --global --unset core.precomposeunicode" &&
43+
prglbl=$1
44+
prlocl=$2
45+
aumlcreat=$3
46+
aumllist=$4
47+
git config --global core.precomposeunicode $prglbl &&
48+
(
49+
rm -rf .git &&
50+
mkdir -p "somewhere/$prglbl/$prlocl/$aumlcreat" &&
51+
mypwd=$PWD &&
52+
cd "somewhere/$prglbl/$prlocl/$aumlcreat" &&
53+
git init &&
54+
git config core.precomposeunicode $prlocl &&
55+
git --literal-pathspecs ls-files "$mypwd/somewhere/$prglbl/$prlocl/$aumllist" 2>err &&
56+
>expected &&
57+
test_cmp expected err
58+
)
59+
}
60+
4061
test_expect_success "detect if nfd needed" '
4162
precomposeunicode=$(git config core.precomposeunicode) &&
4263
test "$precomposeunicode" = true &&
@@ -211,13 +232,29 @@ test_expect_success "unicode decomposed: git restore -p . " '
211232
'
212233

213234
# Test if the global core.precomposeunicode stops autosensing
214-
# Must be the last test case
215235
test_expect_success "respect git config --global core.precomposeunicode" '
236+
test_when_finished "git config --global --unset core.precomposeunicode" &&
216237
git config --global core.precomposeunicode true &&
217238
rm -rf .git &&
218239
git init &&
219240
precomposeunicode=$(git config core.precomposeunicode) &&
220241
test "$precomposeunicode" = "true"
221242
'
222243

244+
test_expect_success "ls-files false false nfd nfd" '
245+
ls_files_nfc_nfd false false $Adiarnfd $Adiarnfd
246+
'
247+
248+
test_expect_success "ls-files false true nfd nfd" '
249+
ls_files_nfc_nfd false true $Adiarnfd $Adiarnfd
250+
'
251+
252+
test_expect_success "ls-files true false nfd nfd" '
253+
ls_files_nfc_nfd true false $Adiarnfd $Adiarnfd
254+
'
255+
256+
test_expect_success "ls-files true true nfd nfd" '
257+
ls_files_nfc_nfd true true $Adiarnfd $Adiarnfd
258+
'
259+
223260
test_done

0 commit comments

Comments
 (0)