音楽メモ

2012年06月08日

git UTF-8-MAC やっつけ対応パッチ

SourceTree の圧倒的な素晴らしさと致命的な欠点について。(修正済み) - こせきの技術日記を見て思い出しましたが、以前git UTF-8-Mac対応+野良ビルド - 音楽メモでこう書いていました。

Mac OS XのHFS+ファイルシステムUTF-8NFCではなくNFDでファイル名を返してくるのでgitがまともに動きません。readdir()にファイル名を変換するラッパーをかませて対処しました。

詳細な対処内容は書いてませんでした。まともな対処方法なのか分からないし、ちゃんとupstreamにフィードバックする気力もないので、とりあえず以下にパッチを貼付けておきます。v1.7.4-rc0からの差分になってると思います(たぶん)。argv文字列も変換してるようです(もうよく覚えていません)。

一応この改造gitコマンドのパスをGitXとかSourceTreeに指定して、"ソ・ラ・ノ・ヲ・ト 3 Flânerie.sib"とか"ぴゅあぴゅあはーと.sib"みたいなファイル名を扱えてます。

diff --git a/Makefile b/Makefile
index 775ee83..a6e1e47 100644
--- a/Makefile
+++ b/Makefile
@@ -1233,6 +1233,9 @@ ifeq ($(uname_S),Darwin)
 		endif
 	endif
 	PTHREAD_LIBS =
+	COMPAT_CFLAGS += -DREADDIR_UTF8NFD2NFC
+	COMPAT_OBJS += compat/readdir.o
+	COMPAT_CFLAGS += -DARGV_UTF8NFD2NFC
 endif
 
 ifndef CC_LD_DYNPATH
diff --git a/compat/readdir.c b/compat/readdir.c
new file mode 100644
index 0000000..45d0d57
--- /dev/null
+++ b/compat/readdir.c
@@ -0,0 +1,32 @@
+#define READDIR_UTF8NFD2NFC_INTERNAL
+#include "../git-compat-util.h"
+#include "../strbuf.h"
+#include "../utf8.h"
+
+struct dirent *git_readdir_utf8nfd2nfc(DIR *dirp)
+{
+	struct dirent *dentp = NULL;
+	static struct dirent dent;
+	char *out = NULL;
+	const char *in = NULL;
+	const char *out_encoding = "UTF-8";
+	const char *in_encoding = "UTF-8-MAC";
+
+	dentp = readdir(dirp);
+	if (!dentp) return dentp;
+	dent = *dentp;
+
+	in = dent.d_name;
+	out = reencode_string(in, out_encoding, in_encoding);
+	if (!out) {
+		fprintf(stderr, "git_readdir_utf8nfd2nfc: fail: \"%s\"\n",
+			dent.d_name);
+		return NULL;
+	}
+	strncpy(dent.d_name, out, sizeof(dent.d_name)-1);
+	dent.d_name[sizeof(dent.d_name)-1] = '\0';
+	dent.d_namlen = strlen(dent.d_name);
+	free(out);
+
+	return &dent;
+}
diff --git a/git-compat-util.h b/git-compat-util.h
index d6d269f..74110db 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -509,6 +509,13 @@ void git_qsort(void *base, size_t nmemb, size_t size,
 # define FORCE_DIR_SET_GID 0
 #endif
 
+#ifdef READDIR_UTF8NFD2NFC
+struct dirent *git_readdir_utf8nfd2nfc(DIR *dirp);
+#ifndef READDIR_UTF8NFD2NFC_INTERNAL
+#define readdir git_readdir_utf8nfd2nfc
+#endif
+#endif
+
 #ifdef NO_NSEC
 #undef USE_NSEC
 #define ST_CTIME_NSEC(st) 0
diff --git a/git.c b/git.c
index 68334f6..5fb47b0 100644
--- a/git.c
+++ b/git.c
@@ -4,6 +4,8 @@
 #include "help.h"
 #include "quote.h"
 #include "run-command.h"
+#include "strbuf.h"
+#include "utf8.h"
 
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=<path>]] [--html-path]\n"
@@ -511,6 +513,26 @@ int main(int argc, const char **argv)
 {
 	const char *cmd;
 
+#ifdef ARGV_UTF8NFD2NFC
+	const char **argv_orig = argv;
+	int i;
+
+	argv = xcalloc(argc+1, sizeof(*argv));
+	for (i = 0; i < argc; i++) {
+		char *out = NULL;
+		const char *in = argv_orig[i];
+		const char *out_encoding = "UTF-8";
+		const char *in_encoding = "UTF-8-MAC";
+
+		out = reencode_string(in, out_encoding, in_encoding);
+		if (!out) {
+			die("git: argv conv fail: \"%s\"\n", in);
+		}
+		argv[i] = out;
+	}
+	argv[i] = NULL;
+#endif
+
 	startup_info = &git_startup_info;
 
 	cmd = git_extract_argv0_path(argv[0]);

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/cantus/20120608/1339184650
Connection: close