commit 88629c9467855819378e15248d9b17f53c6d6d3f Author: femsci Date: Mon Apr 18 17:50:40 2022 +0200 Create base diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ecb332 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.vscode +**/.DS_Store +*.swp +*.*~ + +data/* +!data/.gitkeep +custom.d/*/* +!custom.d/*/.gitkeep diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8b47658 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 nya + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..468d57e --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# pinch + +*A pinch of Git ~~pinches~~ hooks* + +Pinch is a global Git hook manager. Its main use is to establish a modular hook system. + +## Requirements + +- A mostly POSIX-compatible OS +- Bash >= 5.0 +- Busybox, Coreutils or alternatives +- Git >= 2.9 + +## Installation + +To install pinch, clone this repository and execute **[install.sh](install.sh)**. If there is different global hook configuration, pinch will remember it. + +Similarly, in order to uninstall pinch, execute **[uninstall.sh](uninstall.sh)**. Previous configuration (if there was any) will be restored. + +## Debug mode + +In order to enable debug messages, set `PINCH_DEBUG` to `1` as an environment variable before invoking Git hooks. + +## License + +pinch is a free and open-source program distributed under the terms of the [MIT license](https://opensource.org/licenses/MIT). diff --git a/custom.d/README b/custom.d/README new file mode 100644 index 0000000..784c5cc --- /dev/null +++ b/custom.d/README @@ -0,0 +1,4 @@ +This directory (custom.d) is dedicated to custom hooks. +In order to add a custom hook, insert the file to a subdirectory bearing the respective category. +All hidden files (starting with a dot) and files not marked as executable are ignored. +The contents of the subdirectories (except for .gitkeep) are not tracked and will be preserved during project updates. diff --git a/custom.d/applypatch-msg/.gitkeep b/custom.d/applypatch-msg/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/commit-msg/.gitkeep b/custom.d/commit-msg/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-applypatch/.gitkeep b/custom.d/post-applypatch/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-checkout/.gitkeep b/custom.d/post-checkout/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-commit/.gitkeep b/custom.d/post-commit/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-merge/.gitkeep b/custom.d/post-merge/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-receive/.gitkeep b/custom.d/post-receive/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-rewrite/.gitkeep b/custom.d/post-rewrite/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/post-update/.gitkeep b/custom.d/post-update/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-applypatch/.gitkeep b/custom.d/pre-applypatch/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-auto-gc/.gitkeep b/custom.d/pre-auto-gc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-commit/.gitkeep b/custom.d/pre-commit/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-push/.gitkeep b/custom.d/pre-push/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-rebase/.gitkeep b/custom.d/pre-rebase/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/pre-receive/.gitkeep b/custom.d/pre-receive/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/prepare-commit-msg/.gitkeep b/custom.d/prepare-commit-msg/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/custom.d/update/.gitkeep b/custom.d/update/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/.gitkeep b/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/_init.sh b/hooks/_init.sh new file mode 100755 index 0000000..1e773d0 --- /dev/null +++ b/hooks/_init.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +HOOK_ARGS=$@ +HOOK_PATH=$(realpath $0) +HOOK_PATH=${HOOK_PATH%/*} + +export HOOK_PATH + +err_trap() { + echo "Error: $BASH_COMMAND" +} + +if [[ $PINCH_DEBUG -eq 1 ]]; then + pdebug() { + echo -e "\033[33m(DEBUG)\033[0m $@" + } +else + pdebug() { + : + } +fi + +pinfo() { + echo -e "\033[32m=>\033[0m $@" +} + +export -f pdebug +export -f err_trap + +trap err_trap ERR + +exec_custom() { + local hooks_path=$HOOK_PATH/../custom.d/$1 + + for hook in $(ls $hooks_path); do + if [ -x $hooks_path/$hook ]; then + pdebug "Executing custom hook $hooks_path/$hook" + $hooks_path/$hook $HOOK_ARGS + fi + done +} + +exec_all() { + for file in $(ls $1 | sort); do + if [ -x $1/$file ]; then + pdebug "Executing hook $1/$file" + $1/$file $HOOK_ARGS + fi + done +} + +pdebug "Hook type: $(basename $0)" diff --git a/hooks/applypatch-msg b/hooks/applypatch-msg new file mode 100755 index 0000000..815785c --- /dev/null +++ b/hooks/applypatch-msg @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/applypatch-msg.d +exec_custom applypatch-msg + diff --git a/hooks/applypatch-msg.d/.gitkeep b/hooks/applypatch-msg.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/commit-msg b/hooks/commit-msg new file mode 100755 index 0000000..da82030 --- /dev/null +++ b/hooks/commit-msg @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/commit-msg.d +exec_custom commit-msg + diff --git a/hooks/commit-msg.d/.gitkeep b/hooks/commit-msg.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-applypatch b/hooks/post-applypatch new file mode 100755 index 0000000..9970778 --- /dev/null +++ b/hooks/post-applypatch @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-applypatch.d +exec_custom post-applypatch + diff --git a/hooks/post-applypatch.d/.gitkeep b/hooks/post-applypatch.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-checkout b/hooks/post-checkout new file mode 100755 index 0000000..659d6a8 --- /dev/null +++ b/hooks/post-checkout @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-checkout.d +exec_custom post-checkout + diff --git a/hooks/post-checkout.d/.gitkeep b/hooks/post-checkout.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-commit b/hooks/post-commit new file mode 100755 index 0000000..42d7224 --- /dev/null +++ b/hooks/post-commit @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-commit.d +exec_custom post-commit + diff --git a/hooks/post-commit.d/.gitkeep b/hooks/post-commit.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-merge b/hooks/post-merge new file mode 100755 index 0000000..df5f8a1 --- /dev/null +++ b/hooks/post-merge @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-merge.d +exec_custom post-merge + diff --git a/hooks/post-merge.d/.gitkeep b/hooks/post-merge.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-receive b/hooks/post-receive new file mode 100755 index 0000000..c837f9a --- /dev/null +++ b/hooks/post-receive @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-receive.d +exec_custom post-receive + diff --git a/hooks/post-receive.d/.gitkeep b/hooks/post-receive.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-rewrite b/hooks/post-rewrite new file mode 100755 index 0000000..c9dbe8d --- /dev/null +++ b/hooks/post-rewrite @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-rewrite.d +exec_custom post-rewrite + diff --git a/hooks/post-rewrite.d/.gitkeep b/hooks/post-rewrite.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/post-update b/hooks/post-update new file mode 100755 index 0000000..107d7d0 --- /dev/null +++ b/hooks/post-update @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/post-update.d +exec_custom post-update + diff --git a/hooks/post-update.d/.gitkeep b/hooks/post-update.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-applypatch b/hooks/pre-applypatch new file mode 100755 index 0000000..aa92e40 --- /dev/null +++ b/hooks/pre-applypatch @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-applypatch.d +exec_custom pre-applypatch + diff --git a/hooks/pre-applypatch.d/.gitkeep b/hooks/pre-applypatch.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-auto-gc b/hooks/pre-auto-gc new file mode 100755 index 0000000..f7e800c --- /dev/null +++ b/hooks/pre-auto-gc @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-auto-gc.d +exec_custom pre-auto-gc + diff --git a/hooks/pre-auto-gc.d/.gitkeep b/hooks/pre-auto-gc.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-commit b/hooks/pre-commit new file mode 100755 index 0000000..3dc5430 --- /dev/null +++ b/hooks/pre-commit @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-commit.d +exec_custom pre-commit + diff --git a/hooks/pre-commit.d/.gitkeep b/hooks/pre-commit.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-push b/hooks/pre-push new file mode 100755 index 0000000..7a52c28 --- /dev/null +++ b/hooks/pre-push @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-push.d +exec_custom pre-push + diff --git a/hooks/pre-push.d/.gitkeep b/hooks/pre-push.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-rebase b/hooks/pre-rebase new file mode 100755 index 0000000..99971ab --- /dev/null +++ b/hooks/pre-rebase @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-rebase.d +exec_custom pre-rebase + diff --git a/hooks/pre-rebase.d/.gitkeep b/hooks/pre-rebase.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/pre-receive b/hooks/pre-receive new file mode 100755 index 0000000..512e2f9 --- /dev/null +++ b/hooks/pre-receive @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/pre-receive.d +exec_custom pre-receive + diff --git a/hooks/pre-receive.d/.gitkeep b/hooks/pre-receive.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/prepare-commit-msg b/hooks/prepare-commit-msg new file mode 100755 index 0000000..1c69ad0 --- /dev/null +++ b/hooks/prepare-commit-msg @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/prepare-commit-msg.d +exec_custom prepare-commit-msg + diff --git a/hooks/prepare-commit-msg.d/.gitkeep b/hooks/prepare-commit-msg.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hooks/update b/hooks/update new file mode 100755 index 0000000..368d006 --- /dev/null +++ b/hooks/update @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +. "${0%/*}/_init.sh" + +exec_all $HOOK_PATH/update.d +exec_custom update + diff --git a/hooks/update.d/.gitkeep b/hooks/update.d/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..345098c --- /dev/null +++ b/install.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +current_path=$(realpath $0) +hook_base=${current_path%/*} + +if [[ -e $hook_base/data/install ]]; then + echo "Pinch already installed" >&2 + exit 1 +fi + +old_cfg=$(git config --global --get core.hooksPath) +hooks_path=$hook_base/hooks + +if [ ! $? -eq 0 ]; then + echo $old_cfg >$hook_base/data/old_cfg +fi + +git config --global core.hooksPath $hooks_path + +echo $(date +%s) >$hook_base/data/install + +echo "Pinch installed." diff --git a/tools/populate.sh b/tools/populate.sh new file mode 100755 index 0000000..dbe4ab9 --- /dev/null +++ b/tools/populate.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# +# This script is used to populate hook directories +# Use flag -c to clean the hook directories +# If hook files are already present, they will be overwritten +# + +# Add or remove in order to generate different hooks +# For available hooks, see githooks(5) +hooktypes="applypatch-msg \ +pre-applypatch \ +post-applypatch \ +pre-commit \ +prepare-commit-msg \ +commit-msg \ +post-commit \ +pre-rebase \ +post-checkout \ +post-merge \ +pre-receive \ +update \ +post-receive \ +post-update \ +pre-auto-gc \ +post-rewrite \ +pre-push" + +path=$(realpath $0) +path=${path%/*}/.. + +# Clean the hook directories if -c flag is present +if [[ $1 == "-c" ]]; then + find $path/hooks -mindepth 1 -maxdepth 1 -not -name "_init.sh" -exec rm -r {} + + find $path/custom.d -mindepth 1 -maxdepth 1 -not -name "README" -exec rm -r {} + +else + populate_hook() { + echo "#!/usr/bin/env bash +. \"\${0%/*}/_init.sh\" + +exec_all \$HOOK_PATH/$1.d +exec_custom $1 +" >$path/hooks/$1 + chmod +x $path/hooks/$1 + } + + for hooktype in $hooktypes; do + mkdir -p $path/custom.d/$hooktype + touch $path/custom.d/$hooktype/.gitkeep + + mkdir -p $path/hooks/$hooktype.d + touch $path/hooks/$hooktype.d/.gitkeep + populate_hook $hooktype + done +fi diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000..2d2542c --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +current_path=$(realpath $0) +hook_base=${current_path%/*} + +if [[ ! -e $hook_base/data/install ]]; then + echo "Pinch not installed. Consider installing pinch using install.sh..." >&2 + exit 1 +fi + +if [[ -r $hook_base/data/old_cfg ]]; then + old_cfg=$(cat $hook_base/data/old_cfg) + git config --global core.hooksPath $old_cfg + rm $hook_base/data/old_cfg +else + git config --global --unset core.hooksPath +fi + +rm $hook_base/data/install + +echo "Pinch uninstalled..."