git authenticate: Upgrade pre-push hook with a fixed version.

Partly fixes <https://issues.guix.gnu.org/74583>.

* guix/scripts/git/authenticate.scm (%pre-push-hook): New variable.
(install-hooks): Use it.
(broken-pre-push-hook?, maybe-upgrade-hooks): New procedures.
(guix-git-authenticate): Call ‘maybe-upgrade-hooks’ when ‘configured?’
returns true.

Change-Id: I39d34ab66ffe0f34170c0f562e9f97f2f69c9fdc
This commit is contained in:
Ludovic Courtès 2025-06-08 16:50:40 +02:00
parent 55b38ddefc
commit 56eb949f3b
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -26,8 +26,10 @@
#:use-module ((guix channels) #:select (openpgp-fingerprint)) #:use-module ((guix channels) #:select (openpgp-fingerprint))
#:use-module ((guix git) #:select (with-git-error-handling)) #:use-module ((guix git) #:select (with-git-error-handling))
#:use-module (guix progress) #:use-module (guix progress)
#:autoload (guix base16) (base16-string->bytevector)
#:use-module (guix base64) #:use-module (guix base64)
#:autoload (rnrs bytevectors) (bytevector-length) #:autoload (rnrs bytevectors) (bytevector=? bytevector-length)
#:autoload (gcrypt hash) (port-hash hash-algorithm sha1)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (srfi srfi-37) #:use-module (srfi srfi-37)
@ -143,6 +145,24 @@ REPOSITORY."
(info (G_ "introduction and keyring recorded \ (info (G_ "introduction and keyring recorded \
in repository configuration file~%"))) in repository configuration file~%")))
(define %pre-push-hook
;; Contents of the pre-push hook that gets installed.
"\
#!/bin/sh
# Installed by 'guix git authenticate'.
set -e
# The \"empty hash\" used by Git when pushing a branch deletion.
z40=0000000000000000000000000000000000000000
while read local_ref local_oid remote_ref remote_oid
do
if [ \"$local_oid\" != \"$z40\" ]
then
guix git authenticate --end=\"$local_oid\"
fi
done\n")
(define (install-hooks repository) (define (install-hooks repository)
"Attempt to install in REPOSITORY hooks that invoke 'guix git authenticate'. "Attempt to install in REPOSITORY hooks that invoke 'guix git authenticate'.
Bail out if one of these already exists." Bail out if one of these already exists."
@ -166,13 +186,7 @@ authenticated before you push and when you pull updates.")))
(begin (begin
(call-with-output-file pre-push-hook (call-with-output-file pre-push-hook
(lambda (port) (lambda (port)
(format port "#!/bin/sh (display %pre-push-hook port)
# Installed by 'guix git authenticate'.
set -e
while read local_ref local_oid remote_ref remote_oid
do
guix git authenticate --end=\"$local_oid\"
done\n")
(chmod port #o755))) (chmod port #o755)))
(call-with-output-file post-merge-hook (call-with-output-file post-merge-hook
(lambda (port) (lambda (port)
@ -183,6 +197,42 @@ exec guix git authenticate\n")
(info (G_ "installed hooks '~a' and '~a'~%") (info (G_ "installed hooks '~a' and '~a'~%")
pre-push-hook post-merge-hook)))) pre-push-hook post-merge-hook))))
(define (broken-pre-push-hook? file)
"Return true if FILE corresponds to a missing or known-broken pre-push hook
that needs to be replaced."
(define broken-pre-push-hooks
;; Size and SHA1 hash of pre-push hooks that were automatically installed
;; but are known to be broken.
`((161 "a9916155b71894014144fcafad7700f89da26c83")))
(match (stat file #f)
(#f #t)
(st
(find (match-lambda
((size bad-sha1)
(and (= size (stat:size st))
(bytevector=? (call-with-input-file file
(lambda (port)
(port-hash (hash-algorithm sha1) port)))
(base16-string->bytevector bad-sha1)))))
broken-pre-push-hooks))))
(define (maybe-upgrade-hooks repository)
"Update pre-push or post-merge hooks in REPOSITORY if it is missing or a
known-broken version is installed."
(define directory
(repository-common-directory repository))
(define pre-push-hook
(in-vicinity directory "hooks/pre-push"))
(when (broken-pre-push-hook? pre-push-hook)
(info (G_ "upgrading hook '~a'~%") pre-push-hook)
(call-with-output-file pre-push-hook
(lambda (port)
(display %pre-push-hook port)
(chmod port #o755)))))
(define (show-stats stats) (define (show-stats stats)
"Display STATS, an alist containing commit signing stats as returned by "Display STATS, an alist containing commit signing stats as returned by
'authenticate-repository'." 'authenticate-repository'."
@ -303,11 +353,13 @@ expected COMMIT and SIGNER~%")))
#:cache-key cache-key #:cache-key cache-key
#:make-reporter make-reporter)) #:make-reporter make-reporter))
(unless (configured? repository) (if (configured? repository)
(maybe-upgrade-hooks repository)
(begin
(record-configuration repository (record-configuration repository
#:commit commit #:signer signer #:commit commit #:signer signer
#:keyring-reference keyring) #:keyring-reference keyring)
(install-hooks repository)) (install-hooks repository)))
(when (and show-stats? (not (null? stats))) (when (and show-stats? (not (null? stats)))
(show-stats stats)) (show-stats stats))