Improve pre-commit git_hook.

git_hooks/update_copyright.pre-commit:
    Document the operation of this script in more detail.

    Document the use of the new Makefile, and of the new environment
    variable that can be used to avoid redundant copies of the update_copyright
    program's executable.

git_hooks/Makefile:
    Add a trivial makefile to shorten the build and clean commands.

git_hooks/update_copyright.m:
    Merge contiguous year ranges in copyright lines.
This commit is contained in:
Zoltan Somogyi
2024-03-13 16:50:00 +11:00
parent 4ce9d505a8
commit ae701f4200
3 changed files with 80 additions and 21 deletions

16
git_hooks/Makefile Normal file
View File

@@ -0,0 +1,16 @@
#---------------------------------------------------------------------------#
# vim: ts=8 sw=8 noexpandtab
#---------------------------------------------------------------------------#
#
# A makefile for the update_copyright program.
#
# This Makefile is designed for manual operation by Mercury developers;
# it is *not* designed to be invoked by any action in any other Makefile
# or Mmakefile, in any other part of that workspace.
#
update_copyright: update_copyright.m
mmc --mercury-linkage static update_copyright.m
clean:
git clean -fx 'update_copyright.*' 'update_copyright_init.*'

View File

@@ -208,9 +208,9 @@ read_lines_loop(InputStream, Options, CurrentYear,
!.ModState = unmodified,
parse_copyright_line(Options, Line, Prefix, Ranges0, Suffix)
then
% We could normalise ranges here.
sort(Ranges0, Ranges1),
( if add_to_ranges(CurrentYear, Ranges1, Ranges) then
list.sort(Ranges0, Ranges1),
merge_adjacent_ranges_if_possible(Ranges1, Ranges2),
( if add_to_ranges(CurrentYear, Ranges2, Ranges) then
make_copyright_line(Prefix, Ranges, Suffix, NewLine),
!:RevLines = [NewLine | !.RevLines],
!:ModState = found_modified
@@ -289,6 +289,13 @@ parse_ranges(Str, Ranges) :-
Words = string.words_separator(is_whitespace_or_comma, Str),
list.map(parse_range, Words, Ranges).
:- pred is_whitespace_or_comma(char::in) is semidet.
is_whitespace_or_comma(C) :-
( char.is_whitespace(C)
; C = (',')
).
:- pred parse_range(string::in, year_range::out) is semidet.
parse_range(Str, Range) :-
@@ -305,11 +312,27 @@ parse_range(Str, Range) :-
Range = years(N1, N2)
).
:- pred is_whitespace_or_comma(char::in) is semidet.
:- pred merge_adjacent_ranges_if_possible(
list(year_range)::in, list(year_range)::out) is det.
is_whitespace_or_comma(C) :-
( char.is_whitespace(C)
; C = (',')
merge_adjacent_ranges_if_possible(Ranges0, Ranges) :-
(
( Ranges0 = []
; Ranges0 = [_]
),
Ranges = Ranges0
;
Ranges0 = [Range1, Range2 | Ranges3plus],
Range1 = years(RangeLo1, RangeHi1),
Range2 = years(RangeLo2, RangeHi2),
( if RangeLo2 =< RangeHi1 + 1 then
Range12 = years(RangeLo1, RangeHi2),
merge_adjacent_ranges_if_possible([Range12 | Ranges3plus], Ranges)
else
merge_adjacent_ranges_if_possible([Range2 | Ranges3plus],
TailRanges),
Ranges = [Range1 | TailRanges]
)
).
:- pred add_to_ranges(int::in, list(year_range)::in, list(year_range)::out)

View File

@@ -1,26 +1,46 @@
#!/usr/bin/env bash
#
# You can copy/symlink this script to .git/hooks/pre-commit.
# It will update the Copyright lines of all files that are going to be
# modified in the commit, before the commit is made.
# This script is designed to update the Copyright lines of all files
# that are going to be modified in the commit in a workspace,
# before the commit is made.
#
# You need to compile the update_copyright.m program:
# mmc --mercury-linkage static update_copyright.m
# If ${ws} is the pathname of a workspace, then you enable this script
# for that workspace by
#
# You can clean the intermediate files with:
# git clean -fx 'update_copyright.*' 'update_copyright_init.*'
# - compiling update_copyright.m to an executable, and
# - copying or symlinking this script to ${ws}/.git/hooks/pre-commit.
#
# The first step can be done by the command
#
# make update_copyright
#
# The unneeded intermediate files from the first step can cleaned up
# by the command
#
# make clean
#
# By default, this script requires the executable git_hooks/update_copyright
# to be present in the workspace. You can avoid having a duplicate copy
# of that executable in every workspace by
#
# - putting that executable in some central location, and
# - setting the environment variable UPDATE_MERCURY_COPYRIGHT
# to invoke that executable.
#
set -e
rootdir=$( git rev-parse --show-toplevel )
update_copyright="$rootdir/git_hooks/update_copyright"
# Only continue if the update_copyright program has been compiled.
if test ! -x "$update_copyright"
if test "${UPDATE_MERCURY_COPYRIGHT}" != ""
then
exit
update_copyright="${UPDATE_MERCURY_COPYRIGHT}"
else
update_copyright="${rootdir}/git_hooks/update_copyright"
fi
# Continue only if the update_copyright program is available.
command -v "${update_copyright}" > /dev/null || exit 0
# Find changed files for this commit.
changed_files=($( git diff --name-only --cached --diff-filter=ACMR ))
update_files=()
@@ -28,7 +48,7 @@ unknown_files=()
for file in "${changed_files[@]}"
do
case $file in
case ${file} in
*.[mchly] | *.in | *.java | *Mmake*)
update_files+=( "$file" )
;;
@@ -47,5 +67,5 @@ fi
if test "${#update_files}" -gt 0
then
# Accept both "Mercury team" and "Mercury Team".
exec "$update_copyright" --suffix ' Mercury ' -- "${update_files[@]}"
exec "${update_copyright}" --suffix ' Mercury ' -- "${update_files[@]}"
fi