Mercurial Queues Emulation for Git
Revision | eb9c7b1ca12979d8aee379d4a646d55c48b4d89a (tree) |
---|---|
Time | 2019-06-02 07:49:56 |
Author | Keith Marshall <keith@user...> |
Commiter | Keith Marshall |
Disallow regular commit over applied patches.
* git-pre-commit.shar: New shell archive; it delivers...
* pre-commit: ...this generated git pre-commit hook script...
* git-pre-commit-setup.sh: ...this dynamic installer script, and...
* git-pre-commit-verify.sh: ...this setup validation script.
* git-mq-setup.sh: Add an "mq_require" call out to either...
[! -f $GIT_DIR/hooks/pre-commit] (git-pre-commit-setup): ...this...
[-f $GIT_DIR/hooks/pre-commit] (git-pre-commit-verify): ...or this.
* Makefile.in (install): Add dependency on...
(install-git-hooks): ...this new installation rule; it requires...
(pre-commit): ...this new target; define prerequisite build rule...
(all): ...also required here; add dependency reference.
(all, install-libexec-scripts): Add new dependencies on...
(git-pre-commit-setup.sh, git-pre-commit-verify.sh): ...these; add new
pattern rule to generate them.
(package_hooksdir): New macro; define it, and...
(installdirs): ...add it.
@@ -12,14 +12,14 @@ PACKAGE_VERSION := @PACKAGE_VERSION@ | ||
12 | 12 | # |
13 | 13 | # ------------------------------------------------------------------------------ |
14 | 14 | # |
15 | -# This file is part of the git-mq program suite. | |
15 | +# This file is part of the Git-MQ program suite. | |
16 | 16 | # |
17 | -# The git-mq program suite is free software: you can redistribute it | |
17 | +# The Git-MQ program suite is free software: you can redistribute it | |
18 | 18 | # and/or modify it under the terms of the GNU General Public Licence |
19 | 19 | # as published by the Free Software Foundation, either version 3 of |
20 | 20 | # the Licence, or (at your option) any later version. |
21 | 21 | # |
22 | -# The git-mq program suite is distributed in the hope that it will be | |
22 | +# The Git-MQ program suite is distributed in the hope that it will be | |
23 | 23 | # useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
24 | 24 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
25 | 25 | # GNU General Public Licence for more details. |
@@ -145,9 +145,10 @@ libexecdir := @libexecdir@ | ||
145 | 145 | |
146 | 146 | MKDIR_P := @MKDIR_P@ |
147 | 147 | package_libexecdir := ${libexecdir}/${PACKAGE_TARNAME}/${PACKAGE_VERSION} |
148 | +package_hooksdir = ${libexecdir}/${PACKAGE_TARNAME}/hooks | |
148 | 149 | |
149 | -installdirs: ${bindir} ${package_libexecdir} | |
150 | -${bindir} ${package_libexecdir}: | |
150 | +installdirs: ${bindir} ${package_hooksdir} ${package_libexecdir} | |
151 | +${bindir} ${package_hooksdir} ${package_libexecdir}: | |
151 | 152 | $(MKDIR_P) $@ |
152 | 153 | |
153 | 154 | INSTALL := @INSTALL@ |
@@ -174,6 +175,18 @@ install-libexec-scripts: mq-why-guarded.sh mq-push-reordered.sh | ||
174 | 175 | install-libexec-scripts: mq-setup.sh mq-tmpfile.sh mq-atexit.sh |
175 | 176 | @$(call INSTALL_SCRIPTS,$^,-m 644,${package_libexecdir}) |
176 | 177 | |
178 | +all install-libexec-scripts: git-pre-commit-setup.sh | |
179 | +all install-libexec-scripts: git-pre-commit-verify.sh | |
180 | +git-pre-commit-%.sh: git-pre-commit.shar | |
181 | + $(SHELL) $< $* > $@ | |
182 | + | |
183 | +all: pre-commit | |
184 | +pre-commit: git-pre-commit.shar | |
185 | + $(SHELL) $^ > $@ | |
186 | + | |
187 | +install: install-git-hooks | |
188 | +install-git-hooks: pre-commit | |
189 | + @$(call INSTALL_SCRIPTS,$^,-m 755,${package_hooksdir}) | |
177 | 190 | |
178 | 191 | # Distribution |
179 | 192 | # ============ |
@@ -1,9 +1,9 @@ | ||
1 | 1 | # git-mq-setup.sh |
2 | 2 | # ------------------------------------------------------------------------------ |
3 | 3 | # |
4 | -# Universal git-mq initialization hook. All git-mq command scripts should | |
4 | +# Universal Git-MQ initialization hook. All Git-MQ command scripts should | |
5 | 5 | # source this; it performs git specific initialization, before delegating to |
6 | -# the generic mingw-pkg mq plugin initialization code. | |
6 | +# the generic mingw-pkg MQ plugin initialization code. | |
7 | 7 | # |
8 | 8 | # ------------------------------------------------------------------------------ |
9 | 9 | # |
@@ -12,14 +12,14 @@ | ||
12 | 12 | # Written by Keith Marshall <keith@users.osdn.me> |
13 | 13 | # Copyright (C) 2018, Keith Marshall |
14 | 14 | # |
15 | -# This file is part of the git-mq program suite. | |
15 | +# This file is part of the Git-MQ program suite. | |
16 | 16 | # |
17 | -# The git-mq program suite is free software: you can redistribute it | |
17 | +# The Git-MQ program suite is free software: you can redistribute it | |
18 | 18 | # and/or modify it under the terms of the GNU General Public Licence |
19 | 19 | # as published by the Free Software Foundation, either version 3 of |
20 | 20 | # the Licence, or (at your option) any later version. |
21 | 21 | # |
22 | -# The git-mq program suite is distributed in the hope that it will be | |
22 | +# The Git-MQ program suite is distributed in the hope that it will be | |
23 | 23 | # useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
24 | 24 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
25 | 25 | # GNU General Public Licence for more details. |
@@ -43,7 +43,7 @@ | ||
43 | 43 | } |
44 | 44 | mq_patchdir=`git_mq_map_queue "$GIT_DIR/patches"` |
45 | 45 | |
46 | -# All git-mq commands should call the following function to process | |
46 | +# All Git-MQ commands should call the following function to process | |
47 | 47 | # command options, using a while loop, thus: |
48 | 48 | # |
49 | 49 | # while git_mq_getopt "$@" |
@@ -52,7 +52,7 @@ | ||
52 | 52 | # done |
53 | 53 | # |
54 | 54 | # Note: the command specific loop should interpret command specific |
55 | -# options; standard git-mq global options, such as "--colour", will | |
55 | +# options; standard Git-MQ global options, such as "--colour", will | |
56 | 56 | # be interpreted within this function itself. |
57 | 57 | # |
58 | 58 | git_mq_getopt(){ |
@@ -79,7 +79,7 @@ | ||
79 | 79 | case $1 in -*) mq_colour=always ;; *) mq_optarg=mq_colour ;; esac |
80 | 80 | } |
81 | 81 | |
82 | -# The following function may be used to wrap any git-mq action, so | |
82 | +# The following function may be used to wrap any Git-MQ action, so | |
83 | 83 | # that its default output will be in colour, and paged, when stdout |
84 | 84 | # is directed to a terminal device. |
85 | 85 | # |
@@ -101,10 +101,17 @@ | ||
101 | 101 | # |
102 | 102 | mq_collect(){ eval $1='${'$1'+"$'$1' "}"$2"'; } |
103 | 103 | |
104 | -# Delegate remaining initialization requirements to the generic (mingw-pkg) | |
104 | +# Delegate further initialization requirements to the generic (mingw-pkg) | |
105 | 105 | # mq-setup.sh plugin module. |
106 | 106 | # |
107 | 107 | mq_require "$libexecdir/mq-setup.sh" |
108 | + | |
109 | +# Finally, ensure that a git pre-commit hook is in place, to protect the | |
110 | +# integrity of the Git-MQ patch queue against the potentially destructive | |
111 | +# effect of an unmanaged commit over applied Git-MQ patches. | |
112 | +# | |
113 | + test -f "$GIT_DIR/hooks/pre-commit" && mq_require git-pre-commit-verify || | |
114 | + mq_require git-pre-commit-setup | |
108 | 115 | # |
109 | 116 | # ------------------------------------------------------------------------------ |
110 | 117 | # $RCSfile$: end of file |
@@ -0,0 +1,193 @@ | ||
1 | +# git-pre-commit.shar | |
2 | +# ------------------------------------------------------------------------------ | |
3 | +# | |
4 | +# Shell archive to deliver the git pre-commit hook, as required by Git-MQ, | |
5 | +# together with its dynamic installation and verification support scripts. | |
6 | +# | |
7 | +# ------------------------------------------------------------------------------ | |
8 | +# | |
9 | +# The following copyright notice is applicable to all deliverable scripts, | |
10 | +# which are compiled from this archive, and to the archive itself. | |
11 | +# | |
12 | +test ${1-x} = copyright && { cat <<\ETX; exit; } | |
13 | +# ------------------------------------------------------------------------------ | |
14 | +# | |
15 | +# $Id$ | |
16 | +# | |
17 | +# Written by Keith Marshall <keith@users.osdn.me> | |
18 | +# Copyright (C) 2019, Keith Marshall | |
19 | +# | |
20 | +# | |
21 | +# This file is part of the Git-MQ program suite. | |
22 | +# | |
23 | +# The Git-MQ program suite is free software: you can redistribute it | |
24 | +# and/or modify it under the terms of the GNU General Public Licence | |
25 | +# as published by the Free Software Foundation, either version 3 of | |
26 | +# the Licence, or (at your option) any later version. | |
27 | +# | |
28 | +# The Git-MQ program suite is distributed in the hope that it will be | |
29 | +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty | |
30 | +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
31 | +# GNU General Public Licence for more details. | |
32 | +# | |
33 | +# You should have received a copy of the GNU General Public Licence | |
34 | +# along with this program. If not, see <https://www.gnu.org/licenses/>. | |
35 | +# | |
36 | +# ------------------------------------------------------------------------------ | |
37 | +ETX | |
38 | +# Each deliverable script gets its own header preamble to the preceding | |
39 | +# copyright notice. | |
40 | +# | |
41 | +test $# -eq 0 && cat <<\ETX | |
42 | +#!/bin/sh | |
43 | +# ------------------------------------------------------------------------------ | |
44 | +# | |
45 | +# Git pre-commit hook, installed by Git-MQ, from git-pre-commit.shar | |
46 | +# | |
47 | +# CAUTION: Do NOT modify or replace this pre-commit hook! All Git-MQ commands | |
48 | +# will verify its integrity, and will abort if its hash signature has changed; | |
49 | +# any site-specific pre-commit hooks which may be desired should be relocated | |
50 | +# to the $GIT_DIR/hooks/pre-commit.dir subdirectory, whence this Git-MQ hook | |
51 | +# will invoke them. | |
52 | +# | |
53 | +ETX | |
54 | +test ${1-x} = setup && cat <<\ETX | |
55 | +# git-pre-commit-setup.sh | |
56 | +# ------------------------------------------------------------------------------ | |
57 | +# | |
58 | +# Installation support script; invoked via "mq_require", it provides the | |
59 | +# mechanisms for creation of the Git-MQ specific pre-commit hook directory | |
60 | +# infrastructure, relocation of any pre-existing repository specific hooks | |
61 | +# within this infrastructure, and installation of Git-MQ's own pre-commit | |
62 | +# hook, which is required to protect the integrity of a patch series. | |
63 | +# | |
64 | +ETX | |
65 | +test ${1-x} = verify && cat <<\ETX | |
66 | +# git-pre-commit-verify.sh | |
67 | +# ------------------------------------------------------------------------------ | |
68 | +# | |
69 | +# Verification support script, to confirm that any pre-existing pre-commit | |
70 | +# hook is that supplied by Git-MQ, or to make it so; every Git-MQ command | |
71 | +# runs this, during its standard initialization phase of execution. | |
72 | +# | |
73 | +ETX | |
74 | +# Ensure that the copyright notice is included in each generated script. | |
75 | +# | |
76 | +/bin/sh "$0" copyright | |
77 | + | |
78 | +test $1 || { echo '#'; cat <<\ETX; } | |
79 | +# Before considering any repository-specific pre-commit hook, we MUST ensure | |
80 | +# that no commit is permitted when any Git-MQ managed patch has been applied. | |
81 | +# | |
82 | + mq_hook=`git qtop 2> /dev/null` && { | |
83 | + echo >&2 "git-mq: patch series to '$mq_hook' has been applied" | |
84 | + echo >&2 "git-mq: fatal: cannot commit over applied patches" | |
85 | + exit 2 | |
86 | + } | |
87 | + | |
88 | +# If, and only if, we get past the preceding Git-MQ specific check, then we | |
89 | +# may consider any repository-specific pre-commit which may have been set up | |
90 | +# in the $GIT_DIR/hooks/pre-commit.dir subdirectory; initially assume that | |
91 | +# any such hook will permit the commit to proceed, while still providing | |
92 | +# a status code capture mechanism for recission of this permission. | |
93 | +# | |
94 | + mq_status_code=0 | |
95 | + mq_status_update() { test $1 -gt $mq_status_code && mq_status_code=$1; } | |
96 | + | |
97 | +# We may now invoke an arbitrary sequence of pre-commit hooks, in normal | |
98 | +# directory sort order; note that this differs from normal git convention, | |
99 | +# which provides for only one pre-commit script to be run, in that this | |
100 | +# script is that one, and it may delegate to any number of subsidiaries, | |
101 | +# all of which will be invoked, (excluding any which lack the executable | |
102 | +# attribute, or are named with a ".sample" suffix); any one within the | |
103 | +# sequence is empowered to rescind permission to commit. | |
104 | +# | |
105 | + for mq_hook in "$GIT_DIR/hooks/pre-commit.dir/"* | |
106 | + do case "$mq_hook" in *.sample) ;; *) | |
107 | + test -x "$mq_hook" && { "$mq_hook" || mq_status_update $?; } ;; | |
108 | + esac | |
109 | + done | |
110 | + | |
111 | +# Only if all pre-commit hooks returned zero exit codes, thus leaving the | |
112 | +# captured exit status code unchanged from its initial default value, will | |
113 | +# permission to commit be ratified. | |
114 | +# | |
115 | + exit $mq_status_code | |
116 | +ETX | |
117 | +if test ${1-x} = setup; then echo '#'; cat <<\ETX | |
118 | +# Before attempting to set up the Git-MQ pre-commit hook, first check the | |
119 | +# integrity of the Git-MQ installation itself, to ensure that the required | |
120 | +# script is available. | |
121 | +# | |
122 | + local mq_facility="git-mq" | |
123 | + local mq_libdir=`cd "$libexecdir/../hooks" && pwd` | |
124 | + test -f "$mq_libdir/pre-commit" || { | |
125 | + mq_complain "fatal: '$mq_libdir/pre-commit': file not found" | |
126 | + mq_abort 2 "fatal: cannot initialize pre-commit hook" | |
127 | + } | |
128 | +# Irrespective of whether relocation of an existing pre-commit script is | |
129 | +# required, or not, we must ensure that the pre-commit.dir subdirectory of | |
130 | +# git's hooks directory is available, and populated by at least any sample | |
131 | +# pre-commit hook, which git itself would have provided. | |
132 | +# | |
133 | + local git_mq_pre_commit_dir="$GIT_DIR/hooks/pre-commit.dir" | |
134 | + test -d "$git_mq_pre_commit_dir" || mkdir "$git_mq_pre_commit_dir" | |
135 | + test -f "$git_mq_pre_commit_dir/pre-commit.sample" || { | |
136 | + test -f "$GIT_DIR/hooks/pre-commit.sample" && { | |
137 | + mv "$GIT_DIR/hooks/pre-commit.sample" "$git_mq_pre_commit_dir" | |
138 | + } | |
139 | + } | |
140 | +# In the case of a "relocate" request, then it has already been determined | |
141 | +# that there is an existing pre-commit script in git's hooks directory; we | |
142 | +# must relocate it to Git-MQ's pre-commit.dir, provided that doing so does | |
143 | +# not relocate a similar, but distinct, artefact from some previous Git-MQ | |
144 | +# version, and does not overwrite an existing, but different script of the | |
145 | +# same name, which may have been placed in the pre-commit.dir already. | |
146 | +# | |
147 | + test ${1-x} = relocate && { | |
148 | + local mq_signature="installed by Git-MQ, from git-pre-commit.shar" | |
149 | + grep "$mq_signature" "$GIT_DIR/hooks/pre-commit" > /dev/null 2>&1 && { | |
150 | + rm "$GIT_DIR/hooks/pre-commit" | |
151 | + } || { | |
152 | + local git_mq_pre_commit_hook="$git_mq_pre_commit_dir/pre-commit" | |
153 | + test -f "$git_mq_pre_commit_hook" && { | |
154 | + cmp -s "$git_mq_pre_commit_hook" "$GIT_DIR/hooks/pre-commit" || { | |
155 | + mq_complain "fatal: cannot relocate git's pre-commit hook" | |
156 | + mq_complain "fatal: 'pre-commit.dir/pre-commit' is in the way" | |
157 | + mq_abort 2 "fatal: invalid pre-commit hook configuration" | |
158 | + } | |
159 | + rm "$GIT_DIR/hooks/pre-commit" | |
160 | + } || mv "$GIT_DIR/hooks/pre-commit" "$git_mq_pre_commit_hook" | |
161 | + } | |
162 | + } | |
163 | +# Having now ensured that there is no pre-existing pre-commit script in | |
164 | +# the way, we may now safely install the Git-MQ hook; we first attempt to | |
165 | +# link to the appropriate Git-MQ script, then, failing that, to create a | |
166 | +# symbolic link to it, and, as a last resort, copy it into place. | |
167 | +# | |
168 | + ( cd "$GIT_DIR/hooks" && { | |
169 | + ln "$mq_libdir/pre-commit" . || ln -s "$mq_libdir/pre-commit" . || | |
170 | + cp "$mq_libdir/pre-commit" . | |
171 | + } | |
172 | + ) | |
173 | +ETX | |
174 | +elif test ${1-x} = verify; then | |
175 | +eval 'mq_hash=`/bin/sh "$0" | '${git_hash="git hash-object -t blob"}' --stdin`' | |
176 | +echo '# | |
177 | +# Invoked only within the scope of an "mq_require" function call, and then | |
178 | +# only when there is a $GIT_DIR/hooks/pre-commit script already in place, we | |
179 | +# compute the git hash for that script, and verify that it matches the hash | |
180 | +# of the Git-MQ pre-commit script, as computed at build-time; if not, then | |
181 | +# we attempt to relocate the existing script into the Git-MQ pre-commit.dir | |
182 | +# chain, and install the Git-MQ pre-commit hook in its place. | |
183 | +# | |
184 | + local mq_facility=git-mq mq_hash='$mq_hash' | |
185 | + test `'$git_hash' $GIT_DIR/hooks/pre-commit` = $mq_hash || { | |
186 | + mq_require git-pre-commit-setup relocate | |
187 | + }' | |
188 | +fi | |
189 | +cat <<\ETX | |
190 | +# | |
191 | +# ------------------------------------------------------------------------------ | |
192 | +# $RCSfile$: end of file | |
193 | +ETX |