diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-02-05 21:18:18 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2020-02-06 13:51:59 +0300 |
commit | 754099b7218056a24d77aea0278bb3bc2c7a9716 (patch) | |
tree | 56ae541e000ebbb713a60e15465ce44eac01c274 | |
parent | 9ecee2a02b69c867962688f859cea4c8a7c28796 (diff) |
Add pre-commit-copyright-check git hook
-rw-r--r-- | cheatsheet.txt | 8 | ||||
-rwxr-xr-x | hooks/pre-commit | 26 | ||||
-rwxr-xr-x | hooks/pre-commit-copyright-check | 70 |
3 files changed, 104 insertions, 0 deletions
diff --git a/cheatsheet.txt b/cheatsheet.txt index 42efbcd..8e18dd1 100644 --- a/cheatsheet.txt +++ b/cheatsheet.txt @@ -14,6 +14,14 @@ Global Setup git config --global remote.origin.fetch '+refs/tags/*:refs/tags/*' git config --global --unset remote.origin.tagopt + # Enable hooks globally. + # + git config --global core.hooksPath <git-project-dir>/hooks + + # Override the global hooks with the repository-specific hooks (run in a + # repository directory). + # + git config core.hooksPath .git/hooks Undo (move to index) last commit diff --git a/hooks/pre-commit b/hooks/pre-commit new file mode 100755 index 0000000..10a97d9 --- /dev/null +++ b/hooks/pre-commit @@ -0,0 +1,26 @@ +#! /usr/bin/env bash + +# Execute various pre-commit scripts in a git repository. +# +# To enable the hooks globally run: +# +# $ git config --global core.hooksPath <git-project-dir>/hooks +# +# Notes: +# +# - git passes no parameters to this kind of hooks. +# +# - git changes CWD to the git repository root directory for the hook process. +# +# - git command running from inside the hook sees files that should be +# auto-staged due to the -a git-commit option or similar as already staged. +# +trap 'exit 1' ERR + +src_exe="$(realpath "${BASH_SOURCE[0]}")" +src_dir="$(dirname "$src_exe")" + +# Run each hook checking the exit status and bailing out if unsuccessful. We +# can just exec the last one. +# +exec "$src_dir/pre-commit-copyright-check" diff --git a/hooks/pre-commit-copyright-check b/hooks/pre-commit-copyright-check new file mode 100755 index 0000000..1bdeffd --- /dev/null +++ b/hooks/pre-commit-copyright-check @@ -0,0 +1,70 @@ +#! /usr/bin/env bash + +# Check copyright notices in the COPYRIGHT and LICENSE files and issue a +# warning if they don't include the current year. +# +# Specifically, look first for COPYRIGHT and then LICENSE in the root +# directory and all subdirectories in a project. +# +# Then in each file look for the first line matching the: +# +# ^Copyright (\([cC]\))? ... +# +# Regex, where "..." matches various year lists/ranges (e.g., "2010", "2010, +# 2011", "2010-2011", and their combinations; see the pattern below for +# details). Specifically, we don't consider Copyright notices that: +# +# - don't start at the very beginning of a line (indented, etc) +# - contain something other than years prior to the last year (names, etc) +# - wrap over multiple lines (long year list, etc) +# +# Note also that the current year is obtained in the UTC timezone. +# +trap 'exit 1' ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +# Recursively collect the COPYRIGHT and LICENSE files, skipping the LICENSE +# files in directories that contain the COPYRIGHT file. +# +# @@ Note that for now we assume that there are no spaces in the project file +# and directory names. +# +files=() + +fs=($(find . \( -type f -o -type l \) -name COPYRIGHT)) + +for f in "${fs[@]}"; do + files+=("$f") +done + +fs=($(find . \( -type f -o -type l \) -name LICENSE)) + +for f in "${fs[@]}"; do + d="$(dirname "$f")" + + if [ ! -f "$d/COPYRIGHT" ]; then + files+=("$f") + fi +done + +# Grep for the Copyright notice in the collected files and issue the warning +# if it is present and is outdated. +# +# @@ We should probably skip the COPYRIGHT/LICENSE files whose parent +# directories don't (recursively) contain staged files (think of projects +# with multiple packages, bundled third-party code, etc). Note that we can +# obtain the staged file list with the `git diff --name-only --cached` +# command. +# +current_year="$(date -u +'%Y')" + +for f in "${files[@]}"; do + year="$(sed -n -re 's%^Copyright( +\([cC]\))?[ 0-9,-]*[ ,-]([0-9]{4}).*$%\2%p' "$f" | head -n 1)" + + if [ -n "$year" -a "$year" != "$current_year" ]; then + info "WARNING: last copyright year in '${f#./}' is $year" + fi +done |