代码之家  ›  专栏  ›  技术社区  ›  bairog

GIT pre-commit钩子,它在修改/添加的文件中搜索非UTF-8编码(如果发现任何非UTF-8编码,则拒绝提交)

  •  0
  • bairog  · 技术社区  · 7 年前

    我正在使用Git for Windows(和TortoiseGit)。

    我的目标是防止提交中至少有一个非UTF-8文件被修改/添加。

    • 枚举修改/添加的文件: 我找到了以下代码

      { git diff --name-only ; git diff --name-only --staged ; }
      

      这是最好的(正确和最简洁的)方法吗?

    • 搜索非UTF-8文件:

      { git diff --name-only ; git diff --name-only --staged ; } | xargs -I {} bash -c "iconv -f utf-8 -t utf-16 {} &>/dev/null || echo {} - is non-UTF8!"
      

      如果我在我的存储库根文件夹中启动gitbash,它就会工作(每个非UTF-8文件都会显示出来)。所以我重新命名了 .git/hooks/pre-commit.sample .git/hooks/pre-commit 复制并粘贴上面的代码。提交更改后,在tortoisegitcommitgui窗口中不会显示任何特殊内容。所以看起来预提交挂钩工作不正常。

    • 如果存在任何非UTF-8文件,则拒绝提交: 显示所有非UTP-8文件后,应拒绝提交。但我不知道如何做到这一点(显示一些退出代码-但如何?)。

    所以任何帮助都是非常感谢的。

    0 回复  |  直到 7 年前
        1
  •  4
  •   bairog    7 年前

    所以答案是(thx to) phd 很高兴见到你 torek

        git diff --name-only --staged --diff-filter d | xargs -I {} bash -c 
     "iconv -f utf-8 -t utf-16 {} &>/dev/null || { echo {} - is non-UTF8!; exit 1; }"
    

    这段代码遍历在commit中更改的所有文件(除了deleted-即添加、修改、复制和重命名),并检查是否有任何非UTF8文件。将列出找到的所有文件并中止提交。

        2
  •  2
  •   torek    7 年前

    您现有的解决方案可能已经足够了。但这并不是100%正确:以下是剩余的问题,所有这些都是次要的问题,您可以稍后(如果有)在空闲时解决:

    • 你只需要 git diff ... --staged --cached ),因为Git将提交索引/暂存区域中的任何文件,以及 git diff HEAD 承诺并告诉你那里有什么不同。如果索引中的文件副本与中的文件副本不同 ,您应该检查索引副本。

    • 从技术上讲,使用 git diff-index --cached 这样就不会遵守任何用户的要求 差异比较 配置。也就是说, git diff-index 是一个 管道工程 git config 设置。但如果你是为了自己而做 以至于它打破了你自己的习惯 差异比较

    • 您也可以考虑使用 --diff-filter iconv

    • 最重要的: iconv公司 工作树 分阶段 ,而不是工作树中的内容。

    $ git checkout master
    $ printf '\300\300\300' > badfile    # put bad non-UTF-8 crud into file
    $ git add badfile                    # copy file into index
    $ echo 'good data' > badfile         # replace work-tree contents
    $ git commit
    

    犯罪 \300 索引中没有换行符,但预提交挂钩将运行 iconv -f utf-8 -t utf-16 在书的内容上 好的 文件,读取 good data ,那当然好。

    要解决这个问题,您的预提交过滤器必须提取数据 从索引中 对于要提交的每个文件。你该怎么做取决于你自己。最简单(但可能最慢)的方法是使用 git checkout-index . 更好的方法可能是将每个索引(在临时区域中)路径名转换为有效的索引说明符(即, path/to/file 变成 :path/to/file )使用 git cat-file -p $specifier | iconv ... 扫描每个。但所有这些都将相当低效,尤其是在Windows上。为了提高效率,您可能需要编写一个使用 git cat-file --batch 在一个过程中提取它们,并在那里进行格式检查。

    推荐文章