Skip to content

Commit

Permalink
Merge branch 'tb/precompose-prefix-too'
Browse files Browse the repository at this point in the history
When commands are started from a subdirectory, they may have to
compare the path to the subdirectory (called prefix and found out
from $(pwd)) with the tracked paths.  On macOS, $(pwd) and
readdir() yield decomposed path, while the tracked paths are
usually normalized to the precomposed form, causing mismatch.  This
has been fixed by taking the same approach used to normalize the
command line arguments.

* tb/precompose-prefix-too:
  MacOS: precompose_argv_prefix()
  • Loading branch information
gitster committed Feb 12, 2021
2 parents 006c5f7 + 5c32750 commit 8b25dee
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 29 deletions.
2 changes: 1 addition & 1 deletion builtin/diff-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,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] == '-') {
Expand Down
2 changes: 1 addition & 1 deletion builtin/diff-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down
2 changes: 1 addition & 1 deletion builtin/diff-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion builtin/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,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);

Expand Down
2 changes: 1 addition & 1 deletion builtin/submodule--helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
52 changes: 33 additions & 19 deletions compat/precompose_utf8.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
2 changes: 1 addition & 1 deletion compat/precompose_utf8.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion git.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,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);
Expand Down
2 changes: 1 addition & 1 deletion parse-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions t/t3910-mac-os-precompose.sh
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,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" '
Expand Down

0 comments on commit 8b25dee

Please sign in to comment.