KDE sources and custom Git commit hooks

Wait 5 sec.

KDE’s Gitlab setup has a branch naming rule that I always forgetabout – branch names should start with work/ if you wantthe server to allow you to rebase and push rebased commits (that is,only work branches can be --force pushedto).I had to abandon and open new PRs a few times now because ofthis.Something like this is easy to check on the client side withpre-commit hooks. (a pre-push hook can also beused, but I like the check to be as early as possible)A simple hook script that checks your branch name starts withwork/YOUR_USER_NAME (I like to have the username in thebranch name) is rather simple to write:#!/bin/bashREPO_URL=$(git remote get-url origin)KDE_REPO_HOST="invent.kde.org"if [[ "${REPO_URL}" == *"${KDE_REPO_HOST}"* ]]; then BRANCH=$(git rev-parse --abbrev-ref HEAD) BRANCH_REGEX="^work/$USER/.*$" if ! [[ $BRANCH =~ $BRANCH_REGEX ]]; then echo "Your commit was rejected due to its name '$BRANCH', should start with 'work/$USER'" exit 1 fifiIt checks that the Git repository is on invent.kde.org,and if it is, it checks if the current branch follows the desired namingscheme.KDEGitCommitHooksBut the question is where to put this script?Saving it as .git/hooks/pre-commit in the cloned sourcedirectory would work in general, but there are two problems:Manually putting it into every single cloned KDE source directory onyour system would be a pain;KDEGitCommitHooks, which is used by many KDE projects,will overwrite the custom pre-commit hook script youdefine.The second issue is not a problem since a few hours ago.KDEGitCommitHooks (a part of theextra-cmake-modules framework) now generates apre-commit hook that, additionally to what it used to dobefore, executes all the custom scripts you place in the.git/hooks/pre-commit.d/ directory.So, if a project uses KDEGitCommitHooks you can save theaforementioned script as.git/hooks/pre-commit.d/kde-branches-should-start-with-work.shand it should be automatically executed any time you create a new commit(after KDEGitCommitHooks updates the mainpre-commit hook in your project).For projects that do not use KDEGitCommitHooks, you willneed to add a pre-commit hook that executes scripts inpre-commit.d, but more on that in a moment.Git templatesThe first problem remains – putting this into a few hundred localsource directories is a pain and error-prone.Fortunately, Git allows creating a template directory structure whichwill be reproduced for any repository you init orclone.I placed my template files into ~/.git_templates_globaland added these two lines to ~/.gitconfig:[init] templatedir = ~/.git_templates_globalI have two KDE-related hook scripts there.The above one is saved as~/.git_templates_global/hooks/pre-commit.d/kde-branches-should-start-with-work.And the second file is the default mainpre-commit(~/.git_templates_global/hooks/pre-commit) script:#!/usr/bin/env bash# If the user has custom commit hooks defined in pre-commit.d directory,# execute themPRE_COMMIT_D_DIR="$(dirname "$0")/pre-commit.d/"if [ -d "$PRE_COMMIT_D_DIR" ]; then for PRE_COMMIT_D_HOOK in "$PRE_COMMIT_D_DIR"/*; do ./"$PRE_COMMIT_D_HOOK" RESULT=$? if [ $RESULT != 0 ]; then echo "$PRE_COMMIT_D_HOOK returned non-zero: $RESULT, commit aborted" exit $RESULT fi donefiexit 0It tries to run all the scripts in pre-commit.d andreports if any of them fail.This default main pre-commit script will beused in projects that do not use KDEGitCommitHooks. In theprojects that do, KDEGitCommitHooks will replace it with ascript that executes everything in pre-commit.d same asthis one does, but with a few extra steps.