{"thread":{"id":"21406","subject":"[PATCH I18N filenames v2 1/3] Add IO-wrappers for filenames encoding <local encoding> <-> UTF-8","startedAt":"2009-10-28T18:01:38Z","lastAt":"2009-10-29T09:30:58Z","messageCount":6,"participants":["Timur Sufiev","Peter Krefting","Johannes Sixt","Alex Riesen"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"126165","messageId":"1256752900-2615-1-git-send-email-timur@iris-comp.ru","threadId":"21406","inReplyTo":null,"subject":"[PATCH I18N filenames v2 1/3] Add IO-wrappers for filenames encoding <local encoding> <-> UTF-8","fromName":"Timur Sufiev","fromEmail":"timur@iris-comp.ru","sentAt":"2009-10-28T18:01:38Z","receivedAt":"2009-10-28T18:01:38Z","isPatch":true,"sender":{"key":"timur@iris-comp.ru","avatar":null},"body":"The point is to make Git aware of filenames local encoding and make it\nkeep all filenames in UTF-8 internally. If\n`i18n.filenameslocalencoding' option was set via git-config to a\ncorrect <codepage> encoding, 2 things should be done:\n\n1. Translate all filenames read by READDIR from <codepage> into UTF-8.\n\n2. Translate all filenames passed to IO-routines from UTF-8 into\n<codepage>.\n\nThis patch provides:\n\n1. Routines for reencoding filenames from local encoding into UTF-8\nand back (taking `i18n.filenameslocalencoding' into consideration).\n\n2. I18N-wrappers around OPENDIR, READDIR, OPEN, FOPEN, STAT, LSTAT,\nCHMOD, LINK AND UNLINK.\n\n3. Makes `git-config' support `i18n.filenameslocalencoding' option.\n\nSigned-off-by: Timur Sufiev <timur@iris-comp.ru>\n---\n Makefile      |    2 +\n cache.h       |    1 +\n config.c      |    3 +\n environment.c |    1 +\n io-i18n.c     |  231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n io-i18n.h     |   33 ++++++++\n 6 files changed, 271 insertions(+), 0 deletions(-)\n create mode 100644 io-i18n.c\n create mode 100644 io-i18n.h\n\ndiff --git a/Makefile b/Makefile\nindex 42b7d60..ac8e807 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -459,6 +459,7 @@ LIB_H += tree-walk.h\n LIB_H += unpack-trees.h\n LIB_H += userdiff.h\n LIB_H += utf8.h\n+LIB_H += io-i18n.h\n LIB_H += wt-status.h\n \n LIB_OBJS += abspath.o\n@@ -562,6 +563,7 @@ LIB_OBJS += unpack-trees.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+LIB_OBJS += io-i18n.o\n LIB_OBJS += walker.o\n LIB_OBJS += wrapper.o\n LIB_OBJS += write_or_die.o\ndiff --git a/cache.h b/cache.h\nindex 96840c7..7f19f7a 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -919,6 +919,7 @@ extern int user_ident_explicitly_given;\n \n extern const char *git_commit_encoding;\n extern const char *git_log_output_encoding;\n+extern const char *git_filenames_local_encoding;\n extern const char *git_mailmap_file;\n \n /* IO helper functions */\ndiff --git a/config.c b/config.c\nindex c644061..2be6531 100644\n--- a/config.c\n+++ b/config.c\n@@ -539,6 +539,9 @@ static int git_default_i18n_config(const char *var, const char *value)\n \tif (!strcmp(var, \"i18n.logoutputencoding\"))\n \t\treturn git_config_string(&git_log_output_encoding, var, value);\n \n+\tif (!strcmp(var, \"i18n.filenameslocalencoding\"))\n+\t     return git_config_string(&git_filenames_local_encoding, var, value);\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 5de6837..b101f7b 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -24,6 +24,7 @@ int warn_ambiguous_refs = 1;\n int repository_format_version;\n const char *git_commit_encoding;\n const char *git_log_output_encoding;\n+const char *git_filenames_local_encoding;\n int shared_repository = PERM_UMASK;\n const char *apply_default_whitespace;\n const char *apply_default_ignorewhitespace;\ndiff --git a/io-i18n.c b/io-i18n.c\nnew file mode 100644\nindex 0000000..ed88a68\n--- /dev/null\n+++ b/io-i18n.c\n@@ -0,0 +1,231 @@\n+#include <stdarg.h>\n+#include <stddef.h>\n+#include \"utf8.h\"\n+#include \"cache.h\"\n+#include \"io-i18n.h\"\n+\n+inline static int is_string_ascii(const char *str)\n+{\n+\tint is_ascii = 1;\n+\n+\tfor (; *str && is_ascii; str++)\n+\t\tis_ascii &= isascii(*str);\n+\n+\treturn is_ascii;\n+}\n+\n+char *filename_to_utf8(const char *filename)\n+{\n+\tchar *out;\n+\n+\tif (is_string_ascii(filename))\n+\t\treturn NULL;\n+\n+#ifndef NO_ICONV\n+\tif (git_filenames_local_encoding && !is_utf8(filename)) {\n+\t\tout = reencode_string(filename,\n+\t\t\t\t      \"utf-8\", git_filenames_local_encoding);\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr, \"Local -> UTF8 encoding: <%s> -> <%s>\\n\",\n+\t\t\tfilename, out);\n+#endif\n+\t\treturn out;\n+\t} else if (git_filenames_local_encoding && is_utf8(filename)) {\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr,\n+\t\t\t\"Filename <%s> is already utf8-encoded, doing nothing...\\n\",\n+\t\t\tfilename);\n+#endif\n+\t\treturn NULL;\n+\t} else {\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr, \"No local encoding set, doing nothing...\\n\");\n+#endif\n+\t\treturn NULL;\n+\t}\n+#else /* #ifdef NO_ICONV */\n+\twarning(\"No iconv support, doing nothing...\\n\");\n+\treturn NULL;\n+#endif\n+}\n+\n+char *filename_to_local(const char *filename)\n+{\n+\tchar *out;\n+\n+\tif (is_string_ascii(filename))\n+\t\treturn NULL;\n+\n+#ifndef NO_ICONV\n+\tif (git_filenames_local_encoding && is_utf8(filename)) {\n+\t\tout = reencode_string(filename,\n+\t\t\t\t      git_filenames_local_encoding, \"utf-8\");\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr, \"UTF8 -> local encoding: <%s> -> <%s>\\n\",\n+\t\t\tfilename, out);\n+#endif\n+\t\treturn out;\n+\t} else if (git_filenames_local_encoding && !is_utf8(filename)) {\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr,\n+\t\t\t\"Filename <%s> is already local-encoded, doing nothing...\\n\",\n+\t\t\tfilename);\n+#endif\n+\t\treturn NULL;\n+\t} else {\n+#ifdef DEBUG_I18N\n+\t\tfprintf(stderr, \"No local encoding set, doing nothing...\\n\");\n+#endif\n+\t\treturn NULL;\n+\t}\n+#else /* #ifdef NO_ICONV */\n+\twarning(\"No iconv support, doing nothing...\\n\");\n+\treturn NULL;\n+#endif\n+}\n+\n+#undef stat\n+int stat_i18n(const char *filename, struct stat *buf)\n+{\n+\tint ret;\n+\tchar *out = filename_to_local(filename);\n+\n+\tif (out != NULL) {\n+\t\tret = stat(out, buf);\n+\t\tfree(out);\n+\t} else\n+\t\tret = stat(filename, buf);\n+\treturn ret;\n+}\n+\n+#undef lstat\n+int lstat_i18n(const char *filename, struct stat *buf)\n+{\n+\n+\tint ret;\n+\tchar *out = filename_to_local(filename);\n+\n+\tif (out != NULL) {\n+\t\tret = lstat(out, buf);\n+\t\tfree(out);\n+\t} else\n+\t\tret = lstat(filename, buf);\n+\treturn ret;\n+}\n+\n+#undef link\n+int link_i18n(const char *oldname, const char *newname)\n+{\n+\tchar *old_out = filename_to_local(oldname);\n+\tchar *new_out = filename_to_local(newname);\n+\tint ret = link(old_out ? old_out : oldname,\n+\t\t       new_out ? new_out : newname);\n+\n+\tif (old_out)\n+\t\tfree(old_out);\n+\tif (new_out)\n+\t\tfree(new_out);\n+\treturn ret;\n+}\n+\n+#undef open\n+int open_i18n(const char *filename, int flags, ...)\n+{\n+\tint ret;\n+\tmode_t mode = 0;\n+\tchar *out = filename_to_local(filename);\n+\n+\tif ( flags & O_CREAT ) {\n+\t\tva_list ap;\n+\n+\t\tva_start(ap, flags);\n+\t\tmode = va_arg(ap, int);\n+\t\tva_end(ap);\n+\t}\n+\n+\tif (out != NULL) {\n+\t\tret = open(out, flags, mode);\n+\t\tfree(out);\n+\t} else\n+\t\tret = open(filename, flags, mode);\n+\treturn ret;\n+}\n+\n+#undef unlink\n+int unlink_i18n(const char *filename)\n+{\n+\tchar *out = filename_to_local(filename);\n+\tint ret;\n+\n+\tif (out) {\n+\t\tret = unlink(out);\n+\t\tfree(out);\n+\t} else\n+\t\tret = unlink(filename);\n+\treturn ret;\n+}\n+\n+#undef readdir\n+struct dirent *readdir_i18n(DIR * dirstream)\n+{\n+\tstruct dirent *de = readdir(dirstream);\n+\n+\tif (de) {\n+\t\tchar *out = filename_to_utf8(de->d_name);\n+\n+\t\tif (out) {\n+\t\t\tint len = strlen(out);\n+\t\t\tif (len >= NAME_MAX) {\n+\t\t\t\twarning(\"readdir_i18n: converted dir entry name length exceeds NAME_MAX and will be truncated\\n\");\n+\t\t\t\tlen = NAME_MAX - 1;\n+\t\t\t}\n+\t\t\tmemcpy(de->d_name, out, len);\n+\t\t\tde->d_name[len] = '\\0';\n+\t\t\tfree(out);\n+\t\t}\n+\t\treturn de;\n+\t} else\n+\t\treturn NULL;\n+}\n+\n+#undef opendir\n+DIR *opendir_i18n(const char *dirname)\n+{\n+\tDIR *dir;\n+\tchar *out = filename_to_local(dirname);\n+\n+\tif (out != NULL) {\n+\t\tdir = opendir(out);\n+\t\tfree(out);\n+\t} else\n+\t\tdir = opendir(dirname);\n+\treturn dir;\n+}\n+\n+#undef fopen\n+FILE *fopen_i18n(const char *filename, const char *opentype)\n+{\n+\tFILE *file;\n+\tchar *out = filename_to_local(filename);\n+\n+\tif (out != NULL) {\n+\t\tfile = fopen(out, opentype);\n+\t\tfree(out);\n+\t} else\n+\t\tfile = fopen(filename, opentype);\n+\treturn file;\n+}\n+\n+#undef chmod\n+int chmod_i18n(const char *filename, mode_t mode)\n+{\n+\tint ret;\n+\tchar *out = filename_to_local(filename);\n+\n+\tif (out != NULL) {\n+\t\tret = chmod(out, mode);\n+\t\tfree(out);\n+\t} else\n+\t\tret = chmod(filename, mode);\n+\treturn ret;\n+}\ndiff --git a/io-i18n.h b/io-i18n.h\nnew file mode 100644\nindex 0000000..2369d31\n--- /dev/null\n+++ b/io-i18n.h\n@@ -0,0 +1,33 @@\n+#ifndef GIT_IO_I18N_H\n+#define GIT_IO_I18N_H\n+\n+#define _FILE_OFFSET_BITS 64\n+\n+#include <sys/stat.h>\n+#include <dirent.h>\n+#include <stdio.h>\n+#include <unistd.h>\n+\n+char *filename_to_local (const char* filename);\n+char *filename_to_utf8(const char *filename);\n+int stat_i18n(const char *filename, struct stat *buf);\n+int lstat_i18n(const char *filename, struct stat *buf);\n+DIR* opendir_i18n(const char *dirname);\n+struct dirent *readdir_i18n(DIR *dirstream);\n+int open_i18n(const char *filename, int flags, ...);\n+FILE *fopen_i18n(const char *filename, const char *opentype);\n+int chmod_i18n(const char *filename, mode_t mode);\n+int link_i18n(const char *oldname, const char *newname);\n+int unlink_i18n(const char *filename);\n+\n+#define opendir(a) opendir_i18n(a)\n+#define fopen(a, b) fopen_i18n(a, b)\n+#define chmod(a, b) chmod_i18n(a, b)\n+#define open open_i18n\n+#define stat(a, b) stat_i18n(a, b)\n+#define lstat(a, b) lstat_i18n(a, b)\n+#define readdir(a) readdir_i18n(a)\n+#define unlink(a) unlink_i18n(a)\n+#define link(a, b) link_i18n(a, b)\n+\n+#endif /* GIT_IO_I18N_H */\n-- \n1.6.5.1\n"},{"id":"126166","messageId":"1256752900-2615-2-git-send-email-timur@iris-comp.ru","threadId":"21406","inReplyTo":"1256752900-2615-1-git-send-email-timur@iris-comp.ru","subject":"[PATCH I18N filenames v2 2/3] Use I18N-wrappers everywhere in Git","fromName":"Timur Sufiev","fromEmail":"timur@iris-comp.ru","sentAt":"2009-10-28T18:01:39Z","receivedAt":"2009-10-28T18:01:39Z","isPatch":true,"sender":{"key":"timur@iris-comp.ru","avatar":null},"body":"Signed-off-by: Timur Sufiev <timur@iris-comp.ru>\n---\n abspath.c               |    1 +\n attr.c                  |    1 +\n bisect.c                |    1 +\n branch.c                |    1 +\n builtin-add.c           |    1 +\n builtin-apply.c         |    1 +\n builtin-archive.c       |    1 +\n builtin-blame.c         |    1 +\n builtin-clean.c         |    1 +\n builtin-clone.c         |    1 +\n builtin-commit.c        |    1 +\n builtin-count-objects.c |    1 +\n builtin-diff.c          |    1 +\n builtin-fast-export.c   |    1 +\n builtin-fetch--tool.c   |    1 +\n builtin-fetch-pack.c    |    1 +\n builtin-fetch.c         |    1 +\n builtin-fmt-merge-msg.c |    1 +\n builtin-fsck.c          |    1 +\n builtin-gc.c            |    1 +\n builtin-grep.c          |    1 +\n builtin-help.c          |    1 +\n builtin-init-db.c       |    1 +\n builtin-ls-files.c      |    1 +\n builtin-mailinfo.c      |    1 +\n builtin-mailsplit.c     |    1 +\n builtin-merge-file.c    |    1 +\n builtin-merge.c         |    1 +\n builtin-mv.c            |    1 +\n builtin-pack-objects.c  |    1 +\n builtin-prune-packed.c  |    1 +\n builtin-prune.c         |    1 +\n builtin-reflog.c        |    1 +\n builtin-remote.c        |    1 +\n builtin-rerere.c        |    1 +\n builtin-rm.c            |    1 +\n builtin-tag.c           |    1 +\n builtin-update-index.c  |    1 +\n builtin-verify-tag.c    |    1 +\n bundle.c                |    1 +\n check-racy.c            |    1 +\n combine-diff.c          |    1 +\n commit.c                |    1 +\n config.c                |    1 +\n copy.c                  |    1 +\n daemon.c                |    1 +\n diff-lib.c              |    1 +\n diff-no-index.c         |    1 +\n diff.c                  |    1 +\n diffcore-order.c        |    1 +\n dir.c                   |    1 +\n entry.c                 |    1 +\n fast-import.c           |    1 +\n hash-object.c           |    1 +\n help.c                  |    1 +\n http.c                  |    1 +\n index-pack.c            |    1 +\n ll-merge.c              |    1 +\n lockfile.c              |    1 +\n mailmap.c               |    1 +\n merge-recursive.c       |    1 +\n pack-write.c            |    1 +\n path.c                  |    1 +\n preload-index.c         |    1 +\n read-cache.c            |    1 +\n refs.c                  |    1 +\n remote.c                |    1 +\n rerere.c                |    1 +\n server-info.c           |    1 +\n setup.c                 |    1 +\n sha1_file.c             |    1 +\n sha1_name.c             |    1 +\n shallow.c               |    1 +\n strbuf.c                |    1 +\n symlinks.c              |    1 +\n test-chmtime.c          |    1 +\n test-delta.c            |    1 +\n trace.c                 |    1 +\n transport.c             |    1 +\n unpack-trees.c          |    1 +\n wrapper.c               |    1 +\n xdiff-interface.c       |    1 +\n 82 files changed, 82 insertions(+), 0 deletions(-)\n\ndiff --git a/abspath.c b/abspath.c\nindex b88122c..b672c18 100644\n--- a/abspath.c\n+++ b/abspath.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * Do not use this for inspecting *tracked* content.  When path is a\ndiff --git a/attr.c b/attr.c\nindex 55bdb7c..6422254 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,6 +1,7 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n #include \"attr.h\"\n+#include \"io-i18n.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n const char git_attr__false[] = \"\\0(builtin)false\";\ndiff --git a/bisect.c b/bisect.c\nindex dc18db8..fe9fbb5 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -9,6 +9,7 @@\n #include \"run-command.h\"\n #include \"log-tree.h\"\n #include \"bisect.h\"\n+#include \"io-i18n.h\"\n \n struct sha1_array {\n \tunsigned char (*sha1)[20];\ndiff --git a/branch.c b/branch.c\nindex 05ef3f5..1569809 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -3,6 +3,7 @@\n #include \"refs.h\"\n #include \"remote.h\"\n #include \"commit.h\"\n+#include \"io-i18n.h\"\n \n struct tracking {\n \tstruct refspec spec;\ndiff --git a/builtin-add.c b/builtin-add.c\nindex cb6e590..027170c 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -12,6 +12,7 @@\n #include \"parse-options.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_add_usage[] = {\n \t\"git add [options] [--] <filepattern>...\",\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex f667368..7d2f4f4 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -15,6 +15,7 @@\n #include \"string-list.h\"\n #include \"dir.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n /*\n  *  --check turns on checking that the working tree matches the\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex 12351e9..528676e 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -8,6 +8,7 @@\n #include \"parse-options.h\"\n #include \"pkt-line.h\"\n #include \"sideband.h\"\n+#include \"io-i18n.h\"\n \n static void create_output_file(const char *output_file)\n {\ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex 7512773..d349198 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -20,6 +20,7 @@\n #include \"mailmap.h\"\n #include \"parse-options.h\"\n #include \"utf8.h\"\n+#include \"io-i18n.h\"\n \n static char blame_usage[] = \"git blame [options] [rev-opts] [rev] [--] file\";\n \ndiff --git a/builtin-clean.c b/builtin-clean.c\nindex 28cdcd0..37293f7 100644\n--- a/builtin-clean.c\n+++ b/builtin-clean.c\n@@ -11,6 +11,7 @@\n #include \"dir.h\"\n #include \"parse-options.h\"\n #include \"quote.h\"\n+#include \"io-i18n.h\"\n \n static int force = -1; /* unset */\n \ndiff --git a/builtin-clone.c b/builtin-clone.c\nindex 5762a6f..5949438 100644\n--- a/builtin-clone.c\n+++ b/builtin-clone.c\n@@ -23,6 +23,7 @@\n #include \"branch.h\"\n #include \"remote.h\"\n #include \"run-command.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * Overall FIXMEs:\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 200ffda..a124d88 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -24,6 +24,7 @@\n #include \"string-list.h\"\n #include \"rerere.h\"\n #include \"unpack-trees.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_commit_usage[] = {\n \t\"git commit [options] [--] <filepattern>...\",\ndiff --git a/builtin-count-objects.c b/builtin-count-objects.c\nindex 1b0b6c8..dde93dc 100644\n--- a/builtin-count-objects.c\n+++ b/builtin-count-objects.c\n@@ -8,6 +8,7 @@\n #include \"dir.h\"\n #include \"builtin.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static void count_objects(DIR *d, char *path, int len, int verbose,\n \t\t\t  unsigned long *loose,\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex ffcdd05..49748f0 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -13,6 +13,7 @@\n #include \"revision.h\"\n #include \"log-tree.h\"\n #include \"builtin.h\"\n+#include \"io-i18n.h\"\n \n struct blobinfo {\n \tunsigned char sha1[20];\ndiff --git a/builtin-fast-export.c b/builtin-fast-export.c\nindex b0a4029..932b964 100644\n--- a/builtin-fast-export.c\n+++ b/builtin-fast-export.c\n@@ -16,6 +16,7 @@\n #include \"string-list.h\"\n #include \"utf8.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char *fast_export_usage[] = {\n \t\"git fast-export [rev-list-opts]\",\ndiff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c\nindex 3dbdf7a..91b774d 100644\n--- a/builtin-fetch--tool.c\n+++ b/builtin-fetch--tool.c\n@@ -3,6 +3,7 @@\n #include \"refs.h\"\n #include \"commit.h\"\n #include \"sigchain.h\"\n+#include \"io-i18n.h\"\n \n static char *get_stdin(void)\n {\ndiff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c\nindex 629735f..aecc2f4 100644\n--- a/builtin-fetch-pack.c\n+++ b/builtin-fetch-pack.c\n@@ -9,6 +9,7 @@\n #include \"fetch-pack.h\"\n #include \"remote.h\"\n #include \"run-command.h\"\n+#include \"io-i18n.h\"\n \n static int transfer_unpack_limit = -1;\n static int fetch_unpack_limit = -1;\ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex a35a6f8..14e7f79 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -11,6 +11,7 @@\n #include \"run-command.h\"\n #include \"parse-options.h\"\n #include \"sigchain.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_fetch_usage[] = {\n \t\"git fetch [options] [<repository> <refspec>...]\",\ndiff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c\nindex 9d52400..c002968 100644\n--- a/builtin-fmt-merge-msg.c\n+++ b/builtin-fmt-merge-msg.c\n@@ -4,6 +4,7 @@\n #include \"diff.h\"\n #include \"revision.h\"\n #include \"tag.h\"\n+#include \"io-i18n.h\"\n \n static const char * const fmt_merge_msg_usage[] = {\n \t\"git fmt-merge-msg [--log|--no-log] [--file <file>]\",\ndiff --git a/builtin-fsck.c b/builtin-fsck.c\nindex 2d88e45..67d0826 100644\n--- a/builtin-fsck.c\n+++ b/builtin-fsck.c\n@@ -11,6 +11,7 @@\n #include \"fsck.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n #define REACHABLE 0x0001\n #define SEEN      0x0002\ndiff --git a/builtin-gc.c b/builtin-gc.c\nindex 093517e..e66c817 100644\n--- a/builtin-gc.c\n+++ b/builtin-gc.c\n@@ -14,6 +14,7 @@\n #include \"cache.h\"\n #include \"parse-options.h\"\n #include \"run-command.h\"\n+#include \"io-i18n.h\"\n \n #define FAILED_RUN \"failed to run %s\"\n \ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 1df25b0..3f37fab 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -14,6 +14,7 @@\n #include \"userdiff.h\"\n #include \"grep.h\"\n #include \"quote.h\"\n+#include \"io-i18n.h\"\n \n #ifndef NO_EXTERNAL_GREP\n #ifdef __unix__\ndiff --git a/builtin-help.c b/builtin-help.c\nindex e1eba77..7d54179 100644\n--- a/builtin-help.c\n+++ b/builtin-help.c\n@@ -10,6 +10,7 @@\n #include \"parse-options.h\"\n #include \"run-command.h\"\n #include \"help.h\"\n+#include \"io-i18n.h\"\n \n static struct man_viewer_list {\n \tstruct man_viewer_list *next;\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex dd84cae..61b3f28 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -7,6 +7,7 @@\n #include \"builtin.h\"\n #include \"exec_cmd.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n #ifndef DEFAULT_GIT_TEMPLATE_DIR\n #define DEFAULT_GIT_TEMPLATE_DIR \"/usr/share/git-core/templates\"\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex c5c0407..3669d37 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -11,6 +11,7 @@\n #include \"builtin.h\"\n #include \"tree.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static int abbrev;\n static int show_deleted;\ndiff --git a/builtin-mailinfo.c b/builtin-mailinfo.c\nindex c90cd31..a5f6160 100644\n--- a/builtin-mailinfo.c\n+++ b/builtin-mailinfo.c\n@@ -6,6 +6,7 @@\n #include \"builtin.h\"\n #include \"utf8.h\"\n #include \"strbuf.h\"\n+#include \"io-i18n.h\"\n \n static FILE *cmitmsg, *patchfile, *fin, *fout;\n \ndiff --git a/builtin-mailsplit.c b/builtin-mailsplit.c\nindex dfe5b15..637a0f9 100644\n--- a/builtin-mailsplit.c\n+++ b/builtin-mailsplit.c\n@@ -8,6 +8,7 @@\n #include \"builtin.h\"\n #include \"string-list.h\"\n #include \"strbuf.h\"\n+#include \"io-i18n.h\"\n \n static const char git_mailsplit_usage[] =\n \"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]\";\ndiff --git a/builtin-merge-file.c b/builtin-merge-file.c\nindex afd2ea7..d986758 100644\n--- a/builtin-merge-file.c\n+++ b/builtin-merge-file.c\n@@ -3,6 +3,7 @@\n #include \"xdiff/xdiff.h\"\n #include \"xdiff-interface.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char *const merge_file_usage[] = {\n \t\"git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file file2\",\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex b6b8428..2759c25 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -24,6 +24,7 @@\n #include \"rerere.h\"\n #include \"help.h\"\n #include \"merge-recursive.h\"\n+#include \"io-i18n.h\"\n \n #define DEFAULT_TWOHEAD (1<<0)\n #define DEFAULT_OCTOPUS (1<<1)\ndiff --git a/builtin-mv.c b/builtin-mv.c\nindex 1b20028..8ce8dfd 100644\n--- a/builtin-mv.c\n+++ b/builtin-mv.c\n@@ -9,6 +9,7 @@\n #include \"cache-tree.h\"\n #include \"string-list.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_mv_usage[] = {\n \t\"git mv [options] <source>... <destination>\",\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex 02f9246..2fe3e64 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -16,6 +16,7 @@\n #include \"list-objects.h\"\n #include \"progress.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n #ifdef THREADED_DELTA_SEARCH\n #include \"thread-utils.h\"\ndiff --git a/builtin-prune-packed.c b/builtin-prune-packed.c\nindex be99eb0..30f5a8a 100644\n--- a/builtin-prune-packed.c\n+++ b/builtin-prune-packed.c\n@@ -2,6 +2,7 @@\n #include \"cache.h\"\n #include \"progress.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char * const prune_packed_usage[] = {\n \t\"git prune-packed [-n|--dry-run] [-q|--quiet]\",\ndiff --git a/builtin-prune.c b/builtin-prune.c\nindex 8459aec..bfb7eee 100644\n--- a/builtin-prune.c\n+++ b/builtin-prune.c\n@@ -6,6 +6,7 @@\n #include \"reachable.h\"\n #include \"parse-options.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n static const char * const prune_usage[] = {\n \t\"git prune [-n] [-v] [--expire <time>] [--] [<head>...]\",\ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex e23b5ef..b8b637e 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -7,6 +7,7 @@\n #include \"diff.h\"\n #include \"revision.h\"\n #include \"reachable.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * reflog expire\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex 0777dd7..95ba635 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -6,6 +6,7 @@\n #include \"strbuf.h\"\n #include \"run-command.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_remote_usage[] = {\n \t\"git remote [-v | --verbose]\",\ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex adfb7b5..d3e29e0 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -5,6 +5,7 @@\n #include \"rerere.h\"\n #include \"xdiff/xdiff.h\"\n #include \"xdiff-interface.h\"\n+#include \"io-i18n.h\"\n \n static const char git_rerere_usage[] =\n \"git rerere [clear | status | diff | gc]\";\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex 57975db..a4ba0cd 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -9,6 +9,7 @@\n #include \"cache-tree.h\"\n #include \"tree-walk.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char * const builtin_rm_usage[] = {\n \t\"git rm [options] [--] <file>...\",\ndiff --git a/builtin-tag.c b/builtin-tag.c\nindex c479018..fd42072 100644\n--- a/builtin-tag.c\n+++ b/builtin-tag.c\n@@ -12,6 +12,7 @@\n #include \"tag.h\"\n #include \"run-command.h\"\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char * const git_tag_usage[] = {\n \t\"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]\",\ndiff --git a/builtin-update-index.c b/builtin-update-index.c\nindex 92beaaf..0dab755 100644\n--- a/builtin-update-index.c\n+++ b/builtin-update-index.c\n@@ -9,6 +9,7 @@\n #include \"tree-walk.h\"\n #include \"builtin.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * Default to not allowing changes to the list of files. The\ndiff --git a/builtin-verify-tag.c b/builtin-verify-tag.c\nindex 9f482c2..6271aaf 100644\n--- a/builtin-verify-tag.c\n+++ b/builtin-verify-tag.c\n@@ -11,6 +11,7 @@\n #include \"run-command.h\"\n #include <signal.h>\n #include \"parse-options.h\"\n+#include \"io-i18n.h\"\n \n static const char * const verify_tag_usage[] = {\n \t\t\"git verify-tag [-v|--verbose] <tag>...\",\ndiff --git a/bundle.c b/bundle.c\nindex df95e15..46e6b9e 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -7,6 +7,7 @@\n #include \"list-objects.h\"\n #include \"run-command.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n static const char bundle_signature[] = \"# v2 git bundle\\n\";\n \ndiff --git a/check-racy.c b/check-racy.c\nindex 00d92a1..05eeedf 100644\n--- a/check-racy.c\n+++ b/check-racy.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n int main(int ac, char **av)\n {\ndiff --git a/combine-diff.c b/combine-diff.c\nindex 5b63af1..1d6eb1c 100644\n--- a/combine-diff.c\n+++ b/combine-diff.c\n@@ -7,6 +7,7 @@\n #include \"xdiff-interface.h\"\n #include \"log-tree.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)\n {\ndiff --git a/commit.c b/commit.c\nindex fedbd5e..cbdc8c3 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -5,6 +5,7 @@\n #include \"utf8.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n+#include \"io-i18n.h\"\n \n int save_commit_buffer = 1;\n \ndiff --git a/config.c b/config.c\nindex 2be6531..9826eff 100644\n--- a/config.c\n+++ b/config.c\n@@ -7,6 +7,7 @@\n  */\n #include \"cache.h\"\n #include \"exec_cmd.h\"\n+#include \"io-i18n.h\"\n \n #define MAXNAME (256)\n \ndiff --git a/copy.c b/copy.c\nindex a7f58fd..de64127 100644\n--- a/copy.c\n+++ b/copy.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n int copy_fd(int ifd, int ofd)\n {\ndiff --git a/daemon.c b/daemon.c\nindex 1b5ada6..42f70e5 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -3,6 +3,7 @@\n #include \"exec_cmd.h\"\n #include \"run-command.h\"\n #include \"strbuf.h\"\n+#include \"io-i18n.h\"\n \n #include <syslog.h>\n \ndiff --git a/diff-lib.c b/diff-lib.c\nindex 0c74ef5..988baee 100644\n--- a/diff-lib.c\n+++ b/diff-lib.c\n@@ -10,6 +10,7 @@\n #include \"cache-tree.h\"\n #include \"unpack-trees.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * diff-files\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 4ebc1db..b12ad8f 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -15,6 +15,7 @@\n #include \"log-tree.h\"\n #include \"builtin.h\"\n #include \"string-list.h\"\n+#include \"io-i18n.h\"\n \n static int read_directory(const char *path, struct string_list *list)\n {\ndiff --git a/diff.c b/diff.c\nindex b0c7e61..b875429 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -13,6 +13,7 @@\n #include \"utf8.h\"\n #include \"userdiff.h\"\n #include \"sigchain.h\"\n+#include \"io-i18n.h\"\n \n #ifdef NO_FAST_WORKING_DIRECTORY\n #define FAST_WORKING_DIRECTORY 0\ndiff --git a/diffcore-order.c b/diffcore-order.c\nindex 23e9385..6ce4d4a 100644\n--- a/diffcore-order.c\n+++ b/diffcore-order.c\n@@ -4,6 +4,7 @@\n #include \"cache.h\"\n #include \"diff.h\"\n #include \"diffcore.h\"\n+#include \"io-i18n.h\"\n \n static char **order;\n static int order_cnt;\ndiff --git a/dir.c b/dir.c\nindex d0999ba..8bbee16 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -8,6 +8,7 @@\n #include \"cache.h\"\n #include \"dir.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n struct path_simplify {\n \tint len;\ndiff --git a/entry.c b/entry.c\nindex 06d24f1..b01a23b 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"blob.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n static void create_directories(const char *path, int path_len,\n \t\t\t       const struct checkout *state)\ndiff --git a/fast-import.c b/fast-import.c\nindex 6faaaac..97d010d 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -152,6 +152,7 @@ Format of STDIN stream:\n #include \"csum-file.h\"\n #include \"quote.h\"\n #include \"exec_cmd.h\"\n+#include \"io-i18n.h\"\n \n #define PACK_ID_BITS 16\n #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)\ndiff --git a/hash-object.c b/hash-object.c\nindex 9455dd0..0f17bbd 100644\n--- a/hash-object.c\n+++ b/hash-object.c\n@@ -9,6 +9,7 @@\n #include \"quote.h\"\n #include \"parse-options.h\"\n #include \"exec_cmd.h\"\n+#include \"io-i18n.h\"\n \n static void hash_fd(int fd, const char *type, int write_object, const char *path)\n {\ndiff --git a/help.c b/help.c\nindex e8db31f..fcbb8c0 100644\n--- a/help.c\n+++ b/help.c\n@@ -3,6 +3,7 @@\n #include \"exec_cmd.h\"\n #include \"levenshtein.h\"\n #include \"help.h\"\n+#include \"io-i18n.h\"\n \n /* most GUI terminals set COLUMNS (although some don't export it) */\n static int term_columns(void)\ndiff --git a/http.c b/http.c\nindex 23b2a19..d064f58 100644\n--- a/http.c\n+++ b/http.c\n@@ -1,5 +1,6 @@\n #include \"http.h\"\n #include \"pack.h\"\n+#include \"io-i18n.h\"\n \n int data_received;\n int active_requests;\ndiff --git a/index-pack.c b/index-pack.c\nindex b4f8278..2ae89c4 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -9,6 +9,7 @@\n #include \"progress.h\"\n #include \"fsck.h\"\n #include \"exec_cmd.h\"\n+#include \"io-i18n.h\"\n \n static const char index_pack_usage[] =\n \"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }\";\ndiff --git a/ll-merge.c b/ll-merge.c\nindex 2d6b6d6..beff7a9 100644\n--- a/ll-merge.c\n+++ b/ll-merge.c\n@@ -9,6 +9,7 @@\n #include \"xdiff-interface.h\"\n #include \"run-command.h\"\n #include \"ll-merge.h\"\n+#include \"io-i18n.h\"\n \n struct ll_merge_driver;\n \ndiff --git a/lockfile.c b/lockfile.c\nindex 6851fa5..fea9f4c 100644\n--- a/lockfile.c\n+++ b/lockfile.c\n@@ -3,6 +3,7 @@\n  */\n #include \"cache.h\"\n #include \"sigchain.h\"\n+#include \"io-i18n.h\"\n \n static struct lock_file *lock_file_list;\n static const char *alternate_index_output;\ndiff --git a/mailmap.c b/mailmap.c\nindex f167c00..7239fb7 100644\n--- a/mailmap.c\n+++ b/mailmap.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"string-list.h\"\n #include \"mailmap.h\"\n+#include \"io-i18n.h\"\n \n #define DEBUG_MAILMAP 0\n #if DEBUG_MAILMAP\ndiff --git a/merge-recursive.c b/merge-recursive.c\nindex f55b7eb..3258c49 100644\n--- a/merge-recursive.c\n+++ b/merge-recursive.c\n@@ -19,6 +19,7 @@\n #include \"attr.h\"\n #include \"merge-recursive.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n static struct tree *shift_tree_object(struct tree *one, struct tree *two)\n {\ndiff --git a/pack-write.c b/pack-write.c\nindex 741efcd..00d2c4a 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"pack.h\"\n #include \"csum-file.h\"\n+#include \"io-i18n.h\"\n \n uint32_t pack_idx_default_version = 2;\n uint32_t pack_idx_off32_limit = 0x7fffffff;\ndiff --git a/path.c b/path.c\nindex 047fdb0..b598190 100644\n--- a/path.c\n+++ b/path.c\n@@ -11,6 +11,7 @@\n  * which is what it's designed for.\n  */\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n static char bad_path[] = \"/bad-path/\";\n \ndiff --git a/preload-index.c b/preload-index.c\nindex 9289933..bfab0c3 100644\n--- a/preload-index.c\n+++ b/preload-index.c\n@@ -2,6 +2,7 @@\n  * Copyright (C) 2008 Linus Torvalds\n  */\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n #ifdef NO_PTHREADS\n static void preload_index(struct index_state *index, const char **pathspec)\ndiff --git a/read-cache.c b/read-cache.c\nindex 1bbaf1c..cc06da2 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -14,6 +14,7 @@\n #include \"diffcore.h\"\n #include \"revision.h\"\n #include \"blob.h\"\n+#include \"io-i18n.h\"\n \n /* Index extensions.\n  *\ndiff --git a/refs.c b/refs.c\nindex 808f56b..53f6539 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3,6 +3,7 @@\n #include \"object.h\"\n #include \"tag.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n /* ISSYMREF=01 and ISPACKED=02 are public interfaces */\n #define REF_KNOWS_PEELED 04\ndiff --git a/remote.c b/remote.c\nindex 73d33f2..780ff75 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -6,6 +6,7 @@\n #include \"revision.h\"\n #include \"dir.h\"\n #include \"tag.h\"\n+#include \"io-i18n.h\"\n \n static struct refspec s_tag_refspec = {\n \t0,\ndiff --git a/rerere.c b/rerere.c\nindex 29f95f6..dfff2ac 100644\n--- a/rerere.c\n+++ b/rerere.c\n@@ -3,6 +3,7 @@\n #include \"rerere.h\"\n #include \"xdiff/xdiff.h\"\n #include \"xdiff-interface.h\"\n+#include \"io-i18n.h\"\n \n /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */\n static int rerere_enabled = -1;\ndiff --git a/server-info.c b/server-info.c\nindex 4098ca2..f074057 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -3,6 +3,7 @@\n #include \"object.h\"\n #include \"commit.h\"\n #include \"tag.h\"\n+#include \"io-i18n.h\"\n \n /* refs */\n static FILE *info_ref_fp;\ndiff --git a/setup.c b/setup.c\nindex 029371e..c87efa3 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -1,5 +1,6 @@\n #include \"cache.h\"\n #include \"dir.h\"\n+#include \"io-i18n.h\"\n \n static int inside_git_dir = -1;\n static int inside_work_tree = -1;\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 63981fb..3f9145f 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -16,6 +16,7 @@\n #include \"refs.h\"\n #include \"pack-revindex.h\"\n #include \"sha1-lookup.h\"\n+#include \"io-i18n.h\"\n \n #ifndef O_NOATIME\n #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 44bb62d..bee34aa 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -5,6 +5,7 @@\n #include \"blob.h\"\n #include \"tree-walk.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n static int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n {\ndiff --git a/shallow.c b/shallow.c\nindex 4d90eda..745b64f 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n #include \"commit.h\"\n #include \"tag.h\"\n+#include \"io-i18n.h\"\n \n static int is_shallow = -1;\n \ndiff --git a/strbuf.c b/strbuf.c\nindex a6153dc..1baa78a 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -1,5 +1,6 @@\n #include \"cache.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n int prefixcmp(const char *str, const char *prefix)\n {\ndiff --git a/symlinks.c b/symlinks.c\nindex 7b0a86d..7907186 100644\n--- a/symlinks.c\n+++ b/symlinks.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * Returns the length (on a path component basis) of the longest\ndiff --git a/test-chmtime.c b/test-chmtime.c\nindex fe476cb..6471850 100644\n--- a/test-chmtime.c\n+++ b/test-chmtime.c\n@@ -29,6 +29,7 @@\n  */\n #include \"git-compat-util.h\"\n #include <utime.h>\n+#include \"io-i18n.h\"\n \n static const char usage_str[] = \"-v|--verbose (+|=|=+|=-|-)<seconds> <file>...\";\n \ndiff --git a/test-delta.c b/test-delta.c\nindex af40a3c..24d678f 100644\n--- a/test-delta.c\n+++ b/test-delta.c\n@@ -11,6 +11,7 @@\n #include \"git-compat-util.h\"\n #include \"delta.h\"\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n static const char usage_str[] =\n \t\"test-delta (-d|-p) <from_file> <data_file> <out_file>\";\ndiff --git a/trace.c b/trace.c\nindex 4229ae1..616a64e 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -24,6 +24,7 @@\n \n #include \"cache.h\"\n #include \"quote.h\"\n+#include \"io-i18n.h\"\n \n /* Get a trace file descriptor from GIT_TRACE env variable. */\n static int get_trace_fd(int *need_close)\ndiff --git a/transport.c b/transport.c\nindex 644a30a..3e898aa 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -8,6 +8,7 @@\n #include \"bundle.h\"\n #include \"dir.h\"\n #include \"refs.h\"\n+#include \"io-i18n.h\"\n \n /* rsync support */\n \ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 720f7a1..5bad618 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -8,6 +8,7 @@\n #include \"progress.h\"\n #include \"refs.h\"\n #include \"attr.h\"\n+#include \"io-i18n.h\"\n \n /*\n  * Error messages expected by scripts out of plumbing commands such as\ndiff --git a/wrapper.c b/wrapper.c\nindex c9be140..0a89eec 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -2,6 +2,7 @@\n  * Various trivial helper wrappers around standard functions\n  */\n #include \"cache.h\"\n+#include \"io-i18n.h\"\n \n char *xstrdup(const char *str)\n {\ndiff --git a/xdiff-interface.c b/xdiff-interface.c\nindex 01f14fb..dee800c 100644\n--- a/xdiff-interface.c\n+++ b/xdiff-interface.c\n@@ -4,6 +4,7 @@\n #include \"xdiff/xdiffi.h\"\n #include \"xdiff/xemit.h\"\n #include \"xdiff/xmacros.h\"\n+#include \"io-i18n.h\"\n \n struct xdiff_emit_state {\n \txdiff_emit_consume_fn consume;\n-- \n1.6.5.1\n"},{"id":"126167","messageId":"1256752900-2615-3-git-send-email-timur@iris-comp.ru","threadId":"21406","inReplyTo":"1256752900-2615-2-git-send-email-timur@iris-comp.ru","subject":"[PATCH I18N filenames v2 3/3] Provide compatibility with MinGW","fromName":"Timur Sufiev","fromEmail":"timur@iris-comp.ru","sentAt":"2009-10-28T18:01:40Z","receivedAt":"2009-10-28T18:01:40Z","isPatch":true,"sender":{"key":"timur@iris-comp.ru","avatar":null},"body":"Signed-off-by: Timur Sufiev <timur@iris-comp.ru>\n---\n compat/fopen.c    |    5 +++--\n compat/mingw.c    |   37 ++++++++++++++++++++++++++++---------\n compat/mingw.h    |    6 +++++-\n compat/mkstemps.c |    3 ++-\n compat/win32.h    |   13 +++++++++++--\n io-i18n.c         |    5 +++++\n io-i18n.h         |    7 +++++++\n 7 files changed, 61 insertions(+), 15 deletions(-)\n\ndiff --git a/compat/fopen.c b/compat/fopen.c\nindex b5ca142..9136a14 100644\n--- a/compat/fopen.c\n+++ b/compat/fopen.c\n@@ -10,6 +10,7 @@\n  */\n #undef FREAD_READS_DIRECTORIES\n #include \"../git-compat-util.h\"\n+#include \"io-i18n.h\"\n \n FILE *git_fopen(const char *path, const char *mode)\n {\n@@ -17,9 +18,9 @@ FILE *git_fopen(const char *path, const char *mode)\n \tstruct stat st;\n \n \tif (mode[0] == 'w' || mode[0] == 'a')\n-\t\treturn fopen(path, mode);\n+\t\treturn fopen_i18n(path, mode);\n \n-\tif (!(fp = fopen(path, mode)))\n+\tif (!(fp = fopen_i18n(path, mode)))\n \t\treturn NULL;\n \n \tif (fstat(fileno(fp), &st)) {\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6b5b5b2..2a2ebcb 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -2,7 +2,7 @@\n #include \"win32.h\"\n #include <conio.h>\n #include \"../strbuf.h\"\n-\n+#include \"../io-i18n.h\"\n #include <shellapi.h>\n \n static int err_win_to_posix(DWORD winerr)\n@@ -132,7 +132,7 @@ int mingw_open (const char *filename, int oflags, ...)\n \tif (!strcmp(filename, \"/dev/null\"))\n \t\tfilename = \"nul\";\n \n-\tfd = open(filename, oflags, mode);\n+\tfd = open_i18n(filename, oflags, mode);\n \n \tif (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {\n \t\tDWORD attrs = GetFileAttributes(filename);\n@@ -253,7 +253,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)\n \tint fh, rc;\n \n \t/* must have write permission */\n-\tif ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)\n+\tif ((fh = open_i18n(file_name, O_RDWR | O_BINARY)) < 0)\n \t\treturn -1;\n \n \ttime_t_to_filetime(times->modtime, &mft);\n@@ -278,7 +278,7 @@ int mkstemp(char *template)\n \tchar *filename = mktemp(template);\n \tif (filename == NULL)\n \t\treturn -1;\n-\treturn open(filename, O_RDWR | O_CREAT, 0600);\n+\treturn open_i18n(filename, O_RDWR | O_CREAT, 0600);\n }\n \n int gettimeofday(struct timeval *tv, void *tz)\n@@ -519,7 +519,7 @@ static const char *parse_interpreter(const char *cmd)\n \tif (n >= 4 && !strcasecmp(cmd+n-4, \".exe\"))\n \t\treturn NULL;\n \n-\tfd = open(cmd, O_RDONLY);\n+\tfd = open_i18n(cmd, O_RDONLY);\n \tif (fd < 0)\n \t\treturn NULL;\n \tn = read(fd, buf, sizeof(buf)-1);\n@@ -1135,10 +1135,14 @@ sig_handler_t mingw_signal(int sig, sig_handler_t handler)\n static const char *make_backslash_path(const char *path)\n {\n \tstatic char buf[PATH_MAX + 1];\n+\tchar *out = filename_to_local(path);\n \tchar *c;\n \n-\tif (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)\n-\t\tdie(\"Too long path: %.*s\", 60, path);\n+\tif ( strlcpy(buf, out ? out : path, PATH_MAX) >= PATH_MAX) {\n+\t     die(\"Too long path: %.*s\", 60, out ? out : path);\n+\t     free(out);\n+\t}\n+\tfree(out);\n \n \tfor (c = buf; *c; c++) {\n \t\tif (*c == '/')\n@@ -1158,6 +1162,9 @@ int link(const char *oldpath, const char *newpath)\n {\n \ttypedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES);\n \tstatic T create_hard_link = NULL;\n+\tchar *old_out = filename_to_local(oldpath);\n+\tchar *new_out = filename_to_local(newpath);\n+\n \tif (!create_hard_link) {\n \t\tcreate_hard_link = (T) GetProcAddress(\n \t\t\tGetModuleHandle(\"kernel32.dll\"), \"CreateHardLinkA\");\n@@ -1168,10 +1175,15 @@ int link(const char *oldpath, const char *newpath)\n \t\terrno = ENOSYS;\n \t\treturn -1;\n \t}\n-\tif (!create_hard_link(newpath, oldpath, NULL)) {\n+\tif (!create_hard_link(new_out ? new_out : newpath,\n+\t\t\t      old_out ? old_out : oldpath, NULL)) {\n+\t\tfree(new_out);\n+\t\tfree(old_out);\n \t\terrno = err_win_to_posix(GetLastError());\n \t\treturn -1;\n \t}\n+\tfree(new_out);\n+\tfree(old_out);\n \treturn 0;\n }\n \n@@ -1206,6 +1218,7 @@ struct dirent *mingw_readdir(DIR *dir)\n \tWIN32_FIND_DATAA buf;\n \tHANDLE handle;\n \tstruct mingw_DIR *mdir = (struct mingw_DIR*)dir;\n+\tchar *out;\n \n \tif (!dir->dd_handle) {\n \t\terrno = EBADF; /* No set_errno for mingw */\n@@ -1236,7 +1249,13 @@ struct dirent *mingw_readdir(DIR *dir)\n \t}\n \n \t/* We get here if `buf' contains valid data.  */\n-\tstrcpy(dir->dd_dir.d_name, buf.cFileName);\n+\tout = filename_to_utf8(buf.cFileName);\n+\tif ( strlcpy(dir->dd_dir.d_name,\n+\t\t     out ? out : buf.cFileName, FILENAME_MAX) >= FILENAME_MAX) {\n+\t     die(\"Too long dir entry name: %.*s\", 60,\n+\t\t out ? out : buf.cFileName);\n+\t     free(out);\n+\t}\n \t++dir->dd_stat;\n \n \t/* Set file type, based on WIN32_FIND_DATA */\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 5b5258b..2447aa7 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -1,4 +1,7 @@\n+#ifndef GIT_MINGW_H\n+#define GIT_MINGW_H\n #include <winsock2.h>\n+#include \"../io-i18n.h\"\n \n /*\n  * things that are not available in header files\n@@ -112,7 +115,7 @@ static inline int mingw_unlink(const char *pathname)\n {\n \t/* read-only files cannot be removed */\n \tchmod(pathname, 0666);\n-\treturn unlink(pathname);\n+\treturn unlink_i18n(pathname);\n }\n #define unlink mingw_unlink\n \n@@ -273,3 +276,4 @@ struct mingw_dirent\n #define readdir(x) mingw_readdir(x)\n struct dirent *mingw_readdir(DIR *dir);\n #endif // !NO_MINGW_REPLACE_READDIR\n+#endif // GIT_MINGW_H\ndiff --git a/compat/mkstemps.c b/compat/mkstemps.c\nindex 14179c8..0cdd42d 100644\n--- a/compat/mkstemps.c\n+++ b/compat/mkstemps.c\n@@ -1,4 +1,5 @@\n #include \"../git-compat-util.h\"\n+#include \"../io-i18n.h\"\n \n /* Adapted from libiberty's mkstemp.c. */\n \n@@ -47,7 +48,7 @@ int gitmkstemps(char *pattern, int suffix_len)\n \t\ttemplate[4] = letters[v % num_letters]; v /= num_letters;\n \t\ttemplate[5] = letters[v % num_letters]; v /= num_letters;\n \n-\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);\n+\t\tfd = open_i18n(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);\n \t\tif (fd > 0)\n \t\t\treturn fd;\n \t\t/*\ndiff --git a/compat/win32.h b/compat/win32.h\nindex 8ce9104..f71e36d 100644\n--- a/compat/win32.h\n+++ b/compat/win32.h\n@@ -20,8 +20,17 @@ static inline int file_attr_to_st_mode (DWORD attr)\n \n static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)\n {\n-\tif (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))\n-\t\treturn 0;\n+\tchar *out = filename_to_local(fname);\n+\tint ret;\n+\n+\tif ( out != NULL ) {\n+\t     ret = GetFileAttributesExA(out, GetFileExInfoStandard, fdata);\n+\t     free(out);\n+\t} else\n+\t     ret = GetFileAttributesExA(fname, GetFileExInfoStandard, fdata);\n+\n+\tif ( ret )\n+\t     return 0;\n \n \tswitch (GetLastError()) {\n \tcase ERROR_ACCESS_DENIED:\ndiff --git a/io-i18n.c b/io-i18n.c\nindex ed88a68..63e88b8 100644\n--- a/io-i18n.c\n+++ b/io-i18n.c\n@@ -84,6 +84,7 @@ char *filename_to_local(const char *filename)\n #endif\n }\n \n+#ifndef __USE_MINGW_ACCESS\n #undef stat\n int stat_i18n(const char *filename, struct stat *buf)\n {\n@@ -127,6 +128,7 @@ int link_i18n(const char *oldname, const char *newname)\n \t\tfree(new_out);\n \treturn ret;\n }\n+#endif // __USE_MINGW_ACCESS\n \n #undef open\n int open_i18n(const char *filename, int flags, ...)\n@@ -165,6 +167,8 @@ int unlink_i18n(const char *filename)\n \treturn ret;\n }\n \n+#if !defined(__USE_MINGW_ACCESS) || \\\n+     (defined(__USE_MINGW_ACCESS) && defined(NO_MINGW_REPLACE_READDIR))\n #undef readdir\n struct dirent *readdir_i18n(DIR * dirstream)\n {\n@@ -187,6 +191,7 @@ struct dirent *readdir_i18n(DIR * dirstream)\n \t} else\n \t\treturn NULL;\n }\n+#endif\n \n #undef opendir\n DIR *opendir_i18n(const char *dirname)\ndiff --git a/io-i18n.h b/io-i18n.h\nindex 2369d31..38f73b3 100644\n--- a/io-i18n.h\n+++ b/io-i18n.h\n@@ -23,11 +23,18 @@ int unlink_i18n(const char *filename);\n #define opendir(a) opendir_i18n(a)\n #define fopen(a, b) fopen_i18n(a, b)\n #define chmod(a, b) chmod_i18n(a, b)\n+\n+#ifndef __USE_MINGW_ACCESS\n #define open open_i18n\n #define stat(a, b) stat_i18n(a, b)\n #define lstat(a, b) lstat_i18n(a, b)\n #define readdir(a) readdir_i18n(a)\n #define unlink(a) unlink_i18n(a)\n #define link(a, b) link_i18n(a, b)\n+#endif // __USE_MINGW_ACCESS\n+\n+#if defined(__USE_MINGW_ACCESS) && defined(NO_MINGW_REPLACE_READDIR)\n+#define readdir(a) readdir_i18n(a)\n+#endif\n \n #endif /* GIT_IO_I18N_H */\n-- \n1.6.5.1\n"},{"id":"126254","messageId":"alpine.DEB.2.00.0910290955530.8995@ds9.cixit.se","threadId":"21406","inReplyTo":"1256752900-2615-3-git-send-email-timur@iris-comp.ru","subject":"Re: [PATCH I18N filenames v2 3/3] Provide compatibility with MinGW","fromName":"Peter Krefting","fromEmail":"peter@softwolves.pp.se","sentAt":"2009-10-29T09:01:01Z","receivedAt":"2009-10-29T09:01:01Z","isPatch":true,"sender":{"key":"peter@softwolves.pp.se","avatar":"https://avatars.githubusercontent.com/u/990764?v=4"},"body":"Hi!\n\nTimur Sufiev:\n\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 6b5b5b2..2a2ebcb 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -2,7 +2,7 @@\n> #include \"win32.h\"\n> #include <conio.h>\n> #include \"../strbuf.h\"\n> -\n> +#include \"../io-i18n.h\"\n> #include <shellapi.h>\n>\n> static int err_win_to_posix(DWORD winerr)\n> @@ -132,7 +132,7 @@ int mingw_open (const char *filename, int oflags, ...)\n> \tif (!strcmp(filename, \"/dev/null\"))\n> \t\tfilename = \"nul\";\n>\n> -\tfd = open(filename, oflags, mode);\n> +\tfd = open_i18n(filename, oflags, mode);\n>\n> \tif (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {\n> \t\tDWORD attrs = GetFileAttributes(filename);\n\nInstead of calling the open_i18n() which converts from UTF-8 to a local \n8-bit character set, this should probably call a version that converts from \nUTF-8 to UTF-16 and uses _wopen().\n\nSame thing for fopen_i18n() and _wfopen().\n\nI created a small RFC patch for that that changed parts of the system \nearlier this year - http://kerneltrap.org/mailarchive/git/2009/3/2/5350814\n\nI did not address readdir() and friends, I'm not sure if they are available \nin UTF-16 form or if they need to be rewritten using findfirst()/findnext().\n\n-- \n\\\\// Peter - http://www.softwolves.pp.se/\n"},{"id":"126255","messageId":"4AE95FDF.7030601@viscovery.net","threadId":"21406","inReplyTo":"1256752900-2615-1-git-send-email-timur@iris-comp.ru","subject":"Re: [PATCH I18N filenames v2 1/3] Add IO-wrappers for filenames encoding <local encoding> <-> UTF-8","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-29T09:26:55Z","receivedAt":"2009-10-29T09:26:55Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Timur Sufiev schrieb:\n> +#define opendir(a) opendir_i18n(a)\n> +#define fopen(a, b) fopen_i18n(a, b)\n> +#define chmod(a, b) chmod_i18n(a, b)\n> +#define open open_i18n\n> +#define stat(a, b) stat_i18n(a, b)\n> +#define lstat(a, b) lstat_i18n(a, b)\n> +#define readdir(a) readdir_i18n(a)\n> +#define unlink(a) unlink_i18n(a)\n> +#define link(a, b) link_i18n(a, b)\n\nI doubt that such a whole-sale replacement is necessary. For example,\nnames of object files (in .git/objects/XX) need not be translated, nor ref\nnames.\n\nPlease review the infrastructure patch that Linus provided (as pointed out\nby Jeff) and see how you can build on it. IIRC, there are a handful of\ncentral places where path names must be massaged, and perhaps a few others\nas fall-out.\n\nMoreover, once you know what to change, it would be worthwhile to check\nhow the file name translation can be adjusted to use the UTF16 versions of\nthe functions on Windows to avoid the UTF8<->UTF16 conversion (that\nhappens on Windows behind the scenes). Perhaps MacOS can profit from this,\ntoo.\n\n-- Hannes\n"},{"id":"126256","messageId":"81b0412b0910290230x9092c88n414ad0e03fc7f8db@mail.gmail.com","threadId":"21406","inReplyTo":"1256752900-2615-2-git-send-email-timur@iris-comp.ru","subject":"Re: [PATCH I18N filenames v2 2/3] Use I18N-wrappers everywhere in Git","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-10-29T09:30:58Z","receivedAt":"2009-10-29T09:30:58Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Wed, Oct 28, 2009 at 19:01, Timur Sufiev <timur@iris-comp.ru> wrote:\n> Signed-off-by: Timur Sufiev <timur@iris-comp.ru>\n> ---\n>  abspath.c               |    1 +\n>  attr.c                  |    1 +\n>  bisect.c                |    1 +\n\nInstead of modifying all these files you could just have put that\ndarn header in compat/mingw.h\n"}]}