Message ID | 20210202151158.27028-1-tboegi@web.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v3,1/1] MacOS: precompose_argv_prefix() | expand |
tboegi@web.de writes: > diff --git a/builtin/diff-files.c b/builtin/diff-files.c > index 1e352dd8f7..e3851dd1c0 100644 > --- a/builtin/diff-files.c > +++ b/builtin/diff-files.c > @@ -35,7 +35,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) > */ > rev.diffopt.ita_invisible_in_index = 1; > > - precompose_argv(argc, argv); > + prefix = precompose_argv_prefix(argc, argv, prefix); When git.c::cmd_main() calls run_builtin() to call cmd_diff_files(), precompose would have already been called, and we end up calling the already processed argv[] and prefix again here. Is there a codepath where cmd_diff_files() gets called _without_ making the call to precompose() in git.c::run_builtin()? Previous round removed the precompose call and I thought the logic was sound, but I must be missing something. The same question applies to other built-ins. Standalone commands that go through execv_dashed_external() should still have a call to precompose() in their own cmd_main() as the prefix is not affected for them, but I suspect that they are not expected to be run from a subdirectory to begin with? > +const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix) > +{ > + int i = 0; > > while (i < argc) { > - size_t namelen; > - oldarg = argv[i]; > - if (has_non_ascii(oldarg, (size_t)-1, &namelen)) { > - newarg = reencode_string_iconv(oldarg, namelen, ic_precompose, 0, NULL); > - if (newarg) > - argv[i] = newarg; > - } > + argv[i] = precompose_string_if_needed(argv[i]); > i++; > } > - iconv_close(ic_precompose); > + if (prefix) { > + prefix = precompose_string_if_needed(prefix); > + } > + return prefix; > } OK. I missed that the previous round did return NULL when the original should have been returned. It is clear that this caller, and the updated precompose_string_if_needed(), returns the original. Good. > diff --git a/git.c b/git.c > index a00a0a4d94..16a485fbe7 100644 > --- a/git.c > +++ b/git.c > @@ -420,7 +420,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) > int nongit_ok; > prefix = setup_git_directory_gently(&nongit_ok); > } > - > + prefix = precompose_argv_prefix(argc, argv, prefix); > if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY) && > !(p->option & DELAY_PAGER_CONFIG)) > use_pager = check_pager_config(p->cmd); > diff --git a/parse-options.c b/parse-options.c > index f0507432ee..fbea16eaf5 100644 > --- a/parse-options.c > +++ b/parse-options.c > @@ -869,7 +869,7 @@ int parse_options(int argc, const char **argv, const char *prefix, > usage_with_options(usagestr, options); > } > > - precompose_argv(argc, argv); > + precompose_argv_prefix(argc, argv, NULL); The correctness of this call also relies on that precompose() is expected to be idempotent (not saying it is necessarily bad, but just making a note), as argv[] must have been already processed before a built-in calls this function. > diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh > index 54ce19e353..8f7b49221f 100755 > --- a/t/t3910-mac-os-precompose.sh > +++ b/t/t3910-mac-os-precompose.sh > @@ -191,6 +191,22 @@ test_expect_failure 'handle existing decomposed filenames' ' > test_must_be_empty untracked > ' > > +test_expect_success "unicode decomposed: git restore -p . " ' > + DIRNAMEPWD=dir.Odiarnfc && > + DIRNAMEINREPO=dir.$Adiarnfc && > + export DIRNAMEPWD DIRNAMEINREPO && The above is fine, but > + git init $DIRNAMEPWD && > + ( > + cd $DIRNAMEPWD && > + mkdir $DIRNAMEINREPO && > + cd $DIRNAMEINREPO && Shouldn't these variable references be "quoted" for readers (I know they happen to be free of $IFS whitespaces etc., but readers and more importantly those who may casually cut-and-paste would not know)? > + echo "Initial" >file && > + git add file && > + echo "More stuff" >>file && > + echo y | git restore -p . > + ) > +' > + > # Test if the global core.precomposeunicode stops autosensing > # Must be the last test case > test_expect_success "respect git config --global core.precomposeunicode" ' > -- > 2.30.0.155.g66e871b664 Thanks.
diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 1e352dd8f7..e3851dd1c0 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -35,7 +35,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) */ rev.diffopt.ita_invisible_in_index = 1; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, &rev, NULL); while (1 < argc && argv[1][0] == '-') { diff --git a/builtin/diff-index.c b/builtin/diff-index.c index 7f5281c461..c33d7af478 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -25,7 +25,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ repo_init_revisions(the_repository, &rev, prefix); rev.abbrev = 0; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, &rev, NULL); for (i = 1; i < argc; i++) { diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 9fc95e959f..178d12f07f 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -126,7 +126,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) memset(&s_r_opt, 0, sizeof(s_r_opt)); s_r_opt.tweak = diff_tree_tweak_rev; - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); argc = setup_revisions(argc, argv, opt, &s_r_opt); memset(&w, 0, sizeof(w)); diff --git a/builtin/diff.c b/builtin/diff.c index 780c33877f..3c87c95967 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -452,7 +452,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) init_diff_ui_defaults(); git_config(git_diff_ui_config, NULL); - precompose_argv(argc, argv); + prefix = precompose_argv_prefix(argc, argv, prefix); repo_init_revisions(the_repository, &rev, prefix); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index c2bd882d17..9d505a6329 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1257,7 +1257,7 @@ static int compute_summary_module_list(struct object_id *head_oid, git_config(git_diff_basic_config, NULL); init_revisions(&rev, info->prefix); rev.abbrev = 0; - precompose_argv(diff_args.nr, diff_args.v); + precompose_argv_prefix(diff_args.nr, diff_args.v, NULL); setup_revisions(diff_args.nr, diff_args.v, &rev, NULL); rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = submodule_summary_callback; diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index 136250fbf6..ec560565a8 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -60,32 +60,46 @@ void probe_utf8_pathname_composition(void) strbuf_release(&path); } - -void precompose_argv(int argc, const char **argv) +static inline const char *precompose_string_if_needed(const char *in) { - int i = 0; - const char *oldarg; - char *newarg; - iconv_t ic_precompose; + size_t inlen; + size_t outlen; + if (has_non_ascii(in, (size_t)-1, &inlen)) { + iconv_t ic_prec; + char *out; + if (precomposed_unicode < 0) + git_config_get_bool("core.precomposeunicode", &precomposed_unicode); + if (precomposed_unicode != 1) + return in; + ic_prec = iconv_open(repo_encoding, path_encoding); + if (ic_prec == (iconv_t) -1) + return in; + + out = reencode_string_iconv(in, inlen, ic_prec, 0, &outlen); + if (out) { + if (outlen == inlen && !memcmp(in, out, outlen)) + free(out); /* no need to return indentical */ + else + in = out; + } + iconv_close(ic_prec); - if (precomposed_unicode != 1) - return; + } + return in; +} - ic_precompose = iconv_open(repo_encoding, path_encoding); - if (ic_precompose == (iconv_t) -1) - return; +const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix) +{ + int i = 0; while (i < argc) { - size_t namelen; - oldarg = argv[i]; - if (has_non_ascii(oldarg, (size_t)-1, &namelen)) { - newarg = reencode_string_iconv(oldarg, namelen, ic_precompose, 0, NULL); - if (newarg) - argv[i] = newarg; - } + argv[i] = precompose_string_if_needed(argv[i]); i++; } - iconv_close(ic_precompose); + if (prefix) { + prefix = precompose_string_if_needed(prefix); + } + return prefix; } diff --git a/compat/precompose_utf8.h b/compat/precompose_utf8.h index 6f843d3e1a..d70b84665c 100644 --- a/compat/precompose_utf8.h +++ b/compat/precompose_utf8.h @@ -28,7 +28,7 @@ typedef struct { struct dirent_prec_psx *dirent_nfc; } PREC_DIR; -void precompose_argv(int argc, const char **argv); +const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix); void probe_utf8_pathname_composition(void); PREC_DIR *precompose_utf8_opendir(const char *dirname); diff --git a/git-compat-util.h b/git-compat-util.h index 104993b975..93d9b4b7af 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -252,9 +252,9 @@ typedef unsigned long uintptr_t; #ifdef PRECOMPOSE_UNICODE #include "compat/precompose_utf8.h" #else -static inline void precompose_argv(int argc, const char **argv) +static inline const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix) { - ; /* nothing */ + return prefix; } #define probe_utf8_pathname_composition() #endif diff --git a/git.c b/git.c index a00a0a4d94..16a485fbe7 100644 --- a/git.c +++ b/git.c @@ -420,7 +420,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) int nongit_ok; prefix = setup_git_directory_gently(&nongit_ok); } - + prefix = precompose_argv_prefix(argc, argv, prefix); if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY) && !(p->option & DELAY_PAGER_CONFIG)) use_pager = check_pager_config(p->cmd); diff --git a/parse-options.c b/parse-options.c index f0507432ee..fbea16eaf5 100644 --- a/parse-options.c +++ b/parse-options.c @@ -869,7 +869,7 @@ int parse_options(int argc, const char **argv, const char *prefix, usage_with_options(usagestr, options); } - precompose_argv(argc, argv); + precompose_argv_prefix(argc, argv, NULL); free(real_options); free(ctx.alias_groups); return parse_options_end(&ctx); diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh index 54ce19e353..8f7b49221f 100755 --- a/t/t3910-mac-os-precompose.sh +++ b/t/t3910-mac-os-precompose.sh @@ -191,6 +191,22 @@ test_expect_failure 'handle existing decomposed filenames' ' test_must_be_empty untracked ' +test_expect_success "unicode decomposed: git restore -p . " ' + DIRNAMEPWD=dir.Odiarnfc && + DIRNAMEINREPO=dir.$Adiarnfc && + export DIRNAMEPWD DIRNAMEINREPO && + git init $DIRNAMEPWD && + ( + cd $DIRNAMEPWD && + mkdir $DIRNAMEINREPO && + cd $DIRNAMEINREPO && + echo "Initial" >file && + git add file && + echo "More stuff" >>file && + echo y | git restore -p . + ) +' + # Test if the global core.precomposeunicode stops autosensing # Must be the last test case test_expect_success "respect git config --global core.precomposeunicode" '