简体   繁体   English

Git 预提交挂钩,自动授予正在提交的 all.sh 文件的执行权限 (+x)

[英]Git pre-commit hook that automatically grants execution permissions (+x) on all .sh files which are being committed

I'm trying to solve the same exact same problem illustrated here:我正在尝试解决此处说明的完全相同的问题:

How to commit executable shell scripts with Git on Windows 如何在 Windows 上使用 Git 提交可执行的 shell 脚本

"If you develop software involving shell scripts on Windows, which should also run on UNIX, you have a problem. “如果你在 Windows 上开发涉及 shell 脚本的软件,它也应该在 UNIX 上运行,你就有问题了。

Windows filesystems like NTFS do not support UNIX permission bits. Windows NTFS 等文件系统不支持 UNIX 权限位。

Whenever you create new shell scripts on Windows, or rename existing ones (which may have been executable at the time of check-out), these won't be executable.每当您在 Windows 上创建新的 shell 脚本,或重命名现有脚本(在签出时可能已经可执行)时,这些脚本将无法执行。 When you push the code, these scripts won't run a UNIX-based machine."当你推送代码时,这些脚本不会运行基于 UNIX 的机器。”

The given precommit hook-script which is proposed as a solution to the aforementioned problem is written in python. python 中提出了作为上述问题的解决方案的给定预提交钩子脚本。

#!/usr/bin/env python
import subprocess

if __name__ == '__main__':
    output = subprocess.check_output(["git", "ls-files", "-s", "--", "*.sh"], shell=True).decode("utf-8")  # type: str
    files_to_fix = []
    for line in output.splitlines():
        # Example for "line": '100644 82f6a7d558e1b38c8b47ec5084fe20f970f09981 0 test-update.sh'
        entry = line.replace('\t', ' ').split(" ", maxsplit=3)
        mode = entry[0][3:]  # strips the first 3 chars ("100") which we don't care about
        filename = entry[3]
        if mode == "644":
            files_to_fix.append(filename)

    for file_path in files_to_fix:
        # git update-index --chmod=+x script.sh
        subprocess.check_call(["git", "update-index", "--chmod=+x", file_path], shell=True)

I'm not proficient in bash to rewrite it in bash. Is it possible to achieve this in bash at all?我不精通bash改写成bash,难道bash完全可以实现吗?

With a bash script hook:使用 bash 脚本挂钩:

#!/usr/bin/env bash

files_to_fix=()
while read -r -d '' mode _ _ file_path; do
  [[ $mode == *644 ]] && files_to_fix+=("$file_path")
done < <(git ls-files --stage -z '*.sh')
git update-index --chmod=+x -- "${files_to_fix[@]}"

Or with a POSIX shell:或者使用 POSIX shell:

#!/usr/bin/env sh

git ls-files --stage '*.sh' | while read -r mode _ _ file_path; do
  case $mode in
    *644) git update-index --chmod=+x -- "$file_path" ;;
    *) ;;
  esac
done

This one liner uses find to identify files that don't have the execute bit set instead of looking for permission 644 , so it works with unusual patterns like 640 or even 200 (write only:):这个衬里使用find来识别没有设置执行位的文件,而不是寻找权限644 ,因此它适用于不寻常的模式,如640甚至200 (只写:):

find . ! -perm -u+x -type f -name "*.sh" -exec git update-index --chmod=+x -- {} \;

Save it in .git/hooks/pre-commit (and make your hook executable!)将它保存在.git/hooks/pre-commit中(并使你的钩子可执行!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM