Home > Blockchain >  Git pre-commit hook that automatically grants execution permissions ( x) on all .sh files which are
Git pre-commit hook that automatically grants execution permissions ( x) on all .sh files which are

Time:09-21

I'm trying to solve the same exact same problem illustrated here:

How to commit executable shell scripts with Git on Windows

"If you develop software involving shell scripts on Windows, which should also run on UNIX, you have a problem.

Windows filesystems like NTFS do not support UNIX permission bits.

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. When you push the code, these scripts won’t run a UNIX-based machine."

The given precommit hook-script which is proposed as a solution to the aforementioned problem is written in 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?

CodePudding user response:

With a bash script hook:

#!/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:

#!/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
  • Related