From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms1.migadu.com with LMTPS id UGixJ68EE2Y2PAAAe85BDQ:P1 (envelope-from ) for ; Sun, 07 Apr 2024 22:40:15 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2.migadu.com with LMTPS id UGixJ68EE2Y2PAAAe85BDQ (envelope-from ) for ; Sun, 07 Apr 2024 22:40:15 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gnu.org header.s=fencepost-gnu-org header.b=YsbCbbt2; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1712522415; a=rsa-sha256; cv=none; b=ayIClhxm1KVabcFoS7gh9jIsUTiu2dHjl9mJfv9NkBDCTP1L7a8T5Rx7cUDrvOvMrOGKts DUT0SD8w7sWr9KrSelxxYeGc0JBpYJlrE1vtjm1BScmx7gwRmdav6cTwweDgIvZI/36RlU DOVKDglNBxwKFHbdqY7/AtS8leHol3NV+roJg2dqlztjBxo+ONjQG6yCWXsAGyr70eowyX EvXOUe09x+4p5RcSWVfQpYt3WWByzL8Sb7gwXJtmgMR+pSqUQNBdQM4iNCEd+BRBaWdNDq NxvrlqHcHSTm4NhptMO4wiISJYrhwrqF/GJt456T90BziwhD9TZHA2Vd46kHjA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gnu.org header.s=fencepost-gnu-org header.b=YsbCbbt2; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1712522415; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=oqJNVJ9Omjr3msnY+I1fJlXhe/OVASngH3+fDfyPJEQ=; b=q8oY+dOYMOLsWRl51kd2E9RbvQKXn6T5x4OmSI5+cKvXejfB0AzRP2ePZpGmzzXKQpBsPk bIQyFM+hNrZKJqCuvc6GjGS+hwHWteqyVWitlTNQBkye8/h33MikrM2Pcwzp50BJGzVRzH vuwq7uybYJmNbl8wU+oGZ+hFo3vF3lLMJnXdSSf3Dulc2mPgr94d1Yo/fBAYANfv4BZkJ4 N6/8eq+rT8mwJExnEFFAsRlPgvpys3WjYuz3r5wGqH+3/KHEBd3HAc5kdxG4HZocpOYQ6v YYlDw4n/wrts1NR4jKsHHxmOYbveM9w9KZ4Fim54/2jjzxQeROq3D3mqzk/yBw== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 435CE730EF for ; Sun, 7 Apr 2024 22:40:15 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rtZJ4-00018D-TM; Sun, 07 Apr 2024 16:40:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rtZJ3-00016m-H1 for guix-patches@gnu.org; Sun, 07 Apr 2024 16:40:01 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rtZJ3-0005xb-88; Sun, 07 Apr 2024 16:40:01 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rtZJ7-000136-FI; Sun, 07 Apr 2024 16:40:05 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#69780] [PATCH v2 1/5] git authenticate: Record introduction and keyring in =?UTF-8?Q?=E2=80=98.git/config=E2=80=99.?= Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix@cbaines.net, dev@jpoiret.xyz, ludo@gnu.org, othacehe@gnu.org, rekado@elephly.net, zimon.toutoune@gmail.com, me@tobias.gr, guix-patches@gnu.org Resent-Date: Sun, 07 Apr 2024 20:40:05 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 69780 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 69780@debbugs.gnu.org Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= , Christopher Baines , Josselin Poiret , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Mathieu Othacehe , Ricardo Wurmus , Simon Tournier , Tobias Geerinckx-Rice X-Debbugs-Original-Xcc: Christopher Baines , Josselin Poiret , Ludovic =?UTF-8?Q?Court=C3=A8s?= , Mathieu Othacehe , Ricardo Wurmus , Simon Tournier , Tobias Geerinckx-Rice Received: via spool by 69780-submit@debbugs.gnu.org id=B69780.17125223503689 (code B ref 69780); Sun, 07 Apr 2024 20:40:05 +0000 Received: (at 69780) by debbugs.gnu.org; 7 Apr 2024 20:39:10 +0000 Received: from localhost ([127.0.0.1]:44798 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rtZIB-0000wv-GQ for submit@debbugs.gnu.org; Sun, 07 Apr 2024 16:39:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52302) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rtZI4-0000uz-Qy for 69780@debbugs.gnu.org; Sun, 07 Apr 2024 16:39:04 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rtZHs-0005pf-Hr; Sun, 07 Apr 2024 16:38:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=oqJNVJ9Omjr3msnY+I1fJlXhe/OVASngH3+fDfyPJEQ=; b=YsbCbbt2jK60c7U4ehuX 1uhapllChxoGUqETn6uLOAXLBu6psqrVA7Cduwd2+9BnfxtnH7lzQboMO600VXRguVV6pJbL5+aB/ mAQkGZ9bYQnE0wyFf+ehk9KtGAGcEP6fKDj8vgqPtso+wBRZLBpT3aIWJGq1fjN49w5mIYBQSXNif Wb0eaT08ZY18MyK2dcCDMYnruj9E1txkb7plWxsqsLHsAy8CiWyTIfq6Q/eTz1J8aZkN90AaBpLGL 05y3Z76H+asdYxHm3hqU5UwmCNjoZJxVxPAKw45M1y3t7bnhfswPiv8uL48XCrbAyM8SVagqGbUJD Hv8gFKkETK5ovw==; From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Date: Sun, 7 Apr 2024 22:38:26 +0200 Message-ID: <4d37936c1b3aed95ca72de2ba112033bafefc2de.1712522118.git.ludo@gnu.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Spam-Score: -4.57 X-Migadu-Queue-Id: 435CE730EF X-Migadu-Spam-Score: -4.57 X-Migadu-Scanner: mx10.migadu.com X-TUID: V+hMNizr5E8k * guix/scripts/git/authenticate.scm (%default-options): Remove ‘keyring-reference’. (config-value, configured-introduction, configured-keyring-reference) (configured?, record-configuration, current-branch): New procedures. (guix-git-authenticate)[missing-arguments]: New procedure. Use ‘configured-introduction’ when zero arguments are given. Use ‘configured-keyring-reference’ when ‘-k’ is not passed. Add call to ‘record-configuration’. * doc/guix.texi (Invoking guix git authenticate): Document it. Change-Id: I66e111a83f50407b52da71662629947f83a78bbc --- doc/guix.texi | 28 +++++- guix/scripts/git/authenticate.scm | 147 +++++++++++++++++++++++------- tests/guix-git-authenticate.sh | 9 +- 3 files changed, 150 insertions(+), 34 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index acfe60b47a..6ff0e76d97 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -7667,6 +7667,8 @@ Invoking guix git authenticate @section Invoking @command{guix git authenticate} @cindex @command{guix git authenticate} +@cindex authentication, of Git checkouts +@cindex Git checkout authentication The @command{guix git authenticate} command authenticates a Git checkout following the same rule as for channels (@pxref{channel-authentication, @@ -7686,13 +7688,35 @@ Invoking guix git authenticate guix git authenticate @var{commit} @var{signer} [@var{options}@dots{}] @end example +@cindex introduction, for Git authentication By default, this command authenticates the Git checkout in the current directory; it outputs nothing and exits with exit code zero on success and non-zero on failure. @var{commit} above denotes the first commit where authentication takes place, and @var{signer} is the OpenPGP fingerprint of public key used to sign @var{commit}. Together, they -form a ``channel introduction'' (@pxref{channel-authentication, channel -introduction}). The options below allow you to fine-tune the process. +form a @dfn{channel introduction} (@pxref{channel-authentication, channel +introduction}). On your first successful run, the introduction is +recorded in the @file{.git/config} file of your checkout, allowing you +to omit them from subsequent invocations: + +@example +guix git authenticate [@var{options}@dots{}] +@end example + +Should you have branches that require different introductions, you can +specify them directly in @file{.git/config}. For example, if the branch +called @code{personal-fork} has a different introduction than other +branches, you can extend @file{.git/config} along these lines: + +@smallexample +[guix "authentication-personal-fork"] + introduction-commit = cabba936fd807b096b48283debdcddccfea3900d + introduction-signer = C0FF EECA BBA9 E6A8 0D1D E643 A2A0 6DF2 A33A 54FA + keyring = keyring +@end smallexample + +The command-line options described below allow you to fine-tune the +process. @table @code @item --repository=@var{directory} diff --git a/guix/scripts/git/authenticate.scm b/guix/scripts/git/authenticate.scm index def4879e96..a606f1c146 100644 --- a/guix/scripts/git/authenticate.scm +++ b/guix/scripts/git/authenticate.scm @@ -31,6 +31,7 @@ (define-module (guix scripts git authenticate) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) #:use-module (ice-9 format) #:use-module (ice-9 match) #:export (guix-git-authenticate)) @@ -73,8 +74,79 @@ (define %options (alist-cons 'show-stats? #t result))))) (define %default-options - '((directory . ".") - (keyring-reference . "keyring"))) + '((directory . "."))) + +(define (current-branch repository) + "Return the name of the checked out branch of REPOSITORY or #f if it could +not be determined." + (and (not (repository-head-detached? repository)) + (let* ((head (repository-head repository)) + (name (reference-name head))) + (and (string-prefix? "refs/heads/" name) + (string-drop name (string-length "refs/heads/")))))) + +(define (config-value repository key) + "Return the config value associated with KEY in the 'guix.authentication' or +'guix.authentication-BRANCH' name space in REPOSITORY, or #f if no such config +was found." + (let-syntax ((false-if-git-error + (syntax-rules () + ((_ exp) + (catch 'git-error (lambda () exp) (const #f)))))) + (let* ((config (repository-config repository)) + (branch (current-branch repository))) + ;; First try the BRANCH-specific value, then the generic one.` + (or (and branch + (false-if-git-error + (config-entry-value + (config-get-entry config + (string-append "guix.authentication-" + branch "." key))))) + (false-if-git-error + (config-entry-value + (config-get-entry config + (string-append "guix.authentication." + key)))))))) + +(define (configured-introduction repository) + "Return two values: the commit and signer fingerprint (strings) as +configured in REPOSITORY. Error out if one or both were missing." + (let* ((commit (config-value repository "introduction-commit")) + (signer (config-value repository "introduction-signer"))) + (unless (and commit signer) + (leave (G_ "unknown introductory commit and signer~%"))) + (values commit signer))) + +(define (configured-keyring-reference repository) + "Return the keyring reference configured in REPOSITORY or #f if missing." + (config-value repository "keyring")) + +(define (configured? repository) + "Return true if REPOSITORY already container introduction info in its +'config' file." + (and (config-value repository "introduction-commit") + (config-value repository "introduction-signer"))) + +(define* (record-configuration repository + #:key commit signer keyring-reference) + "Record COMMIT, SIGNER, and KEYRING-REFERENCE in the 'config' file of +REPOSITORY." + (define config + (repository-config repository)) + + ;; Guile-Git < 0.7.0 lacks 'set-config-string'. + (if (module-defined? (resolve-interface '(git)) 'set-config-string) + (begin + (set-config-string config "guix.authentication.introduction-commit" + commit) + (set-config-string config "guix.authentication.introduction-signer" + signer) + (set-config-string config "guix.authentication.keyring" + keyring-reference) + (info (G_ "introduction and keyring recorded \ +in repository configuration file~%"))) + (warning (G_ "could not record introduction and keyring configuration\ + (Guile-Git too old?)~%")))) (define (show-stats stats) "Display STATS, an alist containing commit signing stats as returned by @@ -158,35 +230,48 @@ (define (guix-git-authenticate . args) (progress-reporter/bar (length commits)) progress-reporter/silent)) + (define (missing-arguments) + (leave (G_ "wrong number of arguments; \ +expected COMMIT and SIGNER~%"))) + (with-error-handling (with-git-error-handling - (match (command-line-arguments options) - ((commit signer) - (let* ((directory (assoc-ref options 'directory)) - (show-stats? (assoc-ref options 'show-stats?)) - (keyring (assoc-ref options 'keyring-reference)) - (repository (repository-open directory)) - (end (match (assoc-ref options 'end-commit) - (#f (reference-target - (repository-head repository))) - (oid oid))) - (history (match (assoc-ref options 'historical-authorizations) - (#f '()) - (file (call-with-input-file file - read-authorizations)))) - (cache-key (or (assoc-ref options 'cache-key) - (repository-cache-key repository)))) - (define stats - (authenticate-repository repository (string->oid commit) - (openpgp-fingerprint* signer) - #:end end - #:keyring-reference keyring - #:historical-authorizations history - #:cache-key cache-key - #:make-reporter make-reporter)) + (let* ((directory (assoc-ref options 'directory)) + (show-stats? (assoc-ref options 'show-stats?)) + (repository (repository-open directory)) + (commit signer (match (command-line-arguments options) + ((commit signer) + (values commit signer)) + (() + (configured-introduction repository)) + (_ + (missing-arguments)))) + (keyring (or (assoc-ref options 'keyring-reference) + (configured-keyring-reference repository) + "keyring")) + (end (match (assoc-ref options 'end-commit) + (#f (reference-target + (repository-head repository))) + (oid oid))) + (history (match (assoc-ref options 'historical-authorizations) + (#f '()) + (file (call-with-input-file file + read-authorizations)))) + (cache-key (or (assoc-ref options 'cache-key) + (repository-cache-key repository)))) + (define stats + (authenticate-repository repository (string->oid commit) + (openpgp-fingerprint* signer) + #:end end + #:keyring-reference keyring + #:historical-authorizations history + #:cache-key cache-key + #:make-reporter make-reporter)) - (when (and show-stats? (not (null? stats))) - (show-stats stats)))) - (_ - (leave (G_ "wrong number of arguments; \ -expected COMMIT and SIGNER~%"))))))) + (unless (configured? repository) + (record-configuration repository + #:commit commit #:signer signer + #:keyring-reference keyring)) + + (when (and show-stats? (not (null? stats))) + (show-stats stats)))))) diff --git a/tests/guix-git-authenticate.sh b/tests/guix-git-authenticate.sh index ec89f941e6..7b8951b9aa 100644 --- a/tests/guix-git-authenticate.sh +++ b/tests/guix-git-authenticate.sh @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2020, 2022 Ludovic Courtès +# Copyright © 2020, 2022, 2024 Ludovic Courtès # # This file is part of GNU Guix. # @@ -46,6 +46,13 @@ guix git authenticate "$intro_commit" "$intro_signer" \ --cache-key="$cache_key" --stats \ --end="$v1_2_0_commit" +# Check a commit that came soon after v1.2.0. No need to repeat $intro_commit +# and $intro_signer because it should have been recorded in '.git/config'. +after_v1_2_0="be4d9527b55b6829e33a6e0727496af25927a786" +guix git authenticate \ + --cache-key="$cache_key" --stats \ + --end="$v1_2_0_commit" + rm "$XDG_CACHE_HOME/guix/authentication/$cache_key" # Commit and signer of the 'v1.0.0' tag. -- 2.41.0