]>
Lady’s Gitweb - HOMEDIR/blob - sh/githooks/pre-commit.sh
2 # @(#)🏠📂 HOMEDIR sh/githooks/pre-commit.sh 2026-03-22T02:03:39Z
3 # SPDX-FileCopyrightText: 2026 Lady <https://www.ladys.computer/about/#lady>
4 # SPDX-License-Identifier: MPL-2.0
8 ## ∎ Copyright © 2026 Lady [@ Ladys Computer].
10 ## ⋮ This Source Code Form is subject to the terms of the Mozilla
11 ## Public License, version 2.0.
12 ## If a copy of the M·P·L was not distributed with this file, You can
13 ## obtain one at {🔗<https://mozilla.org/MPL/2.0/>}.
17 ## This script performs actions on files prior to a Git commit being
19 ## It is intended to be used as a precommit hook in a Git repository.
21 ## ❦ “What” signature updates
23 ## This script checks the first 24 lines of each file that is currently
24 ## staged in the index (i·e which will be committed) for the string
26 ## It takes this, and all following characters up to the next newline
27 ## or tab (which are assumed to be a product name), and deletes
28 ## everything which follows on that line.
29 ## Then it appends to the line the following items, each preceded by a
32 ## • The path to the file, relative to the repository root.
34 ## • The current date and time.
36 ## This operation is applied both on the version of the file staged in
37 ## the index and on the one in the working tree.
39 ## The result of this change is that calling What (a Posix development
40 ## utility) on the file will provide the associated project name,
41 ## path, and datetime (of last commit) for the file.
42 ## This is useful in situations where more sophisticated versioning
43 ## identification (e·g `git describe´) is not available.
45 ## If a file does not contain the sequence `@({U+23})´ in its first 24
46 ## lines, no changes are made.
50 ## The following variables provide hooks to override the commands used
57 : "${cmd_PRINTF:=printf}"
62 : "${cmd_XARGS:=xargs}"
66 ## `IFS´ is made null to prevent line splitting and `LC_ALL´ is set to
67 ## the Posix (C) locale.
72 ## The `now´ variable simply holds the current datetime.
75 TZ=UTC0 "${cmd_DATE}" -u '+%Y-%m-%dT%H:%M:%SZ'
78 ## The `modified´ variable provides a list of changed text files.
79 ## The `--diff-filter´ excludes deleted files and the `--eol´ check is
80 ## used to exclude binary files.
83 "${cmd_GIT}" diff -z \
84 --cached --name-only --no-renames \
86 "${cmd_XARGS}" -0 "${cmd_GIT}" ls-files --eol -- |
87 "${cmd_SED}" '/^i[/]-text/d;s/^.* //'
90 ## If no files were modified, do nothing.
92 if "${cmd_TEST}" -z "${modified}"
97 ## The `makepatch´ function provides the main implementation.
98 ## It takes a blob of text (`blob´) and prints a diff that Git can
99 ## apply which makes the necessary changes.
100 ## If no changes are necessary, it returns an empty string.
104 ## The `whatline´ variable holds the line number of the `@({U+23})´
105 ## string within the blob.
106 ## This function prints nothing unless `whatline´ holds a value.
109 "${cmd_PRINTF}" '%s\n' "${blob}" |
110 "${cmd_GREP}" -n '@([#])' |
112 "${cmd_SED}" 's/^\([^:]*\):.*$/\1/'
115 ## Up to five lines following the line indicated by `whatline´ are
116 ## included as context in the resulting diff.
118 if "${cmd_TEST}" -n "${whatline}"
121 "${cmd_PRINTF}" '%s\n' "${blob}" |
122 "${cmd_HEAD}" -n $((${whatline} + 5))
126 ## First, the diff includes lines up to `whatline´ with no
127 ## modifications, and deletes the `whatline´ line as it currently
130 "${cmd_PRINTF}" '%s\n' "${context}" |
132 -e $((${whatline} + 1))',$d' \
133 -e "${whatline}"'!s/^/ /' \
134 -e "${whatline}"'s/^/-/'
136 ## An updated version of the `whatline´ line is then inserted.
139 "${cmd_PRINTF}" '%s\n' "${context}" |
141 -e "${whatline}"'!d' \
142 -e "${whatline}"'s/\(@([#])[^ ]*\)\( .*\)*/\1/' \
145 "${cmd_PRINTF}" '\t%s' "${file}" "${now}"
146 "${cmd_PRINTF}" '%s\n' ''
148 "${cmd_SED}" 's/ *$//'
150 ## Finally, lines whose indices follow `whatline´ are included with·out
153 "${cmd_PRINTF}" '%s\n' "${context}" |
155 -e '1,'"${whatline}"'d' \
159 ## The number of lines in the resulting diff cannot be assumed and
161 ## The diff always starts at index 1 and has a context length 1 less
162 ## than its number of lines (because the deletion and addition affect
163 ## the same line of content).
166 "${cmd_PRINTF}" '%s\n' "${diff}" |
169 diffend
=$((${difflen} - 1))
171 ## The diff is printed in a rough `diff --git´ format.
173 "${cmd_PRINTF}" '%s\n' \
174 'diff --git "a/'"${file}"'" "b/'"${file}"'"' \
175 '--- "a/'"${file}"'"' \
176 '+++ "b/'"${file}"'"' \
177 '@@ -1,'"${diffend}"' +1,'"${diffend}"' @@' \
182 ## Staged files are read and the diffs are applied to them when
184 ## Files in the working directory are only updated after changes to the
187 "${cmd_PRINTF}" '%s\n' "${modified}" |
191 "${cmd_GIT}" cat-file blob ':'"${file}" |
195 blob="${indexblob}" makepatch
197 if "${cmd_TEST}" -n "${indexpatch}"
199 "${cmd_PRINTF}" '%s\n' "${indexpatch}" |
200 "${cmd_GIT}" apply
--cached
202 "${cmd_HEAD}" -n 24 -- "${file}"
205 blob="${workingblob}" makepatch
207 if "${cmd_TEST}" -n "${workingpatch}"
209 "${cmd_PRINTF}" '%s\n' "${workingpatch}" |
This page took 0.16054 seconds and 5 git commands to generate.