GNU bug report logs - #78568
[PATCH 0/5] Synchronize team definitions with Codeberg

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Fri, 23 May 2025 19:54:02 UTC

Severity: normal

Tags: patch

To reply to this bug, email your comments to 78568 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:54:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludo <at> gnu.org>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Fri, 23 May 2025 19:54:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: guix-patches <at> gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 0/5] Synchronize team definitions with Codeberg
Date: Fri, 23 May 2025 21:52:39 +0200
Hello Guix,

As a followup to <https://issues.guix.gnu.org/78354>, this patch
series adds a ‘sync-codeberg-teams’ command that pushes team
definitions to Codeberg (name, description, and members).

Currently it creates teams with read-only repository access such
that being a team member does not equate to being a committer (as
is currently the case).

Synchronization works by deleting the team from Codeberg if it
already exists, and recreating it.  This is brute force but it
appears to work well (nothing is lost and list of deletions/creations
does not show up in the activity log; there’s also no rate limit
apparently.)

You can see the result here (you need to be logged in):

  https://codeberg.org/org/guix/teams

That’s 42 teams.  Coincidence?

Feedback welcome!

Ludo’.

PS: ‘define-forgejo-request’ & co. could be used as the basis
    of a separate Guile library of Forgejo bindings.

Ludovic Courtès (5):
  teams: Add ‘codeowners’ command in help message.
  teams: Use suitable team identifiers for Codeberg.
  teams: Add missing team descriptions.
  teams: Add Codeberg accounts to <person> records.
  teams: Add ‘sync-codeberg-teams’ action.

 etc/teams.scm | 367 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 331 insertions(+), 36 deletions(-)


base-commit: 8dff81313876a54519ce17e9fda64d4310e2dd5c
-- 
2.49.0





Information forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:56:01 GMT) Full text and rfc822 format available.

Message #8 received at 78568 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78568 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 1/5] teams: Add ‘codeowners’ command in help message.
Date: Fri, 23 May 2025 21:55:05 +0200
* etc/teams.scm (main): Add ‘codeowners’ command in help message.

Change-Id: I859997aba2b8829173e608e5ba1c8ab59b79d9c5
---
 etc/teams.scm | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/etc/teams.scm b/etc/teams.scm
index f7617e724e..a57d132787 100755
--- a/etc/teams.scm
+++ b/etc/teams.scm
@@ -1107,6 +1107,8 @@ (define (main . args)
   get-maintainer <patch>
       compatibility mode with Linux get_maintainer.pl
   show <team-name>
-      display <team-name> properties~%"))))
+      display <team-name> properties
+  codeowners
+      write a 'CODEOWNERS' file suitable for Codeberg on standard output~%"))))
 
 (apply main (cdr (command-line)))
-- 
2.49.0





Information forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:56:02 GMT) Full text and rfc822 format available.

Message #11 received at 78568 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78568 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 2/5] teams: Use suitable team identifiers for Codeberg.
Date: Fri, 23 May 2025 21:55:06 +0200
The “c++” team has to be called “cpp”.

* etc/teams.scm (team-id->forgejo-id): New procedure.
(team->codeowners-snippet): Use it.

Change-Id: I10619d8833b5c747504f26b7b0eedb9d61bfd812
---
 etc/teams.scm | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/etc/teams.scm b/etc/teams.scm
index a57d132787..9fa189a92c 100755
--- a/etc/teams.scm
+++ b/etc/teams.scm
@@ -1024,13 +1024,27 @@ (define (patch->teams patch-file)
        (find-team-by-scope (apply diff-revisions
                                   (git-patch->revisions patch-file)))))
 
+(define (team-id->forgejo-id id)
+  "Return a name (string) suitable as a Forgejo team name."
+  (define valid                                   ;"AlphaDashDot"
+    (char-set-union char-set:ascii (char-set #\-) (char-set #\.)))
+
+  (define (valid? chr)
+    (char-set-contains? valid chr))
+
+  (string-map (match-lambda
+                (#\+ #\p)                         ;special case for "c++"
+                ((? valid? chr) chr)
+                (_ #\-))
+              (symbol->string id)))
+
 (define (team->codeowners-snippet team)
   (string-join (map (lambda (scope)
                       (format #f "~50a @guix/~a"
                               (if (regexp*? scope)
                                   (regexp*-pattern scope)
                                   (regexp-quote scope))
-                              (team-id team)))
+                              (team-id->forgejo-id (team-id team))))
                     (team-scope team))
                "\n"
                'suffix))
-- 
2.49.0





Information forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:56:02 GMT) Full text and rfc822 format available.

Message #14 received at 78568 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78568 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 3/5] teams: Add missing team descriptions.
Date: Fri, 23 May 2025 21:55:07 +0200
* etc/teams.scm (bootstrap, hurd): Add #:description.

Change-Id: I531907763c746420a60daf6a5c33ec586565db07
---
 etc/teams.scm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/etc/teams.scm b/etc/teams.scm
index 9fa189a92c..4b06d3a937 100755
--- a/etc/teams.scm
+++ b/etc/teams.scm
@@ -126,6 +126,7 @@ (define-team audio
 (define-team bootstrap
   (team 'bootstrap
         #:name "Bootstrap"
+        #:description "Full-source bootstrap: stage0, Mes, Gash, etc."
         #:scope (list "gnu/packages/commencement.scm"
                       "gnu/packages/mes.scm")))
 
@@ -355,6 +356,7 @@ (define-team home
 (define-team hurd
   (team 'hurd
         #:name "Team for the Hurd"
+        #:description "GNU Hurd packages and operating system support."
         #:scope (list "gnu/system/hurd.scm"
                       "gnu/system/images/hurd.scm"
                       "gnu/build/hurd-boot.scm"
-- 
2.49.0





Information forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:56:03 GMT) Full text and rfc822 format available.

Message #17 received at 78568 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78568 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 5/5] teams: Add ‘sync-codeberg-teams’ action.
Date: Fri, 23 May 2025 21:55:09 +0200
* etc/teams.scm (<forgejo-team>): New JSON mapping.
(unit-map->json, json->unit-map): New procedures.
(%default-forgejo-team-units, %default-forgejo-team-unit-map)
(%codeberg-organization): New variables.
(codeberg-url, forgejo-http-headers): New procedures.
(&forgejo-error): New record type.
(process-url-components, define-forgejo-request): New macros.
(organization-teams, create-team, add-team-member)
(team->forgejo-team, synchronize-team, synchronize-teams): New
procedures.
(main): Add ‘sync-codeberg-teams’ action.

Change-Id: I6b1f437a3407bc2d44965519990deb524afa9528
---
 etc/teams.scm | 252 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 250 insertions(+), 2 deletions(-)

diff --git a/etc/teams.scm b/etc/teams.scm
index e881e916ab..08ca891e0d 100755
--- a/etc/teams.scm
+++ b/etc/teams.scm
@@ -41,12 +41,21 @@
 (use-modules (srfi srfi-1)
              (srfi srfi-9)
              (srfi srfi-26)
+             (srfi srfi-34)
+             (srfi srfi-35)
+             (srfi srfi-71)
              (ice-9 format)
              (ice-9 regex)
              (ice-9 match)
              (ice-9 rdelim)
              (guix ui)
-             (git))
+             (git)
+             (json)
+             (web client)
+             (web request)
+             (web response)
+             (rnrs bytevectors)
+             (guix base64))
 
 (define-record-type <regexp*>
   (%make-regexp* pat flag rx)
@@ -116,6 +125,241 @@ (define-syntax-rule (define-member person teams ...)
                    team (cons p (team-members team)))))
               (quote (teams ...)))))
 
+
+;;;
+;;; Forgejo support.
+;;;
+
+;; Forgejo team.  This corresponds to both the 'Team' and 'CreateTeamOption'
+;; structures in Forgejo.
+(define-json-mapping <forgejo-team>
+  forgejo-team forgejo-team?
+  json->forgejo-team <=> forgejo-team->json
+  (name                forgejo-team-name)
+  (id                  forgejo-team-id)           ;integer
+  (description         forgejo-team-description)
+  (all-repositories?   forgejo-team-all-repositories?
+                       "includes_all_repositories")
+  (can-create-org-repository? forgejo-team-can-create-org-repository?
+                              "can_create_org_repo")
+  (permission          forgejo-team-permission
+                       "permission" string->symbol symbol->string)
+  ;; A 'units' field exists but is deprecated in favor of 'units_map'.
+  (unit-map            forgejo-team-unit-map
+                       "units_map" json->unit-map unit-map->json))
+
+(define (unit-map->json lst)
+  (map (match-lambda
+         ((unit . permission)
+          (cons unit (symbol->string permission))))
+       lst))
+
+(define (json->unit-map lst)
+  (map (match-lambda
+         ((unit . permission)
+          (cons unit (string->symbol permission))))
+       lst))
+
+(define %default-forgejo-team-units
+  '("repo.code" "repo.issues" "repo.pulls" "repo.releases"
+    "repo.wiki" "repo.ext_wiki" "repo.ext_issues" "repo.projects"
+    "repo.packages" "repo.actions"))
+
+(define %default-forgejo-team-unit-map
+  ;; Everything (including "repo.code") is read-only by default, except a few
+  ;; units.
+  (map (match-lambda
+         ("repo.pulls" (cons "repo.pulls" 'write))
+         ("repo.issues" (cons "repo.issues" 'write))
+         ("repo.wiki" (cons "repo.wiki" 'write))
+         (unit (cons unit 'read)))
+       %default-forgejo-team-units))
+
+(define (forgejo-http-headers token)
+  "Return the HTTP headers for basic authorization with TOKEN."
+  `((content-type . (application/json (charset . "UTF-8")))
+    ;; The "Auth Basic" scheme needs a base64-encoded colon-separated user and
+    ;; token values. Forgejo doesn't seem to care for the user part but the
+    ;; colon seems to be necessary for the token value to get extracted.
+    (authorization . (basic . ,(base64-encode
+                                (string->utf8
+                                 (string-append ":" token)))))))
+
+;; Error with a Forgejo request.
+(define-condition-type &forgejo-error &error
+  forgejo-error?
+  (url       forgejo-error-url)
+  (method    forgejo-error-method)
+  (response  forgejo-error-response))
+
+(define %codeberg-organization
+  ;; Name of the organization at codeberg.org.
+  "guix")
+
+(define* (codeberg-url items #:key (parameters '()))
+  "Construct a Codeberg API URL with the path components ITEMS and query
+PARAMETERS."
+  (define query
+    (match parameters
+      (() "")
+      (((keys . values) ...)
+       (string-append "?" (string-join
+                           (map (lambda (key value)
+                                  (string-append key "=" value)) ;XXX: hackish
+                                keys values)
+                           "&")))))
+
+  (string-append "https://codeberg.org/api/v1/"
+                 (string-join items "/")
+                 query))
+
+(define-syntax process-url-components
+  (syntax-rules (&)
+    "Helper macro to construct a Codeberg URL."
+    ((_ components ... & parameters)
+     (codeberg-url (list components ...)
+                   #:parameters parameters))
+    ((_ components ...)
+     (codeberg-url (list components ...)))))
+
+(define-syntax define-forgejo-request
+  (syntax-rules (=>)
+    "Define a procedure that performs a Forgejo request."
+    ((_ (proc parameters ...)
+        docstring
+        (verb components ...)
+        body
+        => code
+        deserialize)
+     (define (proc token parameters ...)
+       docstring
+       (let* ((url (process-url-components components ...))
+              (response port (http-request url
+                                           #:method 'verb
+                                           #:streaming? #t
+                                           #:headers (forgejo-http-headers token)
+                                           #:body body)))
+         (if (= code (response-code response))
+             (let ((value (deserialize port)))
+               (when port (close-port port))
+               value)
+             (begin
+               (when port (close-port port))
+               (raise (condition (&forgejo-error (url url)
+                                                 (method 'verb)
+                                                 (response response)))))))))
+    ((_ (proc parameters ...)
+        docstring
+        (method components ...)
+        => code
+        deserialize)
+     (define-forgejo-request (proc parameters ...)
+       docstring
+       (method components ...)
+       ""
+       => code
+       deserialize))
+    ((_ (proc parameters ...)
+        docstring
+        (method components ...)
+        => code)
+     (define-forgejo-request (proc parameters ...)
+       docstring
+       (method components ...)
+       ""
+       => code
+       (const *unspecified*)))))
+
+;; API documentation at <https://codeberg.org/api/swagger>.
+
+(define-forgejo-request (organization-teams organization)
+  "Return the list of teams of ORGANIZATION."
+  (GET "orgs" organization "teams"
+       & '(("limit" . "100")))                    ;get up to 100 teams
+  => 200
+  (lambda (port)
+    (map json->forgejo-team (vector->list (json->scm port)))))
+
+(define-forgejo-request (create-team organization team)
+  "Create TEAM, a Forgejo team, under ORGANIZATION."
+  (POST "orgs" organization "teams")
+  (forgejo-team->json team)
+  => 201
+  json->forgejo-team)
+
+(define-forgejo-request (delete-team team)
+  "Delete TEAM, a Forgejo team."
+  (DELETE "teams" (number->string (forgejo-team-id team)))
+  => 204)
+
+(define-forgejo-request (add-team-member team user)
+  "Add USER (a string) to TEAM, a Forgejo team."
+  (PUT "teams" (number->string (forgejo-team-id team))
+       "members" user)
+  => 204)
+
+(define (team->forgejo-team team)
+  "Return a Forgejo team derived from TEAM, a <team> record."
+  (forgejo-team (team-id->forgejo-id (team-id team))
+                #f
+                (or (team-description team) "")
+                #f                                ;all-repositories?
+                #f                                ;can-create-org-repository?
+                'read                             ;permission
+                %default-forgejo-team-unit-map))
+
+(define* (synchronize-team token team
+                           #:key
+                           (current-teams
+                            (organization-teams token
+                                                %codeberg-organization))
+                           (log-port (current-error-port)))
+  "Synchronize TEAM, a <team> record, so that its metadata and list of members
+are accurate on Codeberg.  Lookup team IDs among CURRENT-TEAMS."
+  (let ((forgejo-team
+         (find (let ((name (team-id->forgejo-id (team-id team))))
+                 (lambda (candidate)
+                   (string=? (forgejo-team-name candidate) name)))
+               current-teams)))
+    (when forgejo-team
+      ;; Delete the previously-created team.
+      (format log-port "team '~a' already exists; deleting it~%"
+              (forgejo-team-name forgejo-team))
+      (delete-team token forgejo-team))
+
+    ;; Create the team.
+    (let ((forgejo-team
+           (create-team token %codeberg-organization
+                        (or forgejo-team
+                            (team->forgejo-team team)))))
+      (format log-port "created team '~a'~%"
+              (forgejo-team-name forgejo-team))
+      (let ((members (filter-map person-codeberg-account
+                                 (team-members team))))
+        (for-each (lambda (member)
+                    (add-team-member token forgejo-team member))
+                  members)
+        (format log-port "added ~a members to team '~a'~%"
+                (length members)
+                (forgejo-team-name forgejo-team))
+        forgejo-team))))
+
+(define (synchronize-teams token)
+  "Push all the existing teams on Codeberg."
+  (let ((teams (sort-teams
+                (hash-map->list (lambda (_ value) value) %teams))))
+    (format (current-error-port)
+            "creating ~a teams in the '~a' organization at Codeberg...~%"
+            (length teams) %codeberg-organization)
+
+    ;; Arrange to compute the list of existing teams once and for all.
+    (for-each (let ((teams (organization-teams token
+                                               %codeberg-organization)))
+                (lambda (team)
+                  (synchronize-team token team
+                                    #:current-teams teams)))
+              teams)))
+
 
 
 (define-team audio
@@ -1132,6 +1376,8 @@ (define (main . args)
      (list-teams team-names))
     (("codeowners")
      (export-codeowners (current-output-port)))
+    (("sync-codeberg-teams" token)
+     (synchronize-teams token))
     (anything
      (format (current-error-port)
              "Usage: etc/teams.scm <command> [<args>]
@@ -1154,6 +1400,8 @@ (define (main . args)
   show <team-name>
       display <team-name> properties
   codeowners
-      write a 'CODEOWNERS' file suitable for Codeberg on standard output~%"))))
+      write a 'CODEOWNERS' file suitable for Codeberg on standard output
+  sync-codeberg-teams <token>
+      create or update the list of teams at Codeberg~%"))))
 
 (apply main (cdr (command-line)))
-- 
2.49.0





Information forwarded to guix-patches <at> gnu.org:
bug#78568; Package guix-patches. (Fri, 23 May 2025 19:56:04 GMT) Full text and rfc822 format available.

Message #20 received at 78568 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78568 <at> debbugs.gnu.org
Cc: Ludovic Courtès <ludo <at> gnu.org>
Subject: [PATCH 4/5] teams: Add Codeberg accounts to <person> records.
Date: Fri, 23 May 2025 21:55:08 +0200
Based on the committer accounts given in the thread at
<https://lists.gnu.org/archive/html/guix-devel/2025-05/msg00072.html>.

* etc/teams.scm (<person>)[account]: Add field.
(person): Add ‘account’ parameter.
<top level>: Add known Codeberg account names.

Change-Id: Iad3b10c328b0df5d3c68d98ffee7f7c8ec4c8e23
---
 etc/teams.scm | 95 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 62 insertions(+), 33 deletions(-)

diff --git a/etc/teams.scm b/etc/teams.scm
index 4b06d3a937..e881e916ab 100755
--- a/etc/teams.scm
+++ b/etc/teams.scm
@@ -75,13 +75,14 @@ (define-record-type <team>
   (scope       team-scope))
 
 (define-record-type <person>
-  (make-person name email)
+  (make-person name email account)
   person?
   (name    person-name)
-  (email   person-email))
+  (email   person-email)
+  (account person-codeberg-account))
 
-(define* (person name #:optional email)
-  (make-person name email))
+(define* (person name #:optional email account)
+  (make-person name email account))
 
 (define* (team id #:key name description (members '())
                (scope '()))
@@ -672,24 +673,29 @@ (define-team zig
 
 
 (define-member (person "Eric Bavier"
-                       "bavier <at> posteo.net")
+                       "bavier <at> posteo.net"
+                       "bavier")
   science)
 
 (define-member (person "Lars-Dominik Braun"
-                       "lars <at> 6xq.net")
+                       "lars <at> 6xq.net"
+                       "ldb")
   python haskell)
 
 (define-member (person "Jonathan Brielmaier"
-                       "jonathan.brielmaier <at> web.de")
+                       "jonathan.brielmaier <at> web.de"
+                       "jonsger")
   mozilla)
 
 (define-member (person "Ludovic Courtès"
-                       "ludo <at> gnu.org")
+                       "ludo <at> gnu.org"
+                       "civodul")
   core home bootstrap core-packages installer
   documentation mentors)
 
 (define-member (person "Andreas Enge"
-                       "andreas <at> enge.fr")
+                       "andreas <at> enge.fr"
+                       "enge")
   bootstrap core-packages lxqt science tex)
 
 (define-member (person "Tanguy Le Carrour"
@@ -701,15 +707,18 @@ (define-member (person "Tobias Geerinckx-Rice"
   core mentors)
 
 (define-member (person "Steve George"
-                       "steve <at> futurile.net")
+                       "steve <at> futurile.net"
+                       "futurile")
   rust)
 
 (define-member (person "Leo Famulari"
-                       "leo <at> famulari.name")
+                       "leo <at> famulari.name"
+                       "lfam")
   kernel)
 
 (define-member (person "Efraim Flashner"
-                       "efraim <at> flashner.co.il")
+                       "efraim <at> flashner.co.il"
+                       "efraim")
   embedded bootstrap rust)
 
 (define-member (person "jgart"
@@ -717,11 +726,13 @@ (define-member (person "jgart"
   lisp mentors)
 
 (define-member (person "Guillaume Le Vaillant"
-                       "glv <at> posteo.net")
+                       "glv <at> posteo.net"
+                       "glv")
   lisp)
 
 (define-member (person "Julien Lepiller"
-                       "julien <at> lepiller.eu")
+                       "julien <at> lepiller.eu"
+                       "roptat")
   java ocaml translations)
 
 (define-member (person "Philip McGrath"
@@ -729,23 +740,28 @@ (define-member (person "Philip McGrath"
   racket)
 
 (define-member (person "Mathieu Othacehe"
-                       "othacehe <at> gnu.org")
+                       "othacehe <at> gnu.org"
+                       "mothacehe")
   core installer mentors)
 
 (define-member (person "Florian Pelz"
-                       "pelzflorian <at> pelzflorian.de")
+                       "pelzflorian <at> pelzflorian.de"
+                       "pelzflorian")
   translations)
 
 (define-member (person "Liliana Marie Prikler"
-                       "liliana.prikler <at> gmail.com")
+                       "liliana.prikler <at> gmail.com"
+                       "lilyp")
   emacs games gnome)
 
 (define-member (person "Ricardo Wurmus"
-                       "rekado <at> elephly.net")
+                       "rekado <at> elephly.net"
+                       "rekado")
   r sugar)
 
 (define-member (person "Christopher Baines"
-                       "guix <at> cbaines.net")
+                       "guix <at> cbaines.net"
+                       "cbaines")
   core mentors ruby)
 
 (define-member (person "Andrew Tropin"
@@ -769,19 +785,22 @@ (define-member (person "Simon Tournier"
   julia core mentors r)
 
 (define-member (person "宋文武"
-                       "iyzsong <at> envs.net")
+                       "iyzsong <at> envs.net"
+                       "iyzsong")
   games localization lxqt qt xfce)
 
 (define-member (person "Vagrant Cascadian"
-                       "vagrant <at> debian.org")
+                       "vagrant <at> debian.org"
+                       "vagrantc")
   embedded)
 
-(define-member (person "Vagrant Cascadian"
+(define-member (person "Vagrant Cascadian"        ;XXX: duplicate
                        "vagrant <at> reproducible-builds.org")
   reproduciblebuilds)
 
 (define-member (person "Maxim Cournoyer"
-                       "maxim.cournoyer <at> gmail.com")
+                       "maxim.cournoyer <at> gmail.com"
+                       "apteryx")
   documentation gnome qt telephony electronics)
 
 (define-member (person "Katherine Cox-Buday"
@@ -797,7 +816,8 @@ (define-member (person "Gabriel Wicki"
   audio documentation electronics embedded)
 
 (define-member (person "Ekaitz Zarraga"
-                       "ekaitz <at> elenq.tech")
+                       "ekaitz <at> elenq.tech"
+                       "ekaitz-zarraga")
   bootstrap zig electronics)
 
 (define-member (person "Divya Ranjan Pattanaik"
@@ -805,7 +825,8 @@ (define-member (person "Divya Ranjan Pattanaik"
   emacs rust haskell)
 
 (define-member (person "Clément Lassieur"
-                       "clement <at> lassieur.org")
+                       "clement <at> lassieur.org"
+                       "snape")
   mozilla)
 
 (define-member (person "Sharlatan Hellseher"
@@ -817,7 +838,8 @@ (define-member (person "Vivien Kraus"
   gnome)
 
 (define-member (person "Mark H Weaver"
-                       "mhw <at> netris.org")
+                       "mhw <at> netris.org"
+                       "mhw")
   mozilla)
 
 (define-member (person "Adam Faiz"
@@ -829,7 +851,8 @@ (define-member (person "Laurent Gatto"
   r)
 
 (define-member (person "Nicolas Goaziou"
-                       "guix <at> nicolasgoaziou.fr")
+                       "guix <at> nicolasgoaziou.fr"
+                       "ngz")
   tex)
 
 (define-member (person "André Batista"
@@ -837,15 +860,18 @@ (define-member (person "André Batista"
   mozilla)
 
 (define-member (person "Janneke Nieuwenhuizen"
-                       "janneke <at> gnu.org")
+                       "janneke <at> gnu.org"
+                       "janneke")
   bootstrap core-packages home hurd installer)
 
 (define-member (person "Ian Eure"
-                       "ian <at> retrospec.tv")
+                       "ian <at> retrospec.tv"
+                       "ieure")
   mozilla emacs)
 
 (define-member (person "Zheng Junjie"
-                       "z572 <at> z572.online")
+                       "z572 <at> z572.online"
+                       "z572")
   core-packages qt kde)
 
 (define-member (person "Sughosha"
@@ -853,7 +879,8 @@ (define-member (person "Sughosha"
   kde)
 
 (define-member (person "Jelle Licht"
-                       "jlicht <at> fsfe.org")
+                       "jlicht <at> fsfe.org"
+                       "jlicht")
   javascript)
 
 (define-member (person "Cayetano Santos"
@@ -861,11 +888,13 @@ (define-member (person "Cayetano Santos"
   emacs electronics)
 
 (define-member (person "Greg Hogan"
-                       "code <at> greghogan.com")
+                       "code <at> greghogan.com"
+                       "greghogan")
   c++)
 
 (define-member (person "Hilton Chain"
-                       "hako <at> ultrarare.space")
+                       "hako <at> ultrarare.space"
+                       "hako")
   emacs home localization mozilla rust zig)
 
 (define-member (person "Noé Lopez"
-- 
2.49.0





This bug report was last modified today.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.