mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
![Torsten Bögershausen](/assets/img/avatar_default.png)
Mac OS X mangles file names containing unicode on file systems HFS+, VFAT or SAMBA. When a file using unicode code points outside ASCII is created on a HFS+ drive, the file name is converted into decomposed unicode and written to disk. No conversion is done if the file name is already decomposed unicode. Calling open("\xc3\x84", ...) with a precomposed "Ä" yields the same result as open("\x41\xcc\x88",...) with a decomposed "Ä". As a consequence, readdir() returns the file names in decomposed unicode, even if the user expects precomposed unicode. Unlike on HFS+, Mac OS X stores files on a VFAT drive (e.g. an USB drive) in precomposed unicode, but readdir() still returns file names in decomposed unicode. When a git repository is stored on a network share using SAMBA, file names are send over the wire and written to disk on the remote system in precomposed unicode, but Mac OS X readdir() returns decomposed unicode to be compatible with its behaviour on HFS+ and VFAT. The unicode decomposition causes many problems: - The names "git add" and other commands get from the end user may often be precomposed form (the decomposed form is not easily input from the keyboard), but when the commands read from the filesystem to see what it is going to update the index with already is on the filesystem, readdir() will give decomposed form, which is different. - Similarly "git log", "git mv" and all other commands that need to compare pathnames found on the command line (often but not always precomposed form; a command line input resulting from globbing may be in decomposed) with pathnames found in the tree objects (should be precomposed form to be compatible with other systems and for consistency in general). - The same for names stored in the index, which should be precomposed, that may need to be compared with the names read from readdir(). NFS mounted from Linux is fully transparent and does not suffer from the above. As Mac OS X treats precomposed and decomposed file names as equal, we can - wrap readdir() on Mac OS X to return the precomposed form, and - normalize decomposed form given from the command line also to the precomposed form, to ensure that all pathnames used in Git are always in the precomposed form. This behaviour can be requested by setting "core.precomposedunicode" configuration variable to true. The code in compat/precomposed_utf8.c implements basically 4 new functions: precomposed_utf8_opendir(), precomposed_utf8_readdir(), precomposed_utf8_closedir() and precompose_argv(). The first three are to wrap opendir(3), readdir(3), and closedir(3) functions. The argv[] conversion allows to use the TAB filename completion done by the shell on command line. It tolerates other tools which use readdir() to feed decomposed file names into git. When creating a new git repository with "git init" or "git clone", "core.precomposedunicode" will be set "false". The user needs to activate this feature manually. She typically sets core.precomposedunicode to "true" on HFS and VFAT, or file systems mounted via SAMBA. Helped-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
24 lines
730 B
C
24 lines
730 B
C
#ifndef GIT_UTF8_H
|
|
#define GIT_UTF8_H
|
|
|
|
typedef unsigned int ucs_char_t; /* assuming 32bit int */
|
|
|
|
int utf8_width(const char **start, size_t *remainder_p);
|
|
int utf8_strwidth(const char *string);
|
|
int is_utf8(const char *text);
|
|
int is_encoding_utf8(const char *name);
|
|
|
|
int strbuf_add_wrapped_text(struct strbuf *buf,
|
|
const char *text, int indent, int indent2, int width);
|
|
int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
|
|
int indent, int indent2, int width);
|
|
|
|
#ifndef NO_ICONV
|
|
char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv);
|
|
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);
|
|
#else
|
|
#define reencode_string(a,b,c) NULL
|
|
#endif
|
|
|
|
#endif
|