libgit2 / libgit2/libgit2sharp

i18n.commitEncoding is EVIL

未關閉
#532 3 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

主要語言
C#
星號
3.5k
分支
925
PR 合併指標
30 天內沒有已合併 PR

描述

Recently days I am researching i18n.commitEncoding, It's real an EVIL!!

First of all, I am a Chinese that OS language is en-us with Chinese(simplified) region. The commonly used encoding is GB2312(also GBK, code page 936).

The i18n.commitEncoding was defined in here that Character encoding the commit messages are stored in; git itself does not care per se, but this information is necessary.

OK, It's mean this config will affect the commit messages. but, I have find no any documents to define the format of encoding. I open the references window of Git GUI, and find the Default File Contents Encoding field. First item is System(cp936) of change menu, however, have an item Chinese Simplified (GB2312). They are equivalent in my first impression of two items.

I created a new repository then submit 3 commits with difference i18n.commitEncoding to test they. Both of they commit messages are four words Chinese, and i18n.commitEncoding followed by default, gb2312, cp936. (pushed to https://github.com/Aimeast/TestForFirst/commits/i18n)

  • git.exe can display the second commit
  • Git GUI can display the first and third commits
  • GitHub can display the first and second commits, third commit displayed as Japanese
  • LibGit2Sharp can display the first and second commits (third commit not same with Github)

OK, the result real funny. I decompress objects files for digging.

  • The first and second commits (e2266b and 38a2b0) were stored as utf-8
  • The third commit (bd9f62) was stored as gb2312

After my analysis, git.exe can identify format start with cp and followed by code page number. So, we can explain why there is such result.

Now, let's into the issue. The code

        // NativeMethods.git_commit_message
        [DllImport(libgit2)]
        [return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(Utf8NoCleanupMarshaler))]
        internal static extern string git_commit_message(GitObjectSafeHandle commit);

It's always marshal as Utf-8 result in third commit message was messy code. So, I suggest that return raw data then decode string in Proxy.git_commit_message. But, the evil is .Net Framework not support some encoding which supported by git.exe.

Hereafter is my code for detect the encoding for a commit

        public static Encoding CpAsEncoding(this Commit commit)
        {
            try
            {
                var encoding = commit.Encoding;

                if (encoding.StartsWith("cp", StringComparison.OrdinalIgnoreCase))
                    return Encoding.GetEncoding(int.Parse(encoding.Substring(2)));

                return Encoding.GetEncoding(encoding);
            }
            catch
            {
                return Encoding.UTF8;
            }
        }

Not perfect codes, but It's working.

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

從 NativeMethods.git_commit_message 和 Proxy.git_commit_message 開始,接著檢查 Commit.Encoding 的公開方式,以及 Utf8NoCleanupMarshaler 如何處理 native 結果。使用 default、gb2312 和 cp936 編碼與三個範例 commit 比較行為;當 Git 宣告了受支援的程式碼頁編碼時,commit 訊息能夠正確解碼,即表示完成。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
csharp, git
領域
devtools
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。