]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
update ghub
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Wed, 24 Dec 2025 12:42:09 +0000 (13:42 +0100)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Wed, 24 Dec 2025 13:54:56 +0000 (14:54 +0100)
21 files changed:
elpa/ghub-20250509.1440/.dir-locals.el [deleted file]
elpa/ghub-20250509.1440/buck.el [deleted file]
elpa/ghub-20250509.1440/dir [deleted file]
elpa/ghub-20250509.1440/ghub-autoloads.el [deleted file]
elpa/ghub-20250509.1440/ghub-graphql.el [deleted file]
elpa/ghub-20250509.1440/ghub-pkg.el [deleted file]
elpa/ghub-20250509.1440/ghub.el [deleted file]
elpa/ghub-20250509.1440/ghub.info [deleted file]
elpa/ghub-20250509.1440/glab.el [deleted file]
elpa/ghub-20250509.1440/gogs.el [deleted file]
elpa/ghub-20250509.1440/gsexp.el [deleted file]
elpa/ghub-20250509.1440/gtea.el [deleted file]
elpa/ghub-20251130.1842/.dir-locals.el [new file with mode: 0644]
elpa/ghub-20251130.1842/dir [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub-autoloads.el [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub-graphql.el [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub-legacy.el [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub-pkg.el [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub.el [new file with mode: 0644]
elpa/ghub-20251130.1842/ghub.info [new file with mode: 0644]
elpa/ghub-20251130.1842/gsexp.el [new file with mode: 0644]

diff --git a/elpa/ghub-20250509.1440/.dir-locals.el b/elpa/ghub-20250509.1440/.dir-locals.el
deleted file mode 100644 (file)
index aff6808..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-((nil
-  (indent-tabs-mode . nil))
- (makefile-mode
-  (indent-tabs-mode . t))
- (git-commit-mode
-  (git-commit-major-mode . git-commit-elisp-text-mode))
- ("CHANGELOG"
-  (nil (fill-column . 70)
-       (mode . display-fill-column-indicator))))
diff --git a/elpa/ghub-20250509.1440/buck.el b/elpa/ghub-20250509.1440/buck.el
deleted file mode 100644 (file)
index 0a56a10..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-;;; buck.el --- Client library for the Bitbucket API  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Buck is a library that provides basic support for using the Bitbucket API
-;; from Emacs packages.  It abstracts access to API resources using only
-;; a handful of functions that are not resource-specific.
-
-;; This library is implemented on top of Ghub.  Unlike Ghub, Buck does
-;; not support the guided creation of tokens because Bitbucket lacks the
-;; features that would be necessary to implement that.  Users have to
-;; create tokens through the web interface.
-
-;;; Code:
-
-(require 'ghub)
-
-(defconst buck-default-host "api.bitbucket.org/2.0"
-  "The default host that is used if `buck.host' is not set.")
-
-;; HEAD and PATCH are not supported according to
-;; https://developer.atlassian.com/bitbucket/api/2/reference/meta/uri-uuid
-
-(cl-defun buck-get (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `GET' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"GET\" as METHOD
-and `bitbucket' as FORGE."
-  (declare (obsolete ghub-get "4.3.1"))
-  (ghub-request "GET" resource params :forge 'bitbucket
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun buck-put (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PUT\" as METHOD
-and `bitbucket' as FORGE."
-  (declare (obsolete ghub-put "4.3.1"))
-  (ghub-request "PUT" resource params :forge 'bitbucket
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun buck-post (resource &optional params
-                              &key query payload headers
-                              silent unpaginate noerror reader
-                              username auth host
-                              callback errorback extra)
-  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"POST\" as METHOD
-and `bitbucket' as FORGE."
-  (declare (obsolete ghub-post "4.3.1"))
-  (ghub-request "POST" resource params :forge 'bitbucket
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun buck-delete (resource &optional params
-                                &key query payload headers
-                                silent unpaginate noerror reader
-                                username auth host
-                                callback errorback extra)
-  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"DELETE\" as METHOD
-and `bitbucket' as FORGE."
-  (declare (obsolete ghub-delete "4.3.1"))
-  (ghub-request "DELETE" resource params :forge 'bitbucket
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun buck-request (method resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a request for RESOURCE and return the response body.
-Like calling `ghub-request' (which see) with `bitbucket' as FORGE."
-  (declare (obsolete ghub-request "4.3.1"))
-  (ghub-request method resource params :forge 'bitbucket
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun buck-repository-id (owner name &key username auth host)
-  "Return the id of the repository specified by OWNER, NAME and HOST."
-  (substring (cdr (assq 'uuid
-                        (ghub-get (format "/repositories/%s/%s" owner name)
-                                  nil :forge 'bitbucket
-                                  :username username :auth auth :host host)))
-             1 -1))
-
-;;; _
-(provide 'buck)
-;;; buck.el ends here
diff --git a/elpa/ghub-20250509.1440/dir b/elpa/ghub-20250509.1440/dir
deleted file mode 100644 (file)
index b703bca..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This is the file .../info/dir, which contains the
-topmost node of the Info hierarchy, called (dir)Top.
-The first time you invoke Info you start off looking at this node.
-\1f
-File: dir,     Node: Top       This is the top of the INFO tree
-
-  This (the Directory node) gives a menu of major topics.
-  Typing "q" exits, "H" lists all Info commands, "d" returns here,
-  "h" gives a primer for first-timers,
-  "mEmacs<Return>" visits the Emacs manual, etc.
-
-  In Emacs, you can click mouse button 2 on a menu item or cross reference
-  to select it.
-
-* Menu:
-
-Emacs
-* Ghub: (ghub).                 Client library for the Github API.
diff --git a/elpa/ghub-20250509.1440/ghub-autoloads.el b/elpa/ghub-20250509.1440/ghub-autoloads.el
deleted file mode 100644 (file)
index 68d71a6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-;;; ghub-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
-;; Generated by the `loaddefs-generate' function.
-
-;; This file is part of GNU Emacs.
-
-;;; Code:
-
-(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
-
-
-\f
-;;; Generated autoloads from buck.el
-
-(register-definition-prefixes "buck" '("buck-default-host"))
-
-\f
-;;; Generated autoloads from ghub.el
-
-(autoload 'ghub-clear-caches "ghub" "\
-Clear all caches that might negatively affect Ghub.
-
-If a library that is used by Ghub caches incorrect information
-such as a mistyped password, then that can prevent Ghub from
-asking the user for the correct information again.
-
-Set `url-http-real-basic-auth-storage' to nil
-and call `auth-source-forget+'." t)
-(register-definition-prefixes "ghub" '("ghub-"))
-
-\f
-;;; Generated autoloads from ghub-graphql.el
-
-(register-definition-prefixes "ghub-graphql" '("ghub-"))
-
-\f
-;;; Generated autoloads from glab.el
-
-(register-definition-prefixes "glab" '("glab-default-host"))
-
-\f
-;;; Generated autoloads from gogs.el
-
-(register-definition-prefixes "gogs" '("gogs-default-host"))
-
-\f
-;;; Generated autoloads from gsexp.el
-
-(register-definition-prefixes "gsexp" '("gsexp-"))
-
-\f
-;;; Generated autoloads from gtea.el
-
-(register-definition-prefixes "gtea" '("gtea-default-host"))
-\f
-;;; End of scraped data
-
-(provide 'ghub-autoloads)
-
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; no-native-compile: t
-;; coding: utf-8-emacs-unix
-;; End:
-
-;;; ghub-autoloads.el ends here
diff --git a/elpa/ghub-20250509.1440/ghub-graphql.el b/elpa/ghub-20250509.1440/ghub-graphql.el
deleted file mode 100644 (file)
index a4ffb7d..0000000
+++ /dev/null
@@ -1,705 +0,0 @@
-;;; ghub-graphql.el --- Access Github API using GraphQL  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This library implements GraphQL queries for Github.
-
-;;; Code:
-
-(require 'ghub)
-(require 'gsexp)
-(require 'treepy)
-
-(eval-when-compile (require 'subr-x))
-
-(define-error 'ghub-graphql-error "GraphQL Error" 'ghub-error)
-
-;;; Settings
-
-(defvar ghub-graphql-message-progress nil
-  "Whether to show \"Fetching page N...\" in echo area during requests.
-By default this information is only shown in the mode-line of the buffer
-from which the request was initiated, and if you kill that buffer, then
-nowhere.  That may make it desirable to display the same message in the
-echo area as well.")
-
-(defvar ghub-graphql-items-per-request 50
-  "Number of GraphQL items to query for entities that return a collection.
-
-Adjust this value if you're hitting query timeouts against larger
-repositories.")
-
-;;; Mutations
-
-(cl-defun ghub-graphql (graphql
-                        &optional variables
-                        &key username auth host forge
-                        headers silent
-                        callback errorback value extra)
-  "Make a GraphQL request using GRAPHQL and VARIABLES.
-Return the response as a JSON-like alist.  Even if the response
-contains `errors', do not raise an error.  GRAPHQL is a GraphQL
-string.  VARIABLES is a JSON-like alist.  The other arguments
-behave as for `ghub-request' (which see)."
-  (cl-assert (not (stringp variables)))
-  (cl-assert (or (stringp graphql)
-                 (memq (car-safe graphql) '(query mutation))))
-  (unless (stringp graphql)
-    (setq graphql (gsexp-encode (ghub--graphql-prepare-query graphql))))
-  (ghub-request "POST"
-                (if (eq forge 'gitlab) "/api/graphql" "/graphql")
-                nil
-                :payload `((query . ,graphql)
-                           ,@(and variables `((variables ,@variables))))
-                :headers headers :silent silent
-                :username username :auth auth :host host :forge forge
-                :callback callback :errorback errorback
-                :extra extra :value value))
-
-(cl-defun ghub--graphql (graphql
-                         &optional variables
-                         &key username auth host forge
-                         headers
-                         callback errorback)
-  "An experimental and unfinished replacement for `ghub-graphql'."
-  (let ((ghub-graphql-message-progress nil))
-    (ghub--graphql-vacuum graphql variables callback nil
-                          :username  username
-                          :auth      auth
-                          :host      host
-                          :forge     forge
-                          :headers   headers
-                          :errorback errorback)))
-
-;;; Queries
-
-(cl-defun ghub-graphql-rate-limit (&key username auth host)
-  "Return rate limit information."
-  (let-alist (ghub-graphql
-              '(query (rateLimit limit cost remaining resetAt))
-              nil :username username :auth auth :host host)
-    .data.rateLimit))
-
-(defconst ghub-fetch-repository-sparse
-  '(query
-    (repository
-     [(owner $owner String!)
-      (name  $name  String!)]
-     name
-     id
-     createdAt
-     updatedAt
-     nameWithOwner
-     (parent nameWithOwner)
-     description
-     homepageUrl
-     (defaultBranchRef name)
-     isArchived
-     isFork
-     isLocked
-     isMirror
-     isPrivate
-     hasDiscussionsEnabled
-     hasIssuesEnabled
-     hasWikiEnabled
-     (licenseInfo name)
-     (stargazers totalCount)
-     (watchers totalCount))))
-
-(defconst ghub-fetch-repository
-  `(query
-    (repository
-     ,@(cdr (cadr ghub-fetch-repository-sparse))
-     (assignableUsers [(:edges t)]
-                      id
-                      login
-                      name)
-     (discussionCategories [(:edges t)]
-                            id
-                            name
-                            emoji
-                            isAnswerable
-                            description)
-     (discussions    [(:edges t)
-                      (:singular discussion number)
-                      (orderBy ((field UPDATED_AT) (direction DESC)))]
-                     id
-                     databaseId
-                     number
-                     url
-                     stateReason
-                     ;; Discussions lack isReadByViewer.
-                     (answer id)
-                     (author login)
-                     title
-                     createdAt
-                     updatedAt
-                     closedAt
-                     locked
-                     (category id)
-                     body
-                     (comments  [(:edges t)]
-                                id
-                                databaseId
-                                (author login)
-                                createdAt
-                                updatedAt
-                                body
-                                (replies [(:edges 20)]
-                                         id
-                                         databaseId
-                                         (author login)
-                                         createdAt
-                                         updatedAt
-                                         body))
-                     (labels    [(:edges t)]
-                                id))
-     (issues         [(:edges t)
-                      (:singular issue number)
-                      (orderBy ((field UPDATED_AT) (direction DESC)))]
-                     number
-                     id
-                     state
-                     stateReason
-                     isReadByViewer
-                     (author login)
-                     title
-                     createdAt
-                     updatedAt
-                     closedAt
-                     locked
-                     (milestone id)
-                     body
-                     (assignees [(:edges t)]
-                                id)
-                     (comments  [(:edges t)]
-                                id
-                                databaseId
-                                (author login)
-                                createdAt
-                                updatedAt
-                                body)
-                     (labels    [(:edges t)]
-                                id))
-     (labels         [(:edges t)
-                      (:singular label id)]
-                     id
-                     name
-                     color
-                     description)
-     (milestones     [(:edges t)
-                      (:singular milestone id)]
-                     id
-                     number
-                     title
-                     createdAt
-                     updatedAt
-                     dueOn
-                     closedAt
-                     description)
-     (pullRequests   [(:edges t)
-                      (:singular pullRequest number)
-                      (orderBy ((field UPDATED_AT) (direction DESC)))]
-                     number
-                     id
-                     state
-                     isReadByViewer
-                     (author login)
-                     title
-                     createdAt
-                     updatedAt
-                     closedAt
-                     mergedAt
-                     isDraft
-                     locked
-                     maintainerCanModify
-                     isCrossRepository
-                     (milestone id)
-                     body
-                     (baseRef name
-                              (repository nameWithOwner))
-                     baseRefOid
-                     (headRef name
-                              (repository (owner login)
-                                          nameWithOwner))
-                     headRefOid
-                     (assignees [(:edges t)]
-                                id)
-                     (reviewRequests [(:edges t)]
-                                     (requestedReviewer "... on User { id }\n"))
-                     (comments  [(:edges t)]
-                                id
-                                databaseId
-                                (author login)
-                                createdAt
-                                updatedAt
-                                body)
-                     (labels    [(:edges t)]
-                                id)))))
-
-(defconst ghub-fetch-repository-review-threads
-  '(query
-    (repository
-     [(owner $owner String!)
-      (name  $name  String!)]
-     (pullRequests   [(:edges t)
-                      (:singular pullRequest number)
-                      (orderBy ((field UPDATED_AT) (direction DESC)))]
-                     number
-                     baseRefOid
-                     headRefOid
-                     (reviewThreads [(:edges t)]
-                                    id
-                                    line
-                                    originalLine
-                                    diffSide
-                                    (resolvedBy login)
-                                    (comments [(:edges t)]
-                                              id
-                                              databaseId
-                                              (author login)
-                                              createdAt
-                                              updatedAt
-                                              body
-                                              (replyTo databaseId)
-                                              (originalCommit oid)
-                                              path))))))
-
-(cl-defun ghub-fetch-repository ( owner name callback
-                                  &optional until
-                                  &key username auth host forge
-                                  headers paginate errorback sparse)
-  "Asynchronously fetch forge data about the specified repository.
-Once all data has been collected, CALLBACK is called with the
-data as the only argument."
-  (ghub--graphql-vacuum (if sparse
-                            ghub-fetch-repository-sparse
-                          ghub-fetch-repository)
-                        `((owner . ,owner)
-                          (name  . ,name))
-                        callback until
-                        :narrow   '(repository)
-                        :username username
-                        :auth     auth
-                        :host     host
-                        :forge    forge
-                        :headers  headers
-                        :paginate paginate
-                        :errorback errorback))
-
-(cl-defun ghub-fetch-discussion ( owner name number callback
-                                  &optional until
-                                  &key username auth host forge
-                                  headers errorback)
-  "Asynchronously fetch forge data about the specified discussion.
-Once all data has been collected, CALLBACK is called with the
-data as the only argument."
-  (ghub--graphql-vacuum (ghub--graphql-prepare-query
-                         ghub-fetch-repository
-                         `(repository discussions (discussion . ,number)))
-                        `((owner . ,owner)
-                          (name  . ,name))
-                        callback until
-                        :narrow   '(repository discussion)
-                        :username username
-                        :auth     auth
-                        :host     host
-                        :forge    forge
-                        :headers  headers
-                        :errorback errorback))
-
-(cl-defun ghub-fetch-issue ( owner name number callback
-                             &optional until
-                             &key username auth host forge
-                             headers paginate errorback)
-  "Asynchronously fetch forge data about the specified issue.
-Once all data has been collected, CALLBACK is called with the
-data as the only argument."
-  (ghub--graphql-vacuum (ghub--graphql-narrow-query
-                         ghub-fetch-repository
-                         `(repository issues (issue . ,number)))
-                        `((owner . ,owner)
-                          (name  . ,name))
-                        callback until
-                        :narrow   '(repository issue)
-                        :username username
-                        :auth     auth
-                        :host     host
-                        :forge    forge
-                        :headers  headers
-                        :paginate paginate
-                        :errorback errorback))
-
-(cl-defun ghub-fetch-pullreq ( owner name number callback
-                               &optional until
-                               &key username auth host forge
-                               headers paginate errorback)
-  "Asynchronously fetch forge data about the specified pull-request.
-Once all data has been collected, CALLBACK is called with the
-data as the only argument."
-  (ghub--graphql-vacuum (ghub--graphql-narrow-query
-                         ghub-fetch-repository
-                         `(repository pullRequests (pullRequest . ,number)))
-                        `((owner . ,owner)
-                          (name  . ,name))
-                        callback until
-                        :narrow   '(repository pullRequest)
-                        :username username
-                        :auth     auth
-                        :host     host
-                        :forge    forge
-                        :headers  headers
-                        :paginate paginate
-                        :errorback errorback))
-
-(cl-defun ghub-fetch-review-threads ( owner name number callback
-                                      &optional until
-                                      &key username auth host forge
-                                      headers paginate errorback)
-  "Asynchronously fetch forge data about the review threads from a pull-request.
-Once all data has been collected, CALLBACK is called with the
-data as the only argument."
-  (ghub--graphql-vacuum (ghub--graphql-narrow-query
-                         ghub-fetch-repository-review-threads
-                         `(repository pullRequests (pullRequest . ,number)))
-                        `((owner . ,owner)
-                          (name  . ,name))
-                        callback until
-                        :narrow   '(repository pullRequest)
-                        :username username
-                        :auth     auth
-                        :host     host
-                        :forge    forge
-                        :headers  headers
-                        :paginate paginate
-                        :errorback errorback))
-
-;;; Internal
-
-(cl-defstruct (ghub--graphql-req
-               (:include ghub--req)
-               (:constructor ghub--make-graphql-req)
-               (:copier nil))
-  (query     nil :read-only t)
-  (query-str nil :read-only nil)
-  (variables nil :read-only t)
-  (until     nil :read-only t)
-  (pages     0   :read-only nil)
-  (paginate  nil :read-only nil)
-  (narrow    nil :read-only t))
-
-(cl-defun ghub--graphql-vacuum ( query variables callback
-                                 &optional until
-                                 &key narrow username auth host forge
-                                 headers paginate errorback)
-  "Make a GraphQL request using QUERY and VARIABLES.
-See Info node `(ghub)GraphQL Support'."
-  (unless host
-    (setq host (ghub--host forge)))
-  (unless (or username (stringp auth) (eq auth 'none))
-    (setq username (ghub--username host forge)))
-  (ghub--graphql-retrieve
-   (ghub--make-graphql-req
-    :url       (url-generic-parse-url
-                (format "https://%s/graphql"
-                        (if (string-suffix-p "/v3" host)
-                            (substring host 0 -3)
-                          host)))
-    :method    "POST"
-    :headers   (ghub--headers headers host auth username forge)
-    :handler   #'ghub--graphql-handle-response
-    :query     query
-    :variables variables
-    :until     until
-    :buffer    (current-buffer)
-    :narrow    narrow
-    :paginate  (or paginate
-                   (and-let* ((p (and (eq auth 'forge)
-                                      (fboundp 'magit-get)
-                                      (magit-get "forge.graphqlItemLimit"))))
-                     (string-to-number p)))
-    :callback  (and (not (eq callback 'synchronous)) callback)
-    :errorback (and (not (eq callback 'synchronous)) errorback))))
-
-(defvar ghub--graphql-synchronous-value nil)
-
-(cl-defun ghub--graphql-synchronous ( query variables
-                                      &optional until
-                                      &key narrow username auth host forge
-                                      headers paginate)
-  "Make a synchronous GraphQL request using QUERY and VARIABLES.
-See Info node `(ghub)GraphQL Support'."
-  (unwind-protect
-      (progn (ghub--graphql-vacuum query variables 'synchronous until
-                                   :narrow narrow :username username
-                                   :auth auth :host host :forge forge
-                                   :headers headers :paginate paginate)
-             ghub--graphql-synchronous-value)
-    (setq ghub--graphql-synchronous-value nil)))
-
-(cl-defun ghub--graphql-retrieve (req &optional lineage cursor)
-  (let ((p (cl-incf (ghub--graphql-req-pages req))))
-    (when ghub-graphql-message-progress
-      (let ((message-log-max nil))
-        (message "Fetching page %s..." p)))
-    (when (> p 1)
-      (ghub--graphql-set-mode-line req "Fetching page %s" p)))
-  (setf (ghub--graphql-req-query-str req)
-        (gsexp-encode
-         (ghub--graphql-prepare-query
-          (ghub--graphql-req-query req)
-          lineage cursor)))
-  (when ghub-debug
-    (with-current-buffer (get-buffer-create " *gsexp-encode*")
-      (erase-buffer)
-      (insert (ghub--graphql-req-query-str req) "\n\n")
-      (let ((pos (point)))
-        (insert (ghub--encode-payload (ghub--graphql-req-variables req)) "\n")
-        (ignore-errors (json-pretty-print pos (point))))))
-  (ghub--retrieve
-   (let ((json-false nil))
-     (ghub--encode-payload
-      `((query     . ,(ghub--graphql-req-query-str req))
-        (variables . ,(ghub--graphql-req-variables req)))))
-   req))
-
-(defun ghub--graphql-prepare-query (query &optional lineage cursor paginate)
-  (when lineage
-    (setq query (ghub--graphql-narrow-query query lineage cursor)))
-  (let ((loc (ghub--alist-zip query))
-        variables)
-    (cl-block nil
-      (while t
-        (let ((node (treepy-node loc)))
-          (when (and (vectorp node)
-                     (listp (aref node 0)))
-            (let ((alist (cl-coerce node 'list))
-                  vars)
-              (when-let ((edges (cadr (assq :edges alist))))
-                (push (list 'first
-                            (apply
-                             #'min
-                             (delq nil (list (and (numberp edges) edges)
-                                             paginate
-                                             ghub-graphql-items-per-request))))
-                      vars)
-                (setq loc  (treepy-up loc))
-                (setq node (treepy-node loc))
-                (setq loc  (treepy-replace
-                            loc `(,(car  node)
-                                  ,(cadr node)
-                                  (pageInfo endCursor hasNextPage)
-                                  (edges (node ,@(cddr node))))))
-                (setq loc  (treepy-down loc))
-                (setq loc  (treepy-next loc)))
-              (dolist (elt alist)
-                (cond ((keywordp (car elt)))
-                      ((length= elt 3)
-                       (push (list (nth 0 elt) (nth 1 elt)) vars)
-                       (push (list (nth 1 elt) (nth 2 elt)) variables))
-                      ((length= elt 2)
-                       (push elt vars))))
-              (setq loc (treepy-replace loc (vconcat (nreverse vars)))))))
-        (if (treepy-end-p loc)
-            (let ((node (copy-sequence (treepy-node loc))))
-              (when variables
-                (push (cl-coerce variables 'vector)
-                      (cdr node)))
-              (cl-return node))
-          (setq loc (treepy-next loc)))))))
-
-(defun ghub--graphql-handle-response (status req)
-  (let ((buf (current-buffer)))
-    (unwind-protect
-        (progn
-          (set-buffer-multibyte t)
-          (let* ((headers (ghub--handle-response-headers status req))
-                 (payload (ghub--handle-response-payload req))
-                 (payload (ghub--handle-response-error status payload req))
-                 (err     (plist-get status :error))
-                 (errors  (cdr (assq 'errors payload)))
-                 (errors  (and errors (cons 'ghub-graphql-error errors))))
-            (cond ((or err errors)
-                   (when (and (not err) ghub-debug)
-                     (ignore-errors (json-pretty-print (point) (point-max)))
-                     (pop-to-buffer buf))
-                   (ghub--graphql-handle-failure
-                    req (or err errors) headers status))
-                  ((ghub--graphql-walk-response req (assq 'data payload))))))
-      (when (and (buffer-live-p buf)
-                 (not (buffer-local-value 'ghub-debug buf)))
-        (kill-buffer buf)))))
-
-(defun ghub--graphql-handle-failure (req errors headers status)
-  (if-let ((errorback (ghub--req-errorback req)))
-      (let ((buffer (ghub--req-buffer req)))
-        (with-current-buffer
-            (if (buffer-live-p buffer) buffer (current-buffer))
-          (funcall errorback errors headers status req)))
-    (ghub--signal-error errors)))
-
-(defun ghub--graphql-handle-success (req data)
-  (let ((callback (ghub--req-callback req))
-        (buffer   (ghub--req-buffer req))
-        (narrow   (ghub--graphql-req-narrow req)))
-    (while-let ((key (pop narrow)))
-      (setq data (cdr (assq key data))))
-    (with-current-buffer
-        (if (buffer-live-p buffer) buffer (current-buffer))
-      (funcall (or callback #'ghub--graphql-pp-response)
-               data))))
-
-(defun ghub--graphql-walk-response (req data)
-  (let* ((loc (ghub--req-value req))
-         (loc (if (not loc)
-                  (ghub--alist-zip data)
-                (setq data (ghub--graphql-narrow-data
-                            data (ghub--graphql-lineage loc)))
-                (setf (alist-get 'edges data)
-                      (append (alist-get 'edges (treepy-node loc))
-                              (or (alist-get 'edges data)
-                                  (error "BUG: Expected new nodes"))))
-                (treepy-replace loc data))))
-    (cl-block nil
-      (while t
-        (when (eq (car-safe (treepy-node loc)) 'edges)
-          (setq loc (treepy-up loc))
-          (pcase-let ((`(,key . ,val) (treepy-node loc)))
-            (let-alist val
-              (let* ((cursor (and .pageInfo.hasNextPage
-                                  .pageInfo.endCursor))
-                     (until  (cdr (assq (intern (format "%s-until" key))
-                                        (ghub--graphql-req-until req))))
-                     (nodes  (mapcar #'cdar .edges))
-                     (nodes  (if until
-                                 (seq-take-while
-                                  (lambda (node)
-                                    (or (string> (cdr (assq 'updatedAt node))
-                                                 until)
-                                        (setq cursor nil)))
-                                  nodes)
-                               nodes)))
-                (cond (cursor
-                       (setf (ghub--req-value req) loc)
-                       (ghub--graphql-retrieve req
-                                               (ghub--graphql-lineage loc)
-                                               cursor)
-                       (cl-return))
-                      ((setq loc (treepy-replace loc (cons key nodes)))))))))
-        (cond ((not (treepy-end-p loc))
-               (setq loc (treepy-next loc)))
-              ((ghub--req-callback req)
-               (ghub--graphql-handle-success req (treepy-root loc))
-               (ghub--graphql-set-mode-line req nil)
-               (cl-return))
-              (t
-               (setq ghub--graphql-synchronous-value (treepy-root loc))
-               (cl-return)))))))
-
-(defun ghub--graphql-lineage (loc)
-  (let (lineage)
-    (while (treepy-up loc)
-      (push (car (treepy-node loc)) lineage)
-      (setq loc (treepy-up loc)))
-    lineage))
-
-(defun ghub--graphql-narrow-data (data lineage)
-  (while-let ((key (pop lineage)))
-    (if (consp (car lineage))
-        (progn (pop lineage)
-               (setf data (cadr data)))
-      (setq data (assq key (cdr data)))))
-  data)
-
-(defun ghub--graphql-narrow-query (query lineage &optional cursor)
-  (if (consp (car lineage))
-      (let* ((child  (cddr query))
-             (alist  (cl-coerce (cadr query) 'list))
-             (single (cdr (assq :singular alist))))
-        `(,(car single)
-          ,(vector (list (cadr single) (cdr (car lineage))))
-          ,@(if (cdr lineage)
-                (ghub--graphql-narrow-query child (cdr lineage) cursor)
-              child)))
-    (let* ((child  (or (assq (car lineage) (cdr query))
-                       ;; Alias
-                       (cl-find-if (lambda (c)
-                                     (eq (car-safe (car-safe c))
-                                         (car lineage)))
-                                   query)
-                       ;; Edges
-                       (cl-find-if (lambda (c)
-                                     (and (listp c)
-                                          (vectorp (cadr c))
-                                          (eq (cadr (assq :singular
-                                                          (cl-coerce (cadr c)
-                                                                     'list)))
-                                              (car lineage))))
-                                   (cdr query))
-                       (error "BUG: Failed to narrow query")))
-           (object (car query))
-           (args   (and (vectorp (cadr query))
-                        (cadr query))))
-      `(,object
-        ,@(and args (list args))
-        ,(cond ((cdr lineage)
-                (ghub--graphql-narrow-query child (cdr lineage) cursor))
-               (cursor
-                `(,(car child)
-                  ,(vconcat `((after ,cursor))
-                            (cadr child))
-                  ,@(cddr child)))
-               (t
-                child))))))
-
-(defun ghub--alist-zip (root)
-  (let ((branchp (##and (listp %) (listp (cdr %))))
-        (make-node (lambda (_ children) children)))
-    (treepy-zipper branchp #'identity make-node root)))
-
-(defun ghub--graphql-set-mode-line (req string &rest args)
-  (let ((buffer (ghub--graphql-req-buffer req)))
-    (when (buffer-live-p buffer)
-      (with-current-buffer buffer
-        (setq mode-line-process
-              (and string (concat " " (apply #'format string args))))
-        (force-mode-line-update t)))))
-
-(defun ghub--graphql-pp-response (data)
-  (pp-display-expression data "*Pp Eval Output*"))
-
-(cl-defun ghub--repository-id (owner name &key username auth host)
-  "Return the id of the repository specified by OWNER, NAME and HOST."
-  (let-alist (ghub-graphql
-              '(query (repository [(owner $owner String!)
-                                   (name  $name  String!)]
-                                  id))
-              `((owner . ,owner)
-                (name  . ,name))
-              :username username :auth auth :host host)
-    .data.repository.id))
-
-;;; _
-(provide 'ghub-graphql)
-;;; ghub-graphql.el ends here
diff --git a/elpa/ghub-20250509.1440/ghub-pkg.el b/elpa/ghub-20250509.1440/ghub-pkg.el
deleted file mode 100644 (file)
index 1c10d3a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-;; -*- no-byte-compile: t; lexical-binding: nil -*-
-(define-package "ghub" "20250509.1440"
-  "Client libraries for Git forge APIs."
-  '((emacs     "29.1")
-    (compat    "30.1.0.0")
-    (let-alist "1.0.6")
-    (llama     "0.6.2")
-    (treepy    "0.1.2"))
-  :url "https://github.com/magit/ghub"
-  :commit "6bb612e7b7eada22569d84cc529f4ca36e08032d"
-  :revdesc "6bb612e7b7ea"
-  :keywords '("tools")
-  :authors '(("Jonas Bernoulli" . "emacs.ghubNOSPAMjonas.bernoulli.dev"))
-  :maintainers '(("Jonas Bernoulli" . "emacs.ghubNOSPAMjonas.bernoulli.dev")))
diff --git a/elpa/ghub-20250509.1440/ghub.el b/elpa/ghub-20250509.1440/ghub.el
deleted file mode 100644 (file)
index f56484e..0000000
+++ /dev/null
@@ -1,826 +0,0 @@
-;;; ghub.el --- Client libraries for Git forge APIs  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; Package-Version: 20250509.1440
-;; Package-Revision: 6bb612e7b7ea
-;; Package-Requires: (
-;;     (emacs "29.1")
-;;     (compat "30.1.0.0")
-;;     (let-alist "1.0.6")
-;;     (llama "0.6.2")
-;;     (treepy "0.1.2"))
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Ghub provides basic support for using the APIs of various Git forges
-;; from Emacs packages.  Originally it only supported the Github REST
-;; API, but now it also supports the Github GraphQL API as well as the
-;; REST APIs of Gitlab, Gitea, Gogs and Bitbucket.
-
-;; Ghub abstracts access to API resources using only a handful of basic
-;; functions such as `ghub-get'.  These are convenience wrappers around
-;; `ghub-request'.  Additional forge-specific wrappers like `glab-put',
-;; `gtea-put', `gogs-post' and `buck-delete' are also available.  Ghub
-;; does not provide any resource-specific functions, with the exception
-;; of `FORGE-repository-id'.
-
-;; When accessing Github, then Ghub handles the creation and storage of
-;; access tokens using a setup wizard to make it easier for users to get
-;; started.  The tokens for other forges have to be created manually.
-
-;; Ghub is intentionally limited to only provide these two essential
-;; features — basic request functions and guided setup — to avoid being
-;; too opinionated, which would hinder wide adoption.  It is assumed that
-;; wide adoption would make life easier for users and maintainers alike,
-;; because then all packages that talk to forge APIs could be configured
-;; the same way.
-
-;; Please consult the manual (info "ghub") for more information.
-
-;;; Code:
-
-(require 'auth-source)
-(require 'cl-lib)
-(require 'compat)
-(require 'gnutls)
-(require 'let-alist)
-(require 'llama)
-(require 'url)
-(require 'url-auth)
-(require 'url-http)
-
-(eval-when-compile (require 'subr-x))
-
-(declare-function glab-repository-id "glab" (owner name &key username auth host))
-(declare-function gtea-repository-id "gtea" (owner name &key username auth host))
-(declare-function gogs-repository-id "gogs" (owner name &key username auth host))
-(declare-function buck-repository-id "buck" (owner name &key username auth host))
-
-(defvar url-callback-arguments)
-(defvar url-http-end-of-headers)
-(defvar url-http-extra-headers)
-(defvar url-http-response-status)
-
-;;; Settings
-
-(defconst ghub-default-host "api.github.com"
-  "The default host that is used if `ghub.host' is not set.")
-
-(defvar ghub-github-token-scopes '(repo)
-  "The Github API scopes that your private tools need.
-
-You have to manually create or update the token at
-https://github.com/settings/tokens.  This variable
-only serves as documentation.")
-
-(defvar ghub-insecure-hosts nil
-  "List of hosts that use http instead of https.")
-
-(defvar ghub-debug nil
-  "Record additional debug information.")
-
-;;; Request
-;;;; Object
-
-(cl-defstruct (ghub--req
-               (:constructor ghub--make-req)
-               (:copier nil))
-  (url        nil :read-only nil)
-  (forge      nil :read-only t)
-  (silent     nil :read-only t)
-  (method     nil :read-only t)
-  (headers    nil :read-only t)
-  (handler    nil :read-only t)
-  (unpaginate nil :read-only nil)
-  (noerror    nil :read-only t)
-  (reader     nil :read-only t)
-  (buffer     nil :read-only t)
-  (callback   nil :read-only t)
-  (errorback  nil :read-only t)
-  (value      nil :read-only nil)
-  (extra      nil :read-only nil))
-
-(defalias 'ghub-req-extra #'ghub--req-extra)
-
-;;;; API
-
-(define-error 'ghub-error "Ghub/Url Error" 'error)
-(define-error 'ghub-http-error "HTTP Error" 'ghub-error)
-
-(defvar ghub-response-headers nil
-  "The headers returned in response to the last request.
-`ghub-request' returns the response body and stores the
-response headers in this variable.")
-
-(cl-defun ghub-head (resource
-                     &optional params
-                     &key query payload headers
-                     silent unpaginate noerror reader
-                     username auth host
-                     callback errorback extra)
-  "Make a `HEAD' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"HEAD\" as METHOD."
-  (ghub-request "HEAD" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-get (resource
-                    &optional params
-                    &key query payload headers
-                    silent unpaginate noerror reader
-                    username auth host
-                    callback errorback extra)
-  "Make a `GET' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"GET\" as METHOD."
-  (ghub-request "GET" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-put (resource
-                    &optional params
-                    &key query payload headers
-                    silent unpaginate noerror reader
-                    username auth host
-                    callback errorback extra)
-  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PUT\" as METHOD."
-  (ghub-request "PUT" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-post (resource
-                     &optional params
-                     &key query payload headers
-                     silent unpaginate noerror reader
-                     username auth host
-                     callback errorback extra)
-  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"POST\" as METHOD."
-  (ghub-request "POST" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-patch (resource
-                      &optional params
-                      &key query payload headers
-                      silent unpaginate noerror reader
-                      username auth host
-                      callback errorback extra)
-  "Make a `PATCH' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PATCH\" as METHOD."
-  (ghub-request "PATCH" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-delete (resource
-                       &optional params
-                       &key query payload headers
-                       silent unpaginate noerror reader
-                       username auth host
-                       callback errorback extra)
-  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"DELETE\" as METHOD."
-  (ghub-request "DELETE" resource params
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun ghub-request ( method resource
-                         &optional params
-                         &key query payload headers
-                         silent unpaginate noerror reader
-                         username auth host forge
-                         callback errorback value extra)
-  "Make a request for RESOURCE and return the response body.
-
-Also place the response headers in `ghub-response-headers'.
-
-METHOD is the HTTP method, given as a string.
-RESOURCE is the resource to access, given as a string beginning
-  with a slash.
-
-PARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify
-  data.  The Github API documentation is vague on how data has
-  to be transmitted and for a particular resource usually just
-  talks about \"parameters\".  Generally speaking when the METHOD
-  is \"HEAD\" or \"GET\", then they have to be transmitted as a
-  query, otherwise as a payload.
-Use PARAMS to automatically transmit like QUERY or PAYLOAD would
-  depending on METHOD.
-Use QUERY to explicitly transmit data as a query.
-Use PAYLOAD to explicitly transmit data as a payload.
-  Instead of an alist, PAYLOAD may also be a string, in which
-  case it gets encoded as UTF-8 but is otherwise transmitted as-is.
-Use HEADERS for those rare resources that require that the data
-  is transmitted as headers instead of as a query or payload.
-  When that is the case, then the API documentation usually
-  mentions it explicitly.
-
-If SILENT is non-nil, then don't message progress reports and
-  the like.
-
-If UNPAGINATE is t, then make as many requests as necessary to
-  get all values.  If UNPAGINATE is a natural number, then get
-  at most that many pages.  For any other non-nil value raise
-  an error.
-If NOERROR is non-nil, then do not raise an error if the request
-  fails and return nil instead.  If NOERROR is `return', then
-  return the error payload instead of nil.
-If READER is non-nil, then it is used to read and return from the
-  response buffer.  The default is `ghub--read-json-payload'.
-  For the very few resources that do not return JSON, you might
-  want to use `ghub--decode-payload'.
-
-If USERNAME is non-nil, then make a request on behalf of that
-  user.  It is better to specify the user using the Git variable
-  `github.user' for \"api.github.com\", or `github.HOST.user' if
-  connecting to a Github Enterprise instance.
-
-Each package that uses `ghub' should use its own token.  If AUTH
-  is nil, then the generic `ghub' token is used instead.  This
-  is only acceptable for personal utilities.  A packages that
-  is distributed to other users should always use this argument
-  to identify itself, using a symbol matching its name.
-
-  Package authors who find this inconvenient should write a
-  wrapper around this function and possibly for the
-  method-specific functions as well.
-
-  Some symbols have a special meaning.  `none' means to make an
-  unauthorized request.  `basic' means to make a password based
-  request.  If the value is a string, then it is assumed to be
-  a valid token.  `basic' and an explicit token string are only
-  intended for internal and debugging uses.
-
-If HOST is non-nil, then connect to that Github instance.  This
-  defaults to \"api.github.com\".  When a repository is connected
-  to a Github Enterprise instance, then it is better to specify
-  that using the Git variable `github.host' instead of using this
-  argument.
-
-If FORGE is `gitlab', then connect to Gitlab.com or, depending
-  on HOST, to another Gitlab instance.  This is only intended for
-  internal use.  Instead of using this argument you should use
-  function `glab-request' and other `glab-*' functions.
-
-If CALLBACK and/or ERRORBACK is non-nil, then make one or more
-  asynchronous requests and call CALLBACK or ERRORBACK when
-  finished.  If no error occurred, then call CALLBACK, unless
-  that is nil.
-
-  If an error occurred, then call ERRORBACK, or if that is nil,
-  then CALLBACK.  ERRORBACK can also be t, in which case an error
-  is signaled instead.  NOERROR is ignored for all asynchronous
-  requests.
-
-Both callbacks are called with four arguments.
-  1. For CALLBACK, the combined value of the retrieved pages.
-     For ERRORBACK, the error that occurred when retrieving the
-     last page.
-  2. The headers of the last page as an alist.
-  3. Status information provided by `url-retrieve'. Its `:error'
-     property holds the same information as ERRORBACK's first
-     argument.
-  4. A `ghub--req' struct, which can be passed to `ghub-continue'
-     (which see) to retrieve the next page, if any."
-  (cl-assert (or (booleanp unpaginate) (natnump unpaginate)))
-  (unless (string-prefix-p "/" resource)
-    (setq resource (concat "/" resource)))
-  (unless host
-    (setq host (ghub--host forge)))
-  (unless (or username (stringp auth) (eq auth 'none))
-    (setq username (ghub--username host forge)))
-  (cond ((not params))
-        ((member method '("GET" "HEAD"))
-         (when query
-           (error "PARAMS and QUERY are mutually exclusive for METHOD %S"
-                  method))
-         (setq query params))
-        (t
-         (when payload
-           (error "PARAMS and PAYLOAD are mutually exclusive for METHOD %S"
-                  method))
-         (setq payload params)))
-  (when (or callback errorback)
-    (setq noerror t))
-  (ghub--retrieve
-   (ghub--encode-payload payload)
-   (ghub--make-req
-    :url (url-generic-parse-url
-          (concat (if (member host ghub-insecure-hosts) "http://" "https://")
-                  (cond ((and (equal resource "/graphql")
-                              (string-suffix-p "/v3" host))
-                         ;; Needed for some Github Enterprise instances.
-                         (substring host 0 -3))
-                        ((and (equal resource "/api/graphql")
-                              (string-suffix-p "/api/v4" host))
-                         ;; Needed for all Gitlab instances.
-                         (substring host 0 -7))
-                        (host))
-                  resource
-                  (and query (concat "?" (ghub--url-encode-params query)))))
-    :forge forge
-    :silent silent
-    ;; Encode in case caller used (symbol-name 'GET). #35
-    :method     (encode-coding-string method 'utf-8)
-    :headers    (ghub--headers headers host auth username forge)
-    :handler    #'ghub--handle-response
-    :unpaginate unpaginate
-    :noerror    noerror
-    :reader     reader
-    :buffer     (current-buffer)
-    :callback   callback
-    :errorback  errorback
-    :value      value
-    :extra      extra)))
-
-(defun ghub-continue (req)
-  "If there is a next page, then retrieve that.
-
-This function is only intended to be called from callbacks.  If
-there is a next page, then retrieve that and return the buffer
-that the result will be loaded into, or t if the process has
-already completed.  If there is no next page, then return nil.
-
-Callbacks are called with four arguments (see `ghub-request').
-The forth argument is a `ghub--req' struct, intended to be passed
-to this function.  A callback may use the struct's `extra' slot
-to pass additional information to the callback that will be
-called after the next request has finished.  Use the function
-`ghub-req-extra' to get and set the value of this slot."
-  (and (assq 'next (ghub-response-link-relations req))
-       (or (ghub--retrieve nil req) t)))
-
-(cl-defun ghub-wait (resource
-                     &optional duration
-                     &key username auth host forge)
-  "Busy-wait up to DURATION seconds for RESOURCE to become available.
-
-DURATION specifies how many seconds to wait at most.  It defaults
-to 64 seconds.  The first attempt is made immediately, the second
-after two seconds, and each subsequent attempt is made after
-waiting as long again as we already waited between all preceding
-attempts combined.
-
-See `ghub-request' for information about the other arguments."
-  (unless duration
-    (setq duration 64))
-  (with-local-quit
-    (let ((total 0))
-      (while (not (ghub-request "GET" resource nil
-                                :noerror t
-                                :username username
-                                :auth auth
-                                :host host
-                                :forge forge))
-        (message "Waited (%3ss of %ss) for %s..." total duration resource)
-        (if (= total duration)
-            (error "%s is taking too long to create %s"
-                   (if forge (capitalize (symbol-name forge)) "Github")
-                   resource)
-          (if (> total 0)
-              (let ((wait (min total (- duration total))))
-                (sit-for wait)
-                (cl-incf total wait))
-            (sit-for (setq total 2))))))))
-
-(defun ghub-response-link-relations (req &optional headers payload)
-  "Return an alist of link relations in HEADERS.
-If optional HEADERS is nil, then return those that were
-previously stored in the variable `ghub-response-headers'.
-
-When accessing a Bitbucket instance then the link relations
-are in PAYLOAD instead of HEADERS, making their API merely
-RESTish and forcing this function to append those relations
-to the value of `ghub-response-headers', for later use when
-this function is called with nil for PAYLOAD."
-  (if (eq (ghub--req-forge req) 'bitbucket)
-      (if payload
-          (let* ((page (seq-keep (##assq % payload)
-                                 '(size page pagelen next previous)))
-                 (headers (cons (cons 'link-alist page) headers)))
-            (if (and req (or (ghub--req-callback req)
-                             (ghub--req-errorback req)))
-                (setq-local ghub-response-headers headers)
-              (setq-default ghub-response-headers headers))
-            page)
-        (cdr (assq 'link-alist ghub-response-headers)))
-    (and-let* ((headers (or headers ghub-response-headers))
-               (rels (cdr (or (assoc "Link" headers)
-                              (assoc "link" headers)))))
-      (mapcar (lambda (elt)
-                (pcase-let ((`(,url ,rel) (split-string elt "; ")))
-                  (cons (intern (substring rel 5 -1))
-                        (substring url 1 -1))))
-              (split-string rels ", ?")))))
-
-(cl-defun ghub-repository-id (owner name &key username auth host forge noerror)
-  "Return the id of the specified repository.
-Signal an error if the id cannot be determined."
-  (let ((fn (cl-case forge
-              ((nil ghub github) #'ghub--repository-id)
-              (gitlab            #'glab-repository-id)
-              (gitea             #'gtea-repository-id)
-              (gogs              #'gogs-repository-id)
-              (bitbucket         #'buck-repository-id)
-              (t (intern (format "%s-repository-id" forge))))))
-    (unless (fboundp fn)
-      (error "ghub-repository-id: Forge type/abbreviation `%s' is unknown"
-             forge))
-    (or (funcall fn owner name :username username :auth auth :host host)
-        (and (not noerror)
-             (error "Repository %S does not exist on %S.\n%s%S?"
-                    (concat owner "/" name)
-                    (or host (ghub--host forge))
-                    "Maybe it was renamed and you have to update "
-                    "remote.<remote>.url")))))
-
-;;;; Internal
-
-(cl-defun ghub--retrieve (payload req)
-  (let ((url-request-extra-headers
-         (let ((headers (ghub--req-headers req)))
-           (if (functionp headers) (funcall headers) headers)))
-        (url-request-method (ghub--req-method req))
-        (url-request-data payload)
-        (url-show-status nil)
-        (url     (ghub--req-url req))
-        (handler (ghub--req-handler req))
-        (silent  (ghub--req-silent req)))
-    (if (or (ghub--req-callback  req)
-            (ghub--req-errorback req))
-        (url-retrieve url handler (list req) silent)
-      (if-let ((buf (url-retrieve-synchronously url silent)))
-          (with-current-buffer buf
-            (funcall handler (car url-callback-arguments) req))
-        (error "ghub--retrieve: No buffer returned")))))
-
-(defun ghub--handle-response (status req)
-  (let ((buf (current-buffer)))
-    (unwind-protect
-        (progn
-          (set-buffer-multibyte t)
-          (let* ((unpaginate (ghub--req-unpaginate req))
-                 (headers (ghub--handle-response-headers status req))
-                 (payload (ghub--handle-response-payload req))
-                 (payload (ghub--handle-response-error status payload req))
-                 (value   (ghub--handle-response-value payload req))
-                 (prev    (ghub--req-url req))
-                 (next    (cdr (assq 'next (ghub-response-link-relations
-                                            req headers payload)))))
-            (when (numberp unpaginate)
-              (cl-decf unpaginate))
-            (setf (ghub--req-url req)
-                  (url-generic-parse-url next))
-            (setf (ghub--req-unpaginate req) unpaginate)
-            (or (and next
-                     unpaginate
-                     (or (eq unpaginate t)
-                         (>  unpaginate 0))
-                     (ghub-continue req))
-                (let ((req-buf   (ghub--req-buffer req))
-                      (callback  (ghub--req-callback req))
-                      (errorback (ghub--req-errorback req))
-                      (err       (plist-get status :error)))
-                  (cond ((and err errorback)
-                         (setf (ghub--req-url req) prev)
-                         (funcall (if (eq errorback t)
-                                      'ghub--errorback
-                                    errorback)
-                                  err headers status req))
-                        (callback
-                         (save-current-buffer
-                           (when (buffer-live-p req-buf)
-                             (set-buffer req-buf))
-                           (funcall callback value headers status req)))
-                        (t value))))))
-      (when (and (buffer-live-p buf)
-                 (not (buffer-local-value 'ghub-debug buf)))
-        (kill-buffer buf)))))
-
-(defun ghub--handle-response-headers (_status req)
-  (let (headers)
-    (when (memq url-http-end-of-headers '(nil 0))
-      (unless url-debug (setq url-debug t))
-      (error "BUG: Missing headers in response buffer %s" (current-buffer)))
-    (goto-char (point-min))
-    (forward-line 1)
-    (while (re-search-forward "^\\([^:]*\\): \\(.+\\)"
-                              url-http-end-of-headers t)
-      (push (cons (match-string 1)
-                  (match-string 2))
-            headers))
-    (setq headers (nreverse headers))
-    (goto-char (1+ url-http-end-of-headers))
-    (if (and req (or (ghub--req-callback req)
-                     (ghub--req-errorback req)))
-        (setq-local ghub-response-headers headers)
-      (setq-default ghub-response-headers headers))
-    headers))
-
-(defun ghub--handle-response-error (status payload req)
-  (if-let ((err (plist-get status :error)))
-      (if-let ((noerror (ghub--req-noerror req)))
-          (if (eq noerror 'return)
-              payload
-            (setcdr (last err) (list payload))
-            nil)
-        (ghub--signal-error err payload req))
-    payload))
-
-(defun ghub--signal-error (err &optional payload req)
-  (pcase-let ((`(,symb . ,data) err))
-    (if (eq symb 'error)
-        (if (eq (car-safe data) 'http)
-            (signal 'ghub-http-error
-                    (let ((code (car (cdr-safe data))))
-                      (list code
-                            (nth 2 (assq code url-http-codes))
-                            (and req (url-recreate-url (ghub--req-url req)))
-                            payload)))
-          (signal 'ghub-error data))
-      (signal symb data))))
-
-(defun ghub--errorback (err _headers _status req)
-  (ghub--signal-error err (nth 3 err) req))
-
-(defun ghub--handle-response-value (payload req)
-  (setf (ghub--req-value req)
-        (nconc (ghub--req-value req)
-               (if-let ((nested (and (eq (ghub--req-forge req) 'bitbucket)
-                                     (assq 'values payload))))
-                   (cdr nested)
-                 payload))))
-
-(defun ghub--handle-response-payload (req)
-  (funcall (or (ghub--req-reader req)
-               'ghub--read-json-payload)
-           url-http-response-status))
-
-(defun ghub--read-json-payload (_status &optional json-type-args)
-  (and-let* ((payload (ghub--decode-payload)))
-    (ghub--assert-json-available)
-    (condition-case nil
-        (apply #'json-parse-string payload
-               (or json-type-args
-                   '( :object-type alist
-                      :array-type list
-                      :null-object nil
-                      :false-object nil)))
-      (json-parse-error
-       (pop-to-buffer (current-buffer))
-       (setq-local ghub-debug t)
-       `((message . ,(if (looking-at "<!DOCTYPE html>")
-                         (if (re-search-forward
-                              "<p>\\(?:<strong>\\)?\\([^<]+\\)" nil t)
-                             (match-string 1)
-                           "error description missing")
-                       (string-trim (buffer-substring (point) (point-max)))))
-         (documentation_url
-          . "https://github.com/magit/ghub/wiki/Github-Errors"))))))
-
-(defun ghub--decode-payload (&optional _status)
-  (and (not (eobp))
-       (decode-coding-string
-        (buffer-substring-no-properties (point) (point-max))
-        'utf-8)))
-
-(defun ghub--encode-payload (payload)
-  (cl-typecase payload
-    (null nil)
-    (string (encode-coding-string payload 'utf-8))
-    (t (ghub--assert-json-available)
-       (encode-coding-string
-        (json-serialize payload
-                        :null-object :null
-                        :false-object nil)
-        'utf-8))))
-
-(defun ghub--url-encode-params (params)
-  (mapconcat (lambda (param)
-               (pcase-let ((`(,key . ,val) param))
-                 (concat (url-hexify-string (symbol-name key)) "="
-                         (cl-typecase val
-                           (integer (number-to-string val))
-                           (boolean (if val "true" "false"))
-                           (t (url-hexify-string val))))))
-             params "&"))
-
-(defun ghub--assert-json-available ()
-  (unless (and (fboundp 'json-available-p)
-               (json-available-p))
-    (error "Ghub requires Emacs 29 --with-json or Emacs >= 30")))
-
-;;; Authentication
-;;;; API
-
-;;;###autoload
-(defun ghub-clear-caches ()
-  "Clear all caches that might negatively affect Ghub.
-
-If a library that is used by Ghub caches incorrect information
-such as a mistyped password, then that can prevent Ghub from
-asking the user for the correct information again.
-
-Set `url-http-real-basic-auth-storage' to nil
-and call `auth-source-forget+'."
-  (interactive)
-  (setq url-http-real-basic-auth-storage nil)
-  (auth-source-forget+))
-
-;;;; Internal
-
-(defun ghub--headers (headers host auth username forge)
-  (push (cons "Content-Type" "application/json") headers)
-  (if (eq auth 'none)
-      headers
-    (unless (or username (stringp auth))
-      (setq username (ghub--username host forge)))
-    (lambda ()
-      (if (eq auth 'basic)
-          (cons (cons "Authorization" (ghub--basic-auth host username))
-                headers)
-        (cons (ghub--auth host auth username forge) headers)))))
-
-(cl-defgeneric ghub--auth (host auth &optional username forge)
-  (unless username
-    (setq username (ghub--username host forge)))
-  (if (eq auth 'basic)
-      (cl-ecase forge
-        ((nil gitea gogs bitbucket)
-         (cons "Authorization" (ghub--basic-auth host username)))
-        ((github gitlab)
-         (error "%s does not support basic authentication"
-                (capitalize (symbol-name forge)))))
-    (cons (cl-ecase forge
-            ((nil github gitea gogs bitbucket)
-             "Authorization")
-            (gitlab
-             "Private-Token"))
-          (if (eq forge 'bitbucket)
-              ;; For some undocumented reason Bitbucket supports
-              ;; values of the form "token <token>" only for GET
-              ;; requests.  For PUT requests we have to use basic
-              ;; authentication.  Note that the secret is a token
-              ;; (aka "app password"), not the actual password.
-              ;; The documentation fails to mention this little
-              ;; detail.  See #97.
-              (concat "Basic "
-                      (base64-encode-string
-                       (concat username ":"
-                               (ghub--token host username auth nil forge))
-                       t))
-            (concat
-             (and (not (eq forge 'gitlab)) "token ")
-             (encode-coding-string
-              (cl-typecase auth
-                (string auth)
-                (null   (ghub--token host username 'ghub nil forge))
-                (symbol (ghub--token host username auth  nil forge))
-                (t (signal 'wrong-type-argument
-                           `((or stringp symbolp) ,auth))))
-              'utf-8))))))
-
-(defun ghub--basic-auth (host username)
-  (let ((url (url-generic-parse-url
-              (if (member host ghub-insecure-hosts) "http://" "https://"))))
-    (setf (url-user url) username)
-    (url-basic-auth url t)))
-
-(defun ghub--token (host username package &optional nocreate forge)
-  (let* ((user (ghub--ident username package))
-         (token (or (ghub--auth-source-get :secret :host host :user user)
-                    (and (string-match "\\`\\([^/]+\\)" host)
-                         (ghub--auth-source-get :secret
-                           :host (match-string 1 host)
-                           :user user)))))
-    (unless (or token nocreate)
-      (error "\
-Required %s token (%S for %s%S) does not exist.
-See https://magit.vc/manual/ghub/Getting-Started.html
-or (info \"(ghub)Getting Started\") for instructions."
-             (capitalize (symbol-name (or forge 'github)))
-             user
-             (if (string-match "\\`\\([^/]+\\)" host)
-                 (format "either %S or " (match-string 1 host))
-               "")
-             host))
-    (if (functionp token) (funcall token) token)))
-
-(cl-defgeneric ghub--host (&optional forge)
-  (cl-ecase forge
-    ((nil github)
-     (or (ignore-errors (car (process-lines "git" "config" "github.host")))
-         ghub-default-host))
-    (gitlab
-     (or (ignore-errors (car (process-lines "git" "config" "gitlab.host")))
-         (bound-and-true-p glab-default-host)))
-    (gitea
-     (or (ignore-errors (car (process-lines "git" "config" "gitea.host")))
-         (bound-and-true-p gtea-default-host)))
-    (gogs
-     (or (ignore-errors (car (process-lines "git" "config" "gogs.host")))
-         (bound-and-true-p gogs-default-host)))
-    (bitbucket
-     (or (ignore-errors (car (process-lines "git" "config" "bitbucket.host")))
-         (bound-and-true-p buck-default-host)))))
-
-(cl-defgeneric ghub--username (host &optional forge)
-  (let ((var
-         (cl-ecase forge
-           ((nil github)
-            (if (equal host ghub-default-host)
-                "github.user"
-              (format "github.%s.user" host)))
-           (gitlab
-            (if (equal host "gitlab.com/api/v4")
-                "gitlab.user"
-              (format "gitlab.%s.user" host)))
-           (bitbucket
-            (if (equal host "api.bitbucket.org/2.0")
-                "bitbucket.user"
-              (format "bitbucket.%s.user" host)))
-           (gitea
-            (when (zerop (call-process "git" nil nil nil "config" "gitea.host"))
-              (message "WARNING: gitea.host is set but always ignored"))
-            (format "gitea.%s.user" host))
-           (gogs
-            (when (zerop (call-process "git" nil nil nil "config" "gogs.host"))
-              (message "WARNING: gogs.host is set but always ignored"))
-            (format "gogs.%s.user"  host)))))
-    (condition-case nil
-        (car (process-lines "git" "config" var))
-      (error
-       (let ((user (read-string
-                    (format "Git variable `%s' is unset.  Set to: " var))))
-         (if (equal user "")
-             (user-error "The empty string is not a valid username")
-           (call-process
-            "git" nil nil nil "config"
-            (if (eq (read-char-choice
-                     (format "Set %s=%s [g]lobally (recommended) or [l]ocally? "
-                             var user)
-                     (list ?g ?l))
-                    ?g)
-                "--global"
-              "--local")
-            var user)
-           user))))))
-
-(defun ghub--ident (username package)
-  (format "%s^%s" username package))
-
-(defun ghub--auth-source-get (keys &rest spec)
-  (declare (indent 1))
-  (if-let ((plist (car (apply #'auth-source-search
-                              (append spec (list :max 1))))))
-      (if (keywordp keys)
-          (plist-get plist keys)
-        (mapcar (##plist-get plist %) keys))
-    ;; Auth-Source caches the information that there is no value, but in
-    ;; our case that is a situation that needs fixing, so we want to keep
-    ;; trying, by invalidating that information.
-    (auth-source-forget spec)
-    nil))
-
-;;; _
-(provide 'ghub)
-(require 'ghub-graphql)
-;;; ghub.el ends here
diff --git a/elpa/ghub-20250509.1440/ghub.info b/elpa/ghub-20250509.1440/ghub.info
deleted file mode 100644 (file)
index 93914b6..0000000
+++ /dev/null
@@ -1,1145 +0,0 @@
-This is ghub.info, produced by makeinfo version 6.8 from ghub.texi.
-
-     Copyright (C) 2017-2025 Jonas Bernoulli
-     <emacs.ghubNOSPAMjonas.bernoulli.dev>
-
-     You can redistribute this document and/or modify it under the terms
-     of the GNU General Public License as published by the Free Software
-     Foundation, either version 3 of the License, or (at your option)
-     any later version.
-
-     This document is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-INFO-DIR-SECTION Emacs
-START-INFO-DIR-ENTRY
-* Ghub: (ghub).         Client library for the Github API.
-END-INFO-DIR-ENTRY
-
-\1f
-File: ghub.info,  Node: Top,  Next: Introduction,  Up: (dir)
-
-Ghub User and Developer Manual
-******************************
-
-Ghub is an Emacs library that is used by various packages to access the
-APIs of various instances of various Git forge implementations.
-
-This manual is for Ghub version 4.3.1.
-
-     Copyright (C) 2017-2025 Jonas Bernoulli
-     <emacs.ghubNOSPAMjonas.bernoulli.dev>
-
-     You can redistribute this document and/or modify it under the terms
-     of the GNU General Public License as published by the Free Software
-     Foundation, either version 3 of the License, or (at your option)
-     any later version.
-
-     This document is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-* Menu:
-
-* Introduction::
-* Getting Started::
-* API::
-* Notes::
-* Function Index::
-* Variable Index::
-
-— The Detailed Node Listing —
-
-Getting Started
-
-* Basic Concepts, Arguments and Variables: Basic Concepts Arguments and Variables.
-* Setting the Username::
-* Creating and Storing a Token::
-* Github Configuration Variables::
-
-API
-
-* Their APIs::
-* Making REST Requests::
-* Making GraphQL Requests::
-* Github Convenience Wrappers::
-* Non-Github Convenience Wrappers::
-
-Notes
-
-* Using Ghub in Personal Scripts::
-* Using Ghub in Your Own Package::
-* Forge Limitations and Notes::
-
-
-\1f
-File: ghub.info,  Node: Introduction,  Next: Getting Started,  Prev: Top,  Up: Top
-
-1 Introduction
-**************
-
-Ghub is an Emacs library that is used by various packages to access the
-APIs of various instances of various Git forge implementations.
-
-   A forge is a web-based collaborative software platform for developing
-and distributing computer applications.  Examples include Github and
-Gitlab.
-
-\1f
-File: ghub.info,  Node: Getting Started,  Next: API,  Prev: Introduction,  Up: Top
-
-2 Getting Started
-*****************
-
-This manual guides you through the steps that are necessary to use the
-Forge package and/or to make a request using just Ghub itself, such as
-this:
-
-     (ghub-request "GET" "/user")
-
-   To be able to do that, Ghub needs to know who you want to talk to,
-who you are, and how you are going to prove the latter to the former.
-
-   Additionally Ghub wants to know on behalf of which Emacs package it
-is making a request.  So the question of "who is making the request" has
-to be rephrased as "which human (or bot) is using what (Emacs) package
-to make the request".  If, for example, the human known as "tarsius" is
-using the ‘forge’ package, then that is represented in some places using
-the string "tarsius^forge".
-
-* Menu:
-
-* Basic Concepts, Arguments and Variables: Basic Concepts Arguments and Variables.
-* Setting the Username::
-* Creating and Storing a Token::
-* Github Configuration Variables::
-
-\1f
-File: ghub.info,  Node: Basic Concepts Arguments and Variables,  Next: Setting the Username,  Up: Getting Started
-
-2.1 Basic Concepts, Arguments and Variables
-===========================================
-
-(If you are trying to configure Forge for <https://github.com> and/or
-<https://gitlab.com>, then you can skip this section.)
-
-   Originally Ghub supported only Github but now it also supports
-Gitlab, Gitea, Gogs and Bitbucket.  Because of that, the function
-‘ghub-request’ defaults to acting on a ‘github’ forge, but can be told
-to act on other forges using the FORGE argument.
-
-   The FORGE argument only specifies what kind of forge we are
-accessing, not which host specifically.  The HOST argument can be used
-to select the instance.  For some forges a default instance is defined:
-
-   • Forge ‘github’ defaults to host ‘api.github.com’.
-   • Forge ‘gitlab’ defaults to host ‘gitlab.com/api/v4’.
-   • Forge ‘bitbucket’ defaults to host ‘api.bitbucket.org/2.0’.
-   • No canonical host exists for the ‘gitea’ and ‘gogs’ forges and
-     ‘localhost:3000/api/v1’ is used as the default host in both cases.
-
-   Together the FORGE and HOST arguments specify the forge type and
-instance.  In addition to that, it is also necessary to specify on whose
-behalf the request is being made, which can be done using the USERNAME
-and AUTH arguments.  For example:
-
-     (ghub-request "GET" "/user" nil
-                   :forge 'github
-                   :host "api.github.com"
-                   :username "tarsius"
-                   :auth 'forge)
-
-   Having to specify these arguments for every request is inconvenient.
-Additional variables and convenience functions can be used to make that
-unnecessary in most cases.
-
-   (But for debugging purposes the above explicit form is very useful.
-You will obviously have to change the value of USERNAME and you should
-use ‘ghub’ as AUTH when first trying this at home.)
-
-   These variables can be set globally and/or for a specific repository.
-
-   • For "api.github.com" (aka the API of <https://github.com>) the Git
-     variable ‘github.user’ specifies the user.
-   • For another ‘github’ instance the Git variable ‘github.HOST.user’
-     specifies the user.  The HOST in that variable name is the same as
-     the value of the HOST argument of the called function.
-   • Instead of specifying the HOST in every function call, the Git
-     variable ‘github.host’ can be used.  This should only be set
-     locally.
-
-   These ‘github’ specific variables are discussed in more detail in
-*note Github Configuration Variables::.
-
-For ‘gitlab’ and ‘bitbucket’ forges similar variables are available:
-
-   • ‘gitlab.user’ specifies the <https://gitlab.com> user.
-   • ‘gitlab.HOST.user’ specifies the user for the HOST ‘gitlab’
-     instance.
-   • ‘gitlab.host’ specifies the ‘gitlab’ host, unless the HOST argument
-     is non-nil
-   • ‘bitbucket.user’ specifies the <https://bitbucket.org> user.
-   • ‘bitbucket.HOST.user’ specifies the user for the HOST ‘bitbucket’
-     instance.
-   • ‘bitbucket.host’ specifies the ‘bitbucket’ host, unless the HOST
-     argument is non-nil.
-
-   For the ‘gitea’ and ‘gogs’ forges some similar variables are
-available, however for some of the ‘ghub.*’ variables no equivalent
-variable exist for these two forges:
-
-   • ‘gitea.user’ is *not* used because no canonical ‘gitea’ instance
-     exists.
-   • ‘gitea.HOST.user’ specifies the user for the HOST ‘gitea’ instance.
-   • ‘gitea.host’ specifies the ‘gitea’ host, unless the HOST argument
-     is non-nil
-   • ‘gogs.user’ is *not* used because no canonical ‘gogs’ instance
-     exists.
-   • ‘gogs.HOST.user’ specifies the user for the HOST ‘gogs’ instance.
-   • ‘gogs.host’ specifies the ‘gogs’ host, unless the HOST argument is
-     non-nil
-
-\1f
-File: ghub.info,  Node: Setting the Username,  Next: Creating and Storing a Token,  Prev: Basic Concepts Arguments and Variables,  Up: Getting Started
-
-2.2 Setting the Username
-========================
-
-Ghub needs to know your username, which you use on the host that you
-want it to connect to.  For each host a different Git variable has to be
-set, to specify the username on that host.  More than one variable is
-needed, because you might use different usernames on different hosts.
-
-Setting your Github.com Username
---------------------------------
-
-To inform Ghub about your "github.com" username do this:
-
-     git config --global github.user USERNAME
-
-   If you need to identify as another user in a particular repository,
-then you have to set that variable locally:
-
-     cd /path/to/repo
-     git config --local github.user USERNAME
-
-Setting your Gitlab.com Username
---------------------------------
-
-To inform Ghub about your "gitlab.com" username do this:
-
-     git config --global gitlab.user USERNAME
-
-   If you need to identify as another user in a particular repository,
-then you have to set that variable locally:
-
-     cd /path/to/repo
-     git config --local gitlab.user USERNAME
-
-   Make sure you use the correct USERNAME for this forge/host.  It might
-not be the same as on "github.com"!
-
-Setting your Github Enterprise Username
----------------------------------------
-
-For Github Enterprise instances you have to specify where the API can be
-accessed and a different variable has to be used to set the username.
-
-   For example if the API is available at ‘https://example.com/api/v3’,
-then you should do this:
-
-     git config --global github.example.com/api/v3.user USERNAME
-
-   Make sure you use the correct USERNAME for this instance.  It might
-not be the same as on "github.com"!
-
-   Doing this only tells Ghub who you are on this host, additionally you
-have to tell Ghub which repositories are connected to that forge/host,
-like so:
-
-     cd /path/to/repo
-     git config --local github.host example.com/api/v3
-
-Setting your Username for Other Hosts and/or Forges
----------------------------------------------------
-
-To inform Ghub about your username on HOST (a FORGE instance) do this:
-
-     git config --global FORGE.HOST.user USERNAME
-
-   FORGE can be one of ‘bitbucket’, ‘gitea’ or ‘gogs’.  It can also be
-‘github’ or ‘gitlab’; but if that is the case, then you should look at
-the preceding sections instead, which discuss these cases specifically.
-
-   HOST identifies the instance.  This actually points at the top-level
-endpoint of the API and may contain path components, e.g.:
-‘example.com/api’.
-
-   If you need to identify as another user in a particular repository,
-then you have to set that variable locally:
-
-     cd /path/to/repo
-     git config --local FORGE.HOST.user USERNAME
-
-\1f
-File: ghub.info,  Node: Creating and Storing a Token,  Next: Github Configuration Variables,  Prev: Setting the Username,  Up: Getting Started
-
-2.3 Creating and Storing a Token
-================================
-
-2.3.1 Creating a Token
-----------------------
-
-To create a token, use the web interface of the host you want to connect
-to.  Here is a list of pages to do this for certain popular hosts:
-
-   • <https://github.com/settings/tokens>
-   • <https://gitlab.com/-/profile/personal_access_tokens>
-
-   For other forges we cannot provide a functioning URL because they
-contain unknown values such as your name.  Just go to the general
-settings page of the respective host and then go from there.
-
-   Except on ‘gitea’ and ‘gogs’ each token can be limited to certain
-"scopes", i.e., it is possible to limit for which purposes any given
-token can be used.
-
-   Before you create a token to be used for a certain package, you
-should consult the documentation of that package, which in turn should
-tell you which scopes are needed and why.  The Forge package for example
-does so in *note (forge)Token Creation::.
-
-2.3.2 Storing a Token
----------------------
-
-Please also see *note (auth)Top:: for all the gory details about
-Auth-Source.
-
-   The variable ‘auth-sources’ controls how and where Auth-Source keeps
-its secrets.  The default value is a list of three files:
-‘("~/.authinfo" "~/.authinfo.gpg" "~/.netrc")’, but to avoid confusion
-you should make sure that only one of these files exists, and then you
-should also adjust the value of the variable to only ever use that file,
-for example:
-
-     (setq auth-sources '("~/.authinfo"))
-
-   In ‘~/.authinfo’ secrets are stored in plain text.  If you don’t want
-that, then you should use the encrypted ‘~/.authinfo.gpg’ instead:
-
-     (setq auth-sources '("~/.authinfo.gpg"))
-
-   Auth-Source also supports storing secrets in various external
-key-chains.  See *note (auth)Top:: for more information.
-
-   The default Auth-Source backends only support storing three values
-per entry; the "machine", the "login" and the "password".  Because Ghub
-uses separate tokens for each package, it has to squeeze four values
-into those three slots, and it does that by using "USERNAME^PACKAGE" as
-the "login".
-
-   Assuming your *Github* username is "ziggy", the package is named
-"forge", and you want to access *Github.com* with the *token*
-"012345abcdef...", an entry in one of the three mentioned files would
-then look like this:
-
-     machine api.github.com login ziggy^forge password 012345abcdef...
-
-   Assuming your *Gitlab* username is "ziggy", the package is named
-"forge", and you want to access *Gitlab.com* with the *token*
-"012345abcdef...", an entry in one of the three mentioned files would
-then look like this:
-
-     machine gitlab.com/api/v4 login ziggy^forge password 012345abcdef...
-
-\1f
-File: ghub.info,  Node: Github Configuration Variables,  Prev: Creating and Storing a Token,  Up: Getting Started
-
-2.4 Github Configuration Variables
-==================================
-
-The username and, unless you only use Github.com itself, the Github
-Enterprise instance have to be configured using Git variables.  In rare
-cases it might also be necessary to specify the identity of the local
-machine, which is done using a lisp variable.
-
- -- Variable: github.user
-     The Github.com username.  This should be set globally and if you
-     have multiple Github.com user accounts, then you should set this
-     locally only for those repositories that you want to access using
-     the secondary identity.
-
- -- Variable: github.HOST.user
-     This variable serves the same purpose as ‘github.user’ but for the
-     Github Enterprise instance identified by ‘HOST’.
-
-     The reason why separate variables are used is that this makes it
-     possible to set both values globally instead of having to set one
-     of the values locally in each and every repository that is
-     connected to the Github Enterprise instance, not Github.com.
-
- -- Variable: github.host
-     This variable should only be set locally for a repository and
-     specifies the Github Enterprise edition that that repository is
-     connected to.  You should not set this globally because then each
-     and every repository becomes connected to the specified Github
-     Enterprise instance, including those that should actually be
-     connected to Github.com.
-
-     When this is undefined, then "api.github.com" is used (defined in
-     the constant ‘ghub-default-host’, which you should never attempt to
-     change.)
-
-\1f
-File: ghub.info,  Node: API,  Next: Notes,  Prev: Getting Started,  Up: Top
-
-3 API
-*****
-
-* Menu:
-
-* Their APIs::
-* Making REST Requests::
-* Making GraphQL Requests::
-* Github Convenience Wrappers::
-* Non-Github Convenience Wrappers::
-
-\1f
-File: ghub.info,  Node: Their APIs,  Next: Making REST Requests,  Up: API
-
-3.1 Their APIs
-==============
-
-Of course this manual does not cover the APIs of all forges that it
-supports, but for your convenience, here are the links to their API
-manuals:
-
-   • Github:
-        • <https://developer.github.com/v4> (GraphQl)
-        • <https://developer.github.com/v3> (REST)
-   • Gitlab:
-        • <https://docs.gitlab.com/ee/api/README.html>
-   • Gitea:
-        • <https://docs.gitea.io/en-us/api-usage>
-        • <https://try.gitea.io/api/swagger>
-   • Gogs:
-        • <https://github.com/gogs/go-gogs-client/wiki>
-   • Bitbucket:
-        • <https://developer.atlassian.com/bitbucket/api/2/reference>
-
-\1f
-File: ghub.info,  Node: Making REST Requests,  Next: Making GraphQL Requests,  Prev: Their APIs,  Up: API
-
-3.2 Making REST Requests
-========================
-
- -- Function: ghub-request method resource &optional params &key query
-          payload headers unpaginate noerror reader username auth host
-          callback errorback url value error extra method*
-     This function makes a request for ‘RESOURCE’ using ‘METHOD’.
-     ‘PARAMS’, ‘QUERY’, ‘PAYLOAD’ and/or ‘HEADERS’ are alists holding
-     additional request data.  The response body is returned and the
-     response headers are stored in the variable
-     ‘ghub-response-headers’.
-
-        • ‘METHOD’ is the HTTP method, given as a string.
-        • ‘RESOURCE’ is the resource to access, given as a string
-          beginning with a slash.
-
-        • ‘PARAMS’, ‘QUERY’, ‘PAYLOAD’ and ‘HEADERS’ are alists and are
-          used to specify request data.  All these arguments are alists
-          that resemble the JSON expected and returned by the Github
-          API.  The keys are symbols and the values stored in the ‘cdr’
-          (not the ‘cadr’) can be strings, integers, or lists of strings
-          and integers.
-
-          The Github API documentation is vague on how data has to be
-          transmitted and for a particular resource usually just talks
-          about "parameters".  Generally speaking when the ‘METHOD’ is
-          "HEAD" or "GET", then they have to be transmitted as a query,
-          otherwise as a payload.
-
-             • Use ‘PARAMS’ to automatically transmit like ‘QUERY’ or
-               ‘PAYLOAD’ would depending on ‘METHOD’.
-             • Use ‘QUERY’ to explicitly transmit data as a query.
-             • Use ‘PAYLOAD’ to explicitly transmit data as a payload.
-               Instead of an alist, ‘PAYLOAD’ may also be a string, in
-               which case it gets encoded as UTF-8 but is otherwise
-               transmitted as-is.
-             • Use ‘HEADERS’ for those rare resources that require that
-               the data is transmitted as headers instead of as a query
-               or payload.  When that is the case, then the Github API
-               documentation usually mentions it explicitly.
-
-        • If ‘SILENT’ is non-nil, then progress reports and the like are
-          not messaged.
-
-        • If ‘UNPAGINATE’ is t, then this function makes as many
-          requests as necessary to get all values.  If ‘UNPAGINATE’ is a
-          natural number, then it gets at most that many pages.  For any
-          other non-nil value it raises an error.
-
-        • If ‘NOERROR’ is non-nil, then no error is raised if the
-          request fails and ‘nil’ is returned instead.  If ‘NOERROR’ is
-          ‘return’, then the error payload is returned instead of ‘nil’.
-
-        • If ‘READER’ is non-nil, then it is used to read and return
-          from the response buffer.  The default is
-          ‘ghub--read-json-payload’.  For the very few resources that do
-          not return JSON, you might want to use ‘ghub--decode-payload’.
-
-        • If ‘USERNAME’ is non-nil, then the request is made on behalf
-          of that user.  It is better to specify the user using the Git
-          variable ‘github.user’ for "api.github.com", or
-          ‘github.HOST.user’ if connecting to a Github Enterprise
-          instance.
-
-        • Each package that uses Ghub should use its own token.  If
-          ‘AUTH’ is ‘nil’ or unspecified, then the generic ‘ghub’ token
-          is used instead.  This is only acceptable for personal
-          utilities.  A package that is distributed to other users
-          should always use this argument to identify itself, using a
-          symbol matching its name.
-
-          Package authors who find this inconvenient should write a
-          wrapper around this function and possibly for the
-          method-specific functions as well.
-
-          Beside ‘nil’, some other symbols have a special meaning too.
-          ‘none’ means to make an unauthorized request.  ‘basic’ means
-          to make a password based request.  If the value is a string,
-          then it is assumed to be a valid token.  ‘basic’ and an
-          explicit token string are only intended for internal and
-          debugging uses.
-
-          If ‘AUTH’ is a package symbol, then the scopes are specified
-          using the variable ‘AUTH-github-token-scopes’.  It is an error
-          if that is not specified.  See ‘ghub-github-token-scopes’ for
-          an example.
-
-        • If ‘HOST’ is non-nil, then connect to that Github instance.
-          This defaults to "api.github.com".  When a repository is
-          connected to a Github Enterprise instance, then it is better
-          to specify that using the Git variable ‘github.host’ instead
-          of using this argument.
-
-        • If ‘FORGE’ is ‘gitlab’, then connect to Gitlab.com or,
-          depending on ‘HOST’, to another Gitlab instance.  This is only
-          intended for internal use.  Instead of using this argument you
-          should use function ‘glab-request’ and other ‘glab-*’
-          functions.
-
-        • If ‘CALLBACK’ and/or ‘ERRORBACK’ is non-nil, then this
-          function makes one or more asynchronous requests and calls
-          ‘CALLBACK’ or ‘ERRORBACK’ when finished.  If no error
-          occurred, then it calls ‘CALLBACK’, unless that is ‘nil’.
-
-          If an error occurred, then it calls ‘ERRORBACK’, or if that is
-          nil, then ‘CALLBACK’.  ‘ERRORBACK’ can also be ‘t’, in which
-          case it signals instead.  ‘NOERROR’ is ignored for all
-          asynchronous requests.
-
-          Both callbacks are called with four arguments.
-
-            1. For ‘CALLBACK’, the combined value of the retrieved
-               pages.  For ‘ERRORBACK’, the error that occurred when
-               retrieving the last page.
-            2. The headers of the last page as an alist.
-            3. Status information provided by ‘url-retrieve’.  Its
-               ‘:error’ property holds the same information as the first
-               argument to ‘ERRORBACK’.
-            4. A ‘ghub--req’ struct, which can be passed to
-               ‘ghub-continue’ (which see) to retrieve the next page, if
-               any.
-
- -- Function: ghub-continue args
-     If there is a next page, then this function retrieves that.
-
-     This function is only intended to be called from callbacks.  If
-     there is a next page, then that is retrieved and the buffer that
-     the result will be loaded into is returned, or t if the process has
-     already completed.  If there is no next page, then return nil.
-
-     Callbacks are called with four arguments (see ‘ghub-request’).  The
-     forth argument is a ‘ghub--req’ struct, intended to be passed to
-     this function.  A callback may use the struct’s ‘extra’ slot to
-     pass additional information to the callback that will be called
-     after the next request.  Use the function ‘ghub-req-extra’ to get
-     and set the value of that slot.
-
-     As an example, using ‘ghub-continue’ in a callback like so:
-
-          (ghub-get "/users/tarsius/repos" nil
-                    :callback (lambda (value _headers _status req)
-                                (unless (ghub-continue req)
-                                  (setq my-value value))))
-
-     is equivalent to:
-
-          (ghub-get "/users/tarsius/repos" nil
-                    :unpaginate t
-                    :callback (lambda (value _headers _status _req)
-                                (setq my-value value)))
-
-     To demonstrate how to pass information from one callback to the
-     next, here we record when we start fetching each page:
-
-          (ghub-get "/users/tarsius/repos" nil
-                    :extra (list (current-time))
-                    :callback (lambda (value _headers _status req)
-                                (push (current-time) (ghub-req-extra req))
-                                (unless (ghub-continue req)
-                                  (setq my-times (ghub-req-extra req))
-                                  (setq my-value value))))
-
- -- Variable: ghub-response-headers
-     A select few Github API resources respond by transmitting data in
-     the response header instead of in the response body.  Because there
-     are so few of these inconsistencies, ‘ghub-request’ always returns
-     the response body.
-
-     To access the response headers use this variable after
-     ‘ghub-request’ has returned.
-
- -- Function: ghub-response-link-relations req headers payload
-     This function returns an alist of the link relations in ‘HEADERS’,
-     or if optional ‘HEADERS’ is nil, then those in
-     ‘ghub-response-headers’.
-
-     When accessing a Bitbucket instance then the link relations are in
-     ‘PAYLOAD’ instead of ‘HEADERS’, making their API merely RESTish and
-     forcing this function to append those relations to the value of
-     ‘ghub-response-headers’, for later use when this function is called
-     with ‘nil’ for ‘PAYLOAD’.
-
-\1f
-File: ghub.info,  Node: Making GraphQL Requests,  Next: Github Convenience Wrappers,  Prev: Making REST Requests,  Up: API
-
-3.3 Making GraphQL Requests
-===========================
-
- -- Function: ghub-graphql graphql &optional variables &key username
-          auth host callback silent callback errorback value extra
-     This function makes a GraphQL request using ‘GRAPHQL’ and
-     ‘VARIABLES’ as inputs.  ‘GRAPHQL’ is a GraphQL string.  ‘VARIABLES’
-     is a JSON-like alist.  The other arguments behave as for
-     ‘ghub-request’ (which see).
-
-     The response is returned as a JSON-like alist.  Even if the
-     response contains ‘errors’, this function does not raise an error.
-     Cursor-handling is likewise left to the caller.
-
-   ‘ghub-graphql’ is a thin convenience wrapper around ‘ghub-request’,
-similar to ‘ghub-post’ and friends.  While the latter only hard-code the
-value of the ‘METHOD’ argument, the former also hard-codes ‘RESOURCE’
-and constructs ‘PAYLOAD’ from ‘GRAPHQL’ and ‘VARIABLES’.  It also drops
-‘UNPAGINATE’, ‘NOERROR’, ‘READER’ (internal functions expect alist-ified
-JSON) and ‘FORGE’ (only Github currently supports GraphQL).
-
-   ‘ghub-graphql’ does not account for the fact that pagination works
-differently in GraphQL than it does in REST, so users of this function
-have to deal with that themselves.  Likewise error handling works
-differently and has to be done by the caller too.
-
-   An early attempt at implementing automatic unpaginating for GraphQL
-can be found in the ‘faithful-graphql’ branch, provided I haven’t
-deleted that by now.  On that branch I try to do things as intended by
-the designers of GraphQL, using variables and fragments, and drowning in
-a sea of boilerplate.
-
-   The problem with that approach is that it only works for applications
-that fetch specific information on demand and actually want things to be
-paginated.  I am convinced that GraphQL is very nice for web apps.
-
-   However the Forge package for which I have implemented all of this
-has very different needs.  It wants to fetch "all the data" and "cache"
-it locally, so that it is available even when there is no internet
-connection.  GraphQL was designed around the idea that you should be
-able to "ask for what you need and get exactly that".  But when that
-boils down to "look, if I persist, then you are going to hand me over
-all the data anyway, so just caught it up already", then things start to
-fall apart.  If Github’s GraphQL allowed pagination to be turned off
-completely, then teaching ‘ghub-graphql’ about error handling would be
-enough.
-
-   But it doesn’t and when doing things as intended, then that leads to
-huge amounts of repetitive boilerplate, which is so boring to write that
-doing it without introducing bugs left and right is near impossible; so
-I decided to give up on GraphQL variables, fragments and conditions, and
-instead implement something more powerful, though also more opinionated.
-
- -- Function: ghub--graphql-vacuum query variables callback &optional
-          until &key narrow username auth host forge
-     This function is an opinionated alternative to ‘ghub-graphql’.  It
-     relies on dark magic to get the job done.
-
-     It makes an initial request using ‘QUERY’.  It then looks for
-     paginated edges in the returned data and makes more requests to
-     resolve them.  In order to do so it automatically transforms the
-     initial ‘QUERY’ into another query suitable for that particular
-     edge.  The data retrieved by subsequent requests is then injected
-     into the data of the original request before that is returned or
-     passed to the callback.  If subsequently retrieved data features
-     new paginated edges, then those are followed recursively.
-
-     The end result is essentially the same as using ‘ghub-graphql’, if
-     only it were possible to say "do not paginate anything".  The
-     implementation is much more complicated because it is not possible
-     to do that.
-
-     ‘QUERY’ is a GraphQL query expressed as an s-expression.  The
-     bundled ‘gsexp’ library is used to turn that into a GraphQL query
-     string.  Only a subset of the GraphQL features are supported;
-     fragments for example are not, and magical stuff happens to
-     variables.  This is not documented yet, I am afraid.  Look at
-     existing callers.
-
-     ‘VARIABLES’ is a JSON-like alist as for ‘ghub-graphql’.
-
-     ‘UNTIL’ is an alist ‘((EDGE-until . VALUE)...)’.  When unpaginating
-     ‘EDGE’ try not to fetch beyond the element whose first field has
-     the value ‘VALUE’ and remove that element as well as all "lesser"
-     elements from the retrieved data if necessary.  Look at
-     ‘forge--pull-repository’ for an example.  This is only useful if
-     you "cache" the response locally and want to avoid fetching data
-     again that you already have.
-
-     Other arguments behave as for ‘ghub-graphql’ and ‘ghub-request’,
-     more or less.  If ‘CALLBACK’ is nil, pretty-print the response.
-
-   Using ‘ghub--graphql-vacuum’, the following resource specific
-functions are implemented.  These functions are not part of the public
-API yet and are very much subject to change.
-
- -- Function: ghub-fetch-repository owner name callback &optional until
-          &key username auth host forge
-     This function asynchronously fetches forge data about the specified
-     repository.  Once all data has been collected, ‘CALLBACK’ is called
-     with the data as the only argument.
-
- -- Function: ghub-fetch-issue owner name callback &optional until &key
-          username auth host forge
-     This function asynchronously fetches forge data about the specified
-     issue.  Once all data has been collected, ‘CALLBACK’ is called with
-     the data as the only argument.
-
- -- Function: ghub-fetch-pullreq owner name callback &optional until
-          &key username auth host forge
-     This function asynchronously fetches forge data about the specified
-     pull-request.  Once all data has been collected, ‘CALLBACK’ is
-     called with the data as the only argument.
-
-   Note that in order to avoid duplication all of these functions base
-their initial query on the query stored in ‘ghub-fetch-repository’.  The
-latter two pass that query through ‘ghub--graphql-prepare-query’, which
-then uses ‘ghub--graphql-narrow-query’ to remove parts the caller is not
-interested in.  These two functions are also used internally, when
-unpaginating, but as demonstrated here they can be useful even before
-making an initial request.
-
-\1f
-File: ghub.info,  Node: Github Convenience Wrappers,  Next: Non-Github Convenience Wrappers,  Prev: Making GraphQL Requests,  Up: API
-
-3.4 Github Convenience Wrappers
-===============================
-
- -- Function: ghub-head resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: ghub-get resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
-     These functions are simple wrappers around ‘ghub-request’.  Their
-     signature is identical to that of the latter, except that they do
-     not have an argument named ‘METHOD’.  The HTTP method is instead
-     given by the second word in the function name.
-
-     As described in the documentation for ‘ghub-request’, it depends on
-     the used method whether the value of the ‘PARAMS’ argument is used
-     as the query or the payload.  For the "HEAD" and "GET" methods it
-     is used as the query.
-
- -- Function: ghub-put resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: ghub-post resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: ghub-patch resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: ghub-delete resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
-     These functions are simple wrappers around ‘ghub-request’.  Their
-     signature is identical to that of the latter, except that they do
-     not have an argument named ‘METHOD’.  The HTTP method is instead
-     given by the second word in the function name.
-
-     As described in the documentation for ‘ghub-request’, it depends on
-     the used method whether the value of the ‘PARAMS’ argument is used
-     as the query or the payload.  For the "PUT", "POST", "PATCH" and
-     "DELETE" methods it is used as the payload.
-
- -- Function: ghub-wait resource &optional duration &key username auth
-          host
-     Some API requests result in an immediate successful response even
-     when the requested action has not actually been carried out yet.
-     An example is the request for the creation of a new repository,
-     which doesn’t cause the repository to immediately become available.
-     The Github API documentation usually mentions this when describing
-     an affected resource.
-
-     If you want to do something with some resource right after making a
-     request for its creation, then you might have to wait for it to
-     actually be created.  This function can be used to do so.  It
-     repeatedly tries to access the resource until it becomes available
-     or until a timeout is reached.  In the latter case it signals
-     ‘ghub-error’.
-
-     ‘RESOURCE’ specifies the resource that this function waits for.
-
-     ‘DURATION’ specifies the maximum number of seconds to wait for,
-     defaulting to 64 seconds.  Emacs will block during that time, but
-     the user can abort using ‘C-g’.
-
-     The first attempt is made immediately and will often succeed.  If
-     not, then another attempt is made after two seconds, and each
-     subsequent attempt is made after waiting as long as we already
-     waited between all preceding attempts combined.
-
-     See ‘ghub-request’’s documentation above for information about the
-     other arguments.
-
-\1f
-File: ghub.info,  Node: Non-Github Convenience Wrappers,  Prev: Github Convenience Wrappers,  Up: API
-
-3.5 Non-Github Convenience Wrappers
-===================================
-
-‘ghub-request’ and ‘ghub-METHOD’ can be used to make a request for any
-of the supported forge types, but except when making a request for a
-‘github’ instance, then that requires the use of the FORGE argument.
-
-   To avoid that, functions named ‘FORGE-request’ and ‘FORGE-METHOD’ are
-also available.  The following forms are equivalent, for example:
-
-     (ghub-get ... :auth 'PACKAGE :forge 'gitlab)
-     (glab-get ... :auth 'PACKAGE)
-
-   These forms would remain equivalent even if you did not specify a
-value for the AUTH arguments — but you should not do that if you plan to
-share your code with others (see *note Using Ghub in Your Own
-Package::).  If you do omit AUTH, then the request is made on behalf of
-the ‘ghub’ package, *regardless* of the symbol prefix of the function
-you use to do so.
-
-   All ‘FORGE-request’ and ‘FORGE-METHOD’ functions, including but not
-limited to ‘ghub-METHOD’, are very simple wrappers around
-‘ghub-request’.  They take fewer arguments than ‘ghub-request’ and
-instead pass constant values for the arguments METHOD and/or FORGE.
-
- -- Function: buck-request resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-request resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-request resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
-     Wrappers around ‘ghub-request’ which hardcode the FORGE to either
-     ‘bitbucket’, ‘gitlab’, ‘gogs’ or ‘gitea’.
-
- -- Function: buck-get resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: buck-put resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: buck-post resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: buck-delete resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-head resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-get resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-put resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-post resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-patch resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: glab-delete resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-get resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-put resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-post resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-patch resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gogs-delete resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gtea-get resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gtea-put resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gtea-post resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gtea-patch resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
- -- Function: gtea-delete resource &optional params &key query payload
-          headers unpaginate noerror reader username auth host callback
-          errorback
-     Wrappers around ‘FORGE-METHOD’ which hardcode the FORGE to either
-     ‘bitbucket’, ‘gitlab’, ‘gogs’ or ‘gitea’, and the METHOD to the
-     implied method.
-
-     Note that ‘buck-head’, ‘buck-patch’, ‘gogs-head’ and ‘gtea-head’ do
-     not exist because the respective APIs do not appear to support
-     these methods.
-
-\1f
-File: ghub.info,  Node: Notes,  Next: Function Index,  Prev: API,  Up: Top
-
-4 Notes
-*******
-
-* Menu:
-
-* Using Ghub in Personal Scripts::
-* Using Ghub in Your Own Package::
-* Forge Limitations and Notes::
-
-\1f
-File: ghub.info,  Node: Using Ghub in Personal Scripts,  Next: Using Ghub in Your Own Package,  Up: Notes
-
-4.1 Using Ghub in Personal Scripts
-==================================
-
-You can of course use ‘ghub-request’ and its wrapper functions in your
-personal scripts.  Unlike when you use Ghub in a package that you
-distribute for others to use, you don’t have to explicitly specify a
-package in personal scripts.
-
-     ;; This is perfectly acceptable in personal scripts ...
-     (ghub-get "/user")
-
-     ;; ... and actually equals to
-     (ghub-get "/user" nil :auth 'ghub)
-
-     ;; In packages you have to specify the package using AUTH.
-     (ghub-get "/user" nil :auth 'some-package)
-
-   When the ‘AUTH’ argument is not specified, then a request is made on
-behalf of the ‘ghub’ package itself.  Like for any other package you
-have to create a dedicated token of course.
-
-\1f
-File: ghub.info,  Node: Using Ghub in Your Own Package,  Next: Forge Limitations and Notes,  Prev: Using Ghub in Personal Scripts,  Up: Notes
-
-4.2 Using Ghub in Your Own Package
-==================================
-
-Every package should use its own token.  This allows you as the author
-of some package to only request access to API scopes that are actually
-needed, which in turn might make it easier for users to trust your
-package not to do unwanted things.
-
-   You have to tell ‘ghub-request’ on behalf of which package a request
-is being made by passing the symbol ‘PACKAGE’ as the value of its ‘AUTH’
-argument.
-
-     (ghub-request "GET" "/user" nil :auth 'PACKAGE)
-
-   Keep in mind that the users of your package will have to manually
-create a suitable token.  To make that easier, you should not only link
-to this manual but also prominently mention the scopes the token needs;
-and explain what they are needed for.
-
-\1f
-File: ghub.info,  Node: Forge Limitations and Notes,  Prev: Using Ghub in Your Own Package,  Up: Notes
-
-4.3 Forge Limitations and Notes
-===============================
-
-   • There are no default Gitea and Gogs instances so the variables
-     ‘gitea.host’ and ‘gogs.host’ are not taken into account.
-
-   • Gitea and Gogs do not support limiting a token to certain scopes.
-
-   • The Bitbucket API is fairly broken and my willingness to deal with
-     that is extremely limited unless someone pays me vast amounts of
-     money.
-
-   • The Gitlab API documentation is not always accurate, though I don’t
-     have an example at hand.  It also isn’t structured well, making it
-     occasionally difficult to find the information one is looking for.
-
-   • Where one would use ‘user/repo’ when accessing another forge, one
-     has to use ‘user%2Frepo’ when accessing Gitlab, e.g.:
-
-          (glab-get "/projects/python-mode-devs%2Fpython-mode")
-
-\1f
-File: ghub.info,  Node: Function Index,  Next: Variable Index,  Prev: Notes,  Up: Top
-
-Appendix A Function Index
-*************************
-
-\0\b[index\0\b]
-* Menu:
-
-* buck-delete:                           Non-Github Convenience Wrappers.
-                                                              (line  49)
-* buck-get:                              Non-Github Convenience Wrappers.
-                                                              (line  40)
-* buck-post:                             Non-Github Convenience Wrappers.
-                                                              (line  46)
-* buck-put:                              Non-Github Convenience Wrappers.
-                                                              (line  43)
-* buck-request:                          Non-Github Convenience Wrappers.
-                                                              (line  28)
-* ghub--graphql-vacuum:                  Making GraphQL Requests.
-                                                              (line  56)
-* ghub-continue:                         Making REST Requests.
-                                                              (line 125)
-* ghub-delete:                           Github Convenience Wrappers.
-                                                              (line  31)
-* ghub-fetch-issue:                      Making GraphQL Requests.
-                                                              (line 105)
-* ghub-fetch-pullreq:                    Making GraphQL Requests.
-                                                              (line 111)
-* ghub-fetch-repository:                 Making GraphQL Requests.
-                                                              (line  99)
-* ghub-get:                              Github Convenience Wrappers.
-                                                              (line   9)
-* ghub-graphql:                          Making GraphQL Requests.
-                                                              (line   6)
-* ghub-head:                             Github Convenience Wrappers.
-                                                              (line   6)
-* ghub-patch:                            Github Convenience Wrappers.
-                                                              (line  28)
-* ghub-post:                             Github Convenience Wrappers.
-                                                              (line  25)
-* ghub-put:                              Github Convenience Wrappers.
-                                                              (line  22)
-* ghub-request:                          Making REST Requests.
-                                                              (line   6)
-* ghub-response-link-relations:          Making REST Requests.
-                                                              (line 174)
-* ghub-wait:                             Github Convenience Wrappers.
-                                                              (line  44)
-* glab-delete:                           Non-Github Convenience Wrappers.
-                                                              (line  67)
-* glab-get:                              Non-Github Convenience Wrappers.
-                                                              (line  55)
-* glab-head:                             Non-Github Convenience Wrappers.
-                                                              (line  52)
-* glab-patch:                            Non-Github Convenience Wrappers.
-                                                              (line  64)
-* glab-post:                             Non-Github Convenience Wrappers.
-                                                              (line  61)
-* glab-put:                              Non-Github Convenience Wrappers.
-                                                              (line  58)
-* glab-request:                          Non-Github Convenience Wrappers.
-                                                              (line  31)
-* gogs-delete:                           Non-Github Convenience Wrappers.
-                                                              (line  82)
-* gogs-get:                              Non-Github Convenience Wrappers.
-                                                              (line  70)
-* gogs-patch:                            Non-Github Convenience Wrappers.
-                                                              (line  79)
-* gogs-post:                             Non-Github Convenience Wrappers.
-                                                              (line  76)
-* gogs-put:                              Non-Github Convenience Wrappers.
-                                                              (line  73)
-* gogs-request:                          Non-Github Convenience Wrappers.
-                                                              (line  34)
-* gtea-delete:                           Non-Github Convenience Wrappers.
-                                                              (line  97)
-* gtea-get:                              Non-Github Convenience Wrappers.
-                                                              (line  85)
-* gtea-patch:                            Non-Github Convenience Wrappers.
-                                                              (line  94)
-* gtea-post:                             Non-Github Convenience Wrappers.
-                                                              (line  91)
-* gtea-put:                              Non-Github Convenience Wrappers.
-                                                              (line  88)
-
-\1f
-File: ghub.info,  Node: Variable Index,  Prev: Function Index,  Up: Top
-
-Appendix B Variable Index
-*************************
-
-\0\b[index\0\b]
-* Menu:
-
-* ghub-response-headers:                 Making REST Requests.
-                                                              (line 165)
-* github.host:                           Github Configuration Variables.
-                                                              (line  26)
-* github.HOST.user:                      Github Configuration Variables.
-                                                              (line  17)
-* github.user:                           Github Configuration Variables.
-                                                              (line  11)
-
-
-\1f
-Tag Table:
-Node: Top\7f773
-Node: Introduction\7f2243
-Node: Getting Started\7f2648
-Node: Basic Concepts Arguments and Variables\7f3675
-Node: Setting the Username\7f7655
-Ref: Setting your Githubcom Username\7f8143
-Ref: Setting your Gitlabcom Username\7f8499
-Ref: Setting your Github Enterprise Username\7f8965
-Ref: Setting your Username for Other Hosts and/or Forges\7f9698
-Node: Creating and Storing a Token\7f10504
-Ref: Creating a Token\7f10717
-Ref: Storing a Token\7f11628
-Node: Github Configuration Variables\7f13371
-Node: API\7f15082
-Node: Their APIs\7f15320
-Node: Making REST Requests\7f16045
-Node: Making GraphQL Requests\7f25458
-Node: Github Convenience Wrappers\7f32141
-Node: Non-Github Convenience Wrappers\7f35845
-Node: Notes\7f41349
-Node: Using Ghub in Personal Scripts\7f41556
-Node: Using Ghub in Your Own Package\7f42447
-Node: Forge Limitations and Notes\7f43382
-Node: Function Index\7f44355
-Node: Variable Index\7f50004
-\1f
-End Tag Table
-
-\1f
-Local Variables:
-coding: utf-8
-End:
diff --git a/elpa/ghub-20250509.1440/glab.el b/elpa/ghub-20250509.1440/glab.el
deleted file mode 100644 (file)
index 8f9f408..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-;;; glab.el --- Client library for the Gitlab API  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Glab is a library that provides basic support for using the Gitlab API
-;; from Emacs packages.  It abstracts access to API resources using only
-;; a handful of functions that are not resource-specific.
-
-;; This library is implemented on top of Ghub.  Unlike Ghub, Glab does
-;; not support the guided creation of tokens because Gitlab lacks the
-;; features that would be necessary to implement that.  Users have to
-;; create tokens through the web interface.
-
-;;; Code:
-
-(require 'ghub)
-
-(defconst glab-default-host "gitlab.com/api/v4"
-  "The default host that is used if `glab.host' is not set.")
-
-(cl-defun glab-head (resource &optional params
-                              &key query payload headers
-                              silent unpaginate noerror reader
-                              username auth host
-                              callback errorback extra)
-  "Make a `HEAD' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"HEAD\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "HEAD" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-get (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `GET' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"GET\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "GET" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-put (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PUT\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "PUT" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-post (resource &optional params
-                              &key query payload headers
-                              silent unpaginate noerror reader
-                              username auth host
-                              callback errorback extra)
-  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"POST\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "POST" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-patch (resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a `PATCH' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PATCH\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "PATCH" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-delete (resource &optional params
-                                &key query payload headers
-                                silent unpaginate noerror reader
-                                username auth host
-                                callback errorback extra)
-  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"DELETE\" as METHOD
-and `gitlab' as FORGE."
-  (ghub-request "DELETE" resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-request (method resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a request for RESOURCE and return the response body.
-Like calling `ghub-request' (which see) with `gitlab' as FORGE."
-  (ghub-request method resource params :forge 'gitlab
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun glab-graphql (graphql &optional variables
-                                &key username auth host
-                                headers silent
-                                callback errorback value extra)
-  "Make a GraphQL request using GRAPHQL and VARIABLES.
-Like calling `ghub-graphql' (which see) with `gitlab' as FORGE."
-  (ghub-graphql graphql variables :forge 'gitlab
-                :username username :auth auth :host host
-                :headers headers :silent silent
-                :callback callback :errorback errorback
-                :value value :extra extra))
-
-(cl-defun glab-repository-id (owner name &key username auth host)
-  "Return the id of the repository specified by OWNER, NAME and HOST."
-  (number-to-string
-   (cdr (assq 'id (glab-get (format "/projects/%s%%2F%s"
-                                    (string-replace "/" "%2F" owner)
-                                    name)
-                            nil :username username :auth auth :host host)))))
-
-;;; _
-(provide 'glab)
-;;; glab.el ends here
diff --git a/elpa/ghub-20250509.1440/gogs.el b/elpa/ghub-20250509.1440/gogs.el
deleted file mode 100644 (file)
index e337878..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-;;; gogs.el --- Client library for the Gogs API  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Gogs is a library that provides basic support for using the Gogs API
-;; from Emacs packages.  It abstracts access to API resources using only
-;; a handful of functions that are not resource-specific.
-
-;; This library is implemented on top of Ghub.  Unlike Ghub, Gogs does
-;; not support the guided creation of tokens because Gogs lacks the
-;; features that would be necessary to implement that.  Users have to
-;; create tokens through the web interface.
-
-;;; Code:
-
-(require 'ghub)
-
-(defconst gogs-default-host "localhost:3000/api/v1"
-  "The default Gogs host.")
-
-;; HEAD does not appear to be supported.
-
-(cl-defun gogs-get (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `GET' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"GET\" as METHOD
-and `gogs' as FORGE."
-  (declare (obsolete ghub-get "4.3.1"))
-  (ghub-request "GET" resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-put (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PUT\" as METHOD
-and `gogs' as FORGE."
-  (declare (obsolete ghub-put "4.3.1"))
-  (ghub-request "PUT" resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-post (resource &optional params
-                              &key query payload headers
-                              silent unpaginate noerror reader
-                              username auth host
-                              callback errorback extra)
-  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"POST\" as METHOD
-and `gogs' as FORGE."
-  (declare (obsolete ghub-post "4.3.1"))
-  (ghub-request "POST" resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-patch (resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a `PATCH' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PATCH\" as METHOD
-and `gogs' as FORGE."
-  (declare (obsolete ghub-patch "4.3.1"))
-  (ghub-request "PATCH" resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-delete (resource &optional params
-                                &key query payload headers
-                                silent unpaginate noerror reader
-                                username auth host
-                                callback errorback extra)
-  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"DELETE\" as METHOD
-and `gogs' as FORGE."
-  (declare (obsolete ghub-delete "4.3.1"))
-  (ghub-request "DELETE" resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-request (method resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a request for RESOURCE and return the response body.
-Like calling `ghub-request' (which see) with `gogs' as FORGE."
-  (declare (obsolete ghub-request "4.3.1"))
-  (ghub-request method resource params :forge 'gogs
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gogs-repository-id (owner name &key username auth host)
-  "Return the id of the repository specified by OWNER, NAME and HOST."
-  (number-to-string
-   (cdr (assq 'id (ghub-get (format "/repos/%s/%s" owner name)
-                            nil :forge 'gogs
-                            :username username :auth auth :host host)))))
-
-;;; _
-(provide 'gogs)
-;;; gogs.el ends here
diff --git a/elpa/ghub-20250509.1440/gsexp.el b/elpa/ghub-20250509.1440/gsexp.el
deleted file mode 100644 (file)
index a1fac79..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-;;; gsexp.el --- GraphQl as S-expressions  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This library encodes S-expressions as GraphQl documents.  Currently
-;; it is rather incomplete and only intended for use by `ghub-graphql'
-;; but I might fill the gaps and add documentation eventually.  I am
-;; not in a hurry though.
-
-;;; Code:
-
-(require 'cl-lib)
-
-(defvar gsexp-one-variable-per-line nil)
-
-(defun gsexp-encode (document)
-  (gsexp--pp (gsexp--encode-field document)))
-
-(defun gsexp--encode-field (field)
-  (cond
-   ((stringp field)
-    field)
-   ((symbolp field)
-    (symbol-name field))
-   ((listp (car field))
-    (concat (format "%s: " (caar field))
-            (gsexp--encode-field (cons (car (cdar field))
-                                       (cdr field)))))
-   ((concat
-     (pcase (pop field)
-       (`[] "")
-       ((and (pred symbolp) op) (symbol-name op))
-       (`[,op] (symbol-name op))
-       (`[,op ,name] (format "%s %s" op name)))
-     (and (vectorp (car field))
-          (format " (%s%s)"
-                  (if gsexp-one-variable-per-line "\n" "")
-                  (mapconcat #'gsexp--encode-argument
-                             (append (pop field) nil)
-                             (if gsexp-one-variable-per-line ",\n" ","))))
-     (and field
-          (format " {\n%s\n}"
-                  (mapconcat #'gsexp--encode-field field "\n")))))))
-
-(cl-defun gsexp--encode-argument ((argument value))
-  (format "%s: %s" argument (gsexp--encode-value value)))
-
-(defun gsexp--encode-value (value)
-  (cond
-   ((numberp value)
-    (number-to-string value))
-   ((symbolp value) ; including variables, enums, booleans and null
-    (symbol-name value))
-   ((stringp value)
-    (prin1-to-string value))
-   ((vectorp value)
-    (format "(%s)" (mapconcat #'gsexp--encode-value value "")))
-   ((listp value)
-    (format "{%s}" (mapconcat
-                    (pcase-lambda (`(,name ,value))
-                      (format "%s: %s" name (gsexp--encode-value value)))
-                    value ", ")))
-   ((error "Invalid field value: %S" value))))
-
-(defun gsexp--pp (string)
-  (with-temp-buffer
-    (save-excursion
-      (insert string))
-    (while (< (point) (point-max))
-      (unless (and (bolp) (eolp))
-        (save-excursion
-          (let ((level (car (syntax-ppss (line-beginning-position)))))
-            (when (looking-at "\\s-*\\s)")
-              (cl-decf level))
-            (indent-line-to (* 2 level)))))
-      (forward-line 1))
-    (buffer-string)))
-
-;;; _
-(provide 'gsexp)
-;;; gsexp.el ends here
diff --git a/elpa/ghub-20250509.1440/gtea.el b/elpa/ghub-20250509.1440/gtea.el
deleted file mode 100644 (file)
index 4728c04..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-;;; gtea.el --- Client library for the Gitea API  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2016-2025 Jonas Bernoulli
-
-;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
-;; Homepage: https://github.com/magit/ghub
-;; Keywords: tools
-
-;; SPDX-License-Identifier: GPL-3.0-or-later
-
-;; This file is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published
-;; by the Free Software Foundation, either version 3 of the License,
-;; or (at your option) any later version.
-;;
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Gtea is a library that provides basic support for using the Gitea API
-;; from Emacs packages.  It abstracts access to API resources using only
-;; a handful of functions that are not resource-specific.
-
-;; This library is implemented on top of Ghub.  Unlike Ghub, Gtea does
-;; not support the guided creation of tokens because Gitea lacks the
-;; features that would be necessary to implement that.  Users have to
-;; create tokens through the web interface.
-
-;;; Code:
-
-(require 'ghub)
-
-(defconst gtea-default-host "localhost:3000/api/v1"
-  "The default Gitea host.")
-
-;; HEAD does not appear to be supported.
-
-(cl-defun gtea-get (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `GET' request for RESOURCE, with optional query PARAMS.
-Like calling `ghub-request' (which see) with \"GET\" as METHOD
-and `gitea' as FORGE."
-  (declare (obsolete ghub-get "4.3.1"))
-  (ghub-request "GET" resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-put (resource &optional params
-                             &key query payload headers
-                             silent unpaginate noerror reader
-                             username auth host
-                             callback errorback extra)
-  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PUT\" as METHOD
-and `gitea' as FORGE."
-  (declare (obsolete ghub-put "4.3.1"))
-  (ghub-request "PUT" resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-post (resource &optional params
-                              &key query payload headers
-                              silent unpaginate noerror reader
-                              username auth host
-                              callback errorback extra)
-  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"POST\" as METHOD
-and `gitea' as FORGE."
-  (declare (obsolete ghub-post "4.3.1"))
-  (ghub-request "POST" resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-patch (resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a `PATCH' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"PATCH\" as METHOD
-and `gitea' as FORGE."
-  (declare (obsolete ghub-patch "4.3.1"))
-  (ghub-request "PATCH" resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-delete (resource &optional params
-                                &key query payload headers
-                                silent unpaginate noerror reader
-                                username auth host
-                                callback errorback extra)
-  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
-Like calling `ghub-request' (which see) with \"DELETE\" as METHOD
-and `gitea' as FORGE."
-  (declare (obsolete ghub-delete "4.3.1"))
-  (ghub-request "DELETE" resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-request (method resource &optional params
-                               &key query payload headers
-                               silent unpaginate noerror reader
-                               username auth host
-                               callback errorback extra)
-  "Make a request for RESOURCE and return the response body.
-Like calling `ghub-request' (which see) with `gitea' as FORGE."
-  (declare (obsolete ghub-request "4.3.1"))
-  (ghub-request method resource params :forge 'gitea
-                :query query :payload payload :headers headers
-                :silent silent :unpaginate unpaginate
-                :noerror noerror :reader reader
-                :username username :auth auth :host host
-                :callback callback :errorback errorback :extra extra))
-
-(cl-defun gtea-repository-id (owner name &key username auth host)
-  "Return the id of the repository specified by OWNER, NAME and HOST."
-  (number-to-string
-   (cdr (assq 'id (ghub-get (format "/repos/%s/%s" owner name)
-                            nil :forge 'gitea
-                            :username username :auth auth :host host)))))
-
-;;; _
-(provide 'gtea)
-;;; gtea.el ends here
diff --git a/elpa/ghub-20251130.1842/.dir-locals.el b/elpa/ghub-20251130.1842/.dir-locals.el
new file mode 100644 (file)
index 0000000..aff6808
--- /dev/null
@@ -0,0 +1,9 @@
+((nil
+  (indent-tabs-mode . nil))
+ (makefile-mode
+  (indent-tabs-mode . t))
+ (git-commit-mode
+  (git-commit-major-mode . git-commit-elisp-text-mode))
+ ("CHANGELOG"
+  (nil (fill-column . 70)
+       (mode . display-fill-column-indicator))))
diff --git a/elpa/ghub-20251130.1842/dir b/elpa/ghub-20251130.1842/dir
new file mode 100644 (file)
index 0000000..b703bca
--- /dev/null
@@ -0,0 +1,18 @@
+This is the file .../info/dir, which contains the
+topmost node of the Info hierarchy, called (dir)Top.
+The first time you invoke Info you start off looking at this node.
+\1f
+File: dir,     Node: Top       This is the top of the INFO tree
+
+  This (the Directory node) gives a menu of major topics.
+  Typing "q" exits, "H" lists all Info commands, "d" returns here,
+  "h" gives a primer for first-timers,
+  "mEmacs<Return>" visits the Emacs manual, etc.
+
+  In Emacs, you can click mouse button 2 on a menu item or cross reference
+  to select it.
+
+* Menu:
+
+Emacs
+* Ghub: (ghub).                 Client library for the Github API.
diff --git a/elpa/ghub-20251130.1842/ghub-autoloads.el b/elpa/ghub-20251130.1842/ghub-autoloads.el
new file mode 100644 (file)
index 0000000..3e17aff
--- /dev/null
@@ -0,0 +1,52 @@
+;;; ghub-autoloads.el --- automatically extracted autoloads (do not edit)   -*- lexical-binding: t -*-
+;; Generated by the `loaddefs-generate' function.
+
+;; This file is part of GNU Emacs.
+
+;;; Code:
+
+(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
+
+
+\f
+;;; Generated autoloads from ghub.el
+
+(autoload 'ghub-clear-caches "ghub" "\
+Clear all caches that might negatively affect Ghub.
+
+If a library that is used by Ghub caches incorrect information
+such as a mistyped password, then that can prevent Ghub from
+asking the user for the correct information again.
+
+Set `url-http-real-basic-auth-storage' to nil
+and call `auth-source-forget+'." t)
+(register-definition-prefixes "ghub" '("auth-source-netrc-parse" "ghub-"))
+
+\f
+;;; Generated autoloads from ghub-graphql.el
+
+(register-definition-prefixes "ghub-graphql" '("ghub-"))
+
+\f
+;;; Generated autoloads from ghub-legacy.el
+
+(register-definition-prefixes "ghub-legacy" '("ghub-fetch-repository"))
+
+\f
+;;; Generated autoloads from gsexp.el
+
+(register-definition-prefixes "gsexp" '("gsexp-"))
+\f
+;;; End of scraped data
+
+(provide 'ghub-autoloads)
+
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; no-native-compile: t
+;; coding: utf-8-emacs-unix
+;; End:
+
+;;; ghub-autoloads.el ends here
diff --git a/elpa/ghub-20251130.1842/ghub-graphql.el b/elpa/ghub-20251130.1842/ghub-graphql.el
new file mode 100644 (file)
index 0000000..adaaa24
--- /dev/null
@@ -0,0 +1,352 @@
+;;; ghub-graphql.el --- Access Github API using GraphQL  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2016-2025 Jonas Bernoulli
+
+;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
+;; Homepage: https://github.com/magit/ghub
+;; Keywords: tools
+
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;; This file is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library implements GraphQL queries for Github.
+
+;;; Code:
+
+(require 'ghub)
+(require 'gsexp)
+(require 'treepy)
+
+(eval-when-compile (require 'subr-x))
+
+(define-error 'ghub-graphql-error "GraphQL Error" 'ghub-error)
+
+(defvar ghub-graphql-message-progress nil
+  "Whether to show \"Fetching page N...\" in echo area during requests.
+By default this information is only shown in the mode-line of the buffer
+from which the request was initiated, and if you kill that buffer, then
+nowhere.  That may make it desirable to display the same message in the
+echo area as well.")
+
+(defvar ghub-graphql-items-per-request 50
+  "Number of GraphQL items to query for entities that return a collection.
+
+Adjust this value if you're hitting query timeouts against larger
+repositories.")
+
+(cl-defun ghub-graphql-rate-limit (&key username auth host)
+  "Return rate limit information."
+  (let-alist (ghub-query
+              '(query (rateLimit limit cost remaining resetAt)) nil
+              :synchronous t :username username :auth auth :host host)
+    .data.rateLimit))
+
+(cl-defstruct (ghub--graphql-req
+               (:include ghub--req)
+               (:constructor ghub--make-graphql-req)
+               (:copier nil))
+  (query     nil :read-only t)
+  (query-str nil :read-only nil)
+  (variables nil :read-only t)
+  (until     nil :read-only t)
+  (pages     0   :read-only nil)
+  (paginate  nil :read-only nil)
+  (narrow    nil :read-only t))
+
+(cl-defun ghub-query
+    (query &optional variables
+           &key until narrow headers paginate
+           callback errorback noerror synchronous
+           username auth host forge)
+  (declare (indent defun))
+  (unless forge
+    (setq forge 'github))
+  (unless host
+    (setq host (ghub--host forge)))
+  (unless (or username (stringp auth) (eq auth 'none))
+    (setq username (ghub--username host forge)))
+  (when (eq callback 'pp)
+    (setq callback #'ghub--graphql-pp-response)
+    (setq noerror t))
+  (ghub--graphql-retrieve
+   (ghub--make-graphql-req
+    :url         (ghub--encode-url
+                  host (if (eq forge 'gitlab) "/api/graphql" "/graphql"))
+    :method      "POST"
+    :headers     (ghub--headers headers host auth username forge)
+    :handler     #'ghub--graphql-handle-response
+    :query       query
+    :variables   variables
+    :until       until
+    :buffer      (current-buffer)
+    :narrow      narrow
+    :paginate    (or paginate
+                     (and-let* ((p (and (eq auth 'forge)
+                                        (fboundp 'magit-get)
+                                        (magit-get "forge.graphqlItemLimit"))))
+                       (string-to-number p)))
+    :noerror     noerror
+    :synchronous synchronous
+    :callback    callback
+    :errorback   errorback)))
+
+(cl-defun ghub--graphql-retrieve (req &optional lineage cursor)
+  (let ((p (cl-incf (ghub--graphql-req-pages req))))
+    (when (> p 1)
+      (when ghub-graphql-message-progress
+        (let ((message-log-max nil))
+          (message "Fetching page %s..." p)))
+      (ghub--graphql-set-mode-line req "Fetching page %s" p)))
+  (setf (ghub--graphql-req-query-str req)
+        (gsexp-encode
+         (ghub--graphql-prepare-query
+          (ghub--graphql-req-query req)
+          lineage cursor)))
+  (when ghub-debug
+    (with-current-buffer (get-buffer-create " *gsexp-encode*")
+      (erase-buffer)
+      (insert (ghub--graphql-req-query-str req) "\n\n")
+      (let ((pos (point)))
+        (insert (ghub--encode-payload (ghub--graphql-req-variables req)) "\n")
+        (ignore-errors (json-pretty-print pos (point))))))
+  (ghub--retrieve
+   (ghub--encode-payload
+    `((query . ,(ghub--graphql-req-query-str req))
+      ,@(and-let* ((variables (ghub--graphql-req-variables req)))
+          `((variables . ,variables)))))
+   req)
+  (ghub--req-value req))
+
+(defun ghub--graphql-prepare-query (query &optional lineage cursor paginate)
+  (when lineage
+    (setq query (ghub--graphql-narrow-query query lineage cursor)))
+  (let ((loc (ghub--alist-zip query))
+        variables)
+    (catch :done
+      (while t
+        (let ((node (treepy-node loc)))
+          (when (and (vectorp node)
+                     (listp (aref node 0)))
+            (let ((alist (append node ()))
+                  (vars nil))
+              (when-let ((edges (cadr (assq :edges alist))))
+                (push (list 'first
+                            (apply
+                             #'min
+                             (delq nil (list (and (numberp edges) edges)
+                                             paginate
+                                             ghub-graphql-items-per-request))))
+                      vars)
+                (setq loc  (treepy-up loc))
+                (setq node (treepy-node loc))
+                (setq loc  (treepy-replace
+                            loc `(,(car  node)
+                                  ,(cadr node)
+                                  (pageInfo endCursor hasNextPage)
+                                  (edges (node ,@(cddr node))))))
+                (setq loc  (treepy-down loc))
+                (setq loc  (treepy-next loc)))
+              (dolist (elt alist)
+                (cond ((keywordp (car elt)))
+                      ((length= elt 3)
+                       (push (list (nth 0 elt) (nth 1 elt)) vars)
+                       (push (list (nth 1 elt) (nth 2 elt)) variables))
+                      ((length= elt 2)
+                       (push elt vars))))
+              (setq loc (treepy-replace loc (vconcat (nreverse vars)))))))
+        (if (treepy-end-p loc)
+            (let ((node (copy-sequence (treepy-node loc))))
+              (when variables
+                (push (vconcat (nreverse variables))
+                      (cdr node)))
+              (throw :done node))
+          (setq loc (treepy-next loc)))))))
+
+(defun ghub--graphql-handle-response (status req)
+  (let ((buf (current-buffer)))
+    (unwind-protect
+        (progn
+          (set-buffer-multibyte t)
+          (let* ((headers (ghub--handle-response-headers status req))
+                 (payload (ghub--handle-response-payload req))
+                 (err     (plist-get status :error))
+                 (errors  (and (not (and (ghub--req-noerror req)
+                                         (assq 'data payload)))
+                               (assq 'errors payload))))
+            (cond ((or err errors)
+                   (when (and (not err) ghub-debug)
+                     (ignore-errors (json-pretty-print (point) (point-max)))
+                     (pop-to-buffer buf))
+                   (ghub--graphql-handle-failure
+                    req (or err errors) headers status))
+                  ((ghub--graphql-walk-response req (assq 'data payload))))))
+      (when (and (buffer-live-p buf)
+                 (not (buffer-local-value 'ghub-debug buf)))
+        (kill-buffer buf)))))
+
+(defun ghub--graphql-handle-failure (req errors headers status)
+  (ghub--graphql-set-mode-line req)
+  (setf (ghub--req-value req) errors)
+  (cond-let
+    ([errorback (ghub--req-errorback req)]
+     (ghub--graphql-run-callback req errorback errors headers status req))
+    ((ghub--req-noerror req)
+     (when-let ((callback (ghub--req-callback req)))
+       (ghub--graphql-run-callback req callback errors)))
+    ((ghub--signal-error (if (eq (car errors) 'errors)
+                             (cons 'ghub-graphql-error (cdr errors))
+                           errors)))))
+
+(defun ghub--graphql-handle-success (req data)
+  (ghub--graphql-set-mode-line req)
+  (when-let ((narrow (ghub--graphql-req-narrow req)))
+    (while-let ((key (pop narrow)))
+      (setq data (cdr (assq key data)))))
+  (setf (ghub--req-value req) data)
+  (when-let ((callback (ghub--req-callback req)))
+    (ghub--graphql-run-callback req callback data)))
+
+(defun ghub--graphql-run-callback (req callback &rest args)
+  (let ((buffer (ghub--req-buffer req)))
+    (if (buffer-live-p buffer)
+        (with-current-buffer buffer
+          (apply callback args))
+      (apply callback args))))
+
+(defun ghub--graphql-set-mode-line (req &optional format &rest args)
+  (let ((buffer (ghub--graphql-req-buffer req)))
+    (when (buffer-live-p buffer)
+      (with-current-buffer buffer
+        (setq mode-line-process
+              (and format (concat " " (apply #'format format args))))
+        (force-mode-line-update t)))))
+
+(defun ghub--graphql-pp-response (data)
+  (pp-display-expression data "*Pp Eval Output*"))
+
+(defun ghub--graphql-walk-response (req data)
+  (let* ((loc (ghub--req-value req))
+         (loc (if (not loc)
+                  (ghub--alist-zip data)
+                (setq data (ghub--graphql-narrow-data
+                            data (ghub--graphql-lineage loc)))
+                (setf (alist-get 'edges data)
+                      (append (alist-get 'edges (treepy-node loc))
+                              (or (alist-get 'edges data)
+                                  (error "BUG: Expected new nodes"))))
+                (treepy-replace loc data))))
+    (catch :done
+      (while t
+        (when (eq (car-safe (treepy-node loc)) 'edges)
+          (setq loc (treepy-up loc))
+          (pcase-let ((`(,key . ,val) (treepy-node loc)))
+            (let-alist val
+              (let* ((cursor (and .pageInfo.hasNextPage
+                                  .pageInfo.endCursor))
+                     (until  (cdr (assq (intern (format "%s-until" key))
+                                        (ghub--graphql-req-until req))))
+                     (nodes  (mapcar #'cdar .edges))
+                     (nodes  (if until
+                                 (seq-take-while
+                                  (lambda (node)
+                                    (or (string> (cdr (assq 'updatedAt node))
+                                                 until)
+                                        (setq cursor nil)))
+                                  nodes)
+                               nodes)))
+                (cond (cursor
+                       (setf (ghub--req-value req) loc)
+                       (ghub--graphql-retrieve req
+                                               (ghub--graphql-lineage loc)
+                                               cursor)
+                       (throw :done nil))
+                      ((setq loc (treepy-replace loc (cons key nodes)))))))))
+        (if (treepy-end-p loc)
+            (progn (ghub--graphql-handle-success req (treepy-root loc))
+                   (throw :done nil))
+          (setq loc (treepy-next loc)))))))
+
+(defun ghub--graphql-lineage (loc)
+  (let (lineage)
+    (while (treepy-up loc)
+      (push (car (treepy-node loc)) lineage)
+      (setq loc (treepy-up loc)))
+    lineage))
+
+(defun ghub--graphql-narrow-data (data lineage)
+  (while-let ((key (pop lineage)))
+    (if (consp (car lineage))
+        (progn (pop lineage)
+               (setf data (cadr data)))
+      (setq data (assq key (cdr data)))))
+  data)
+
+(defun ghub--graphql-narrow-query (query lineage &optional cursor)
+  (if (consp (car lineage))
+      (let* ((child  (cddr query))
+             (alist  (append (cadr query) ()))
+             (single (cdr (assq :singular alist))))
+        `(,(car single)
+          ,(vector (list (cadr single) (cdr (car lineage))))
+          ,@(if (cdr lineage)
+                (ghub--graphql-narrow-query child (cdr lineage) cursor)
+              child)))
+    (let* ((child  (or (assq (car lineage) (cdr query))
+                       ;; Alias
+                       (cl-find-if (lambda (c)
+                                     (eq (car-safe (car-safe c))
+                                         (car lineage)))
+                                   query)
+                       ;; Edges
+                       (cl-find-if (lambda (c)
+                                     (and (listp c)
+                                          (vectorp (cadr c))
+                                          (eq (cadr (assq :singular
+                                                          (append (cadr c) ())))
+                                              (car lineage))))
+                                   (cdr query))
+                       (error "BUG: Failed to narrow query")))
+           (object (car query))
+           (args   (and (vectorp (cadr query))
+                        (cadr query))))
+      `(,object
+        ,@(and args (list args))
+        ,(cond ((cdr lineage)
+                (ghub--graphql-narrow-query child (cdr lineage) cursor))
+               (cursor
+                `(,(car child)
+                  ,(vconcat `((after ,cursor))
+                            (cadr child))
+                  ,@(cddr child)))
+               (t
+                child))))))
+
+(defun ghub--alist-zip (root)
+  (let ((branchp (##and (listp %) (listp (cdr %))))
+        (make-node (lambda (_ children) children)))
+    (treepy-zipper branchp #'identity make-node root)))
+
+;;; _
+;; Local Variables:
+;; read-symbol-shorthands: (
+;;   ("and-let"   . "cond-let--and-let")
+;;   ("if-let"    . "cond-let--if-let")
+;;   ("when-let"  . "cond-let--when-let")
+;;   ("while-let" . "cond-let--while-let"))
+;; End:
+(provide 'ghub-graphql)
+;;; ghub-graphql.el ends here
diff --git a/elpa/ghub-20251130.1842/ghub-legacy.el b/elpa/ghub-20251130.1842/ghub-legacy.el
new file mode 100644 (file)
index 0000000..4c46b3c
--- /dev/null
@@ -0,0 +1,377 @@
+;;; ghub-legacy.el --- Deprecated Ghub functions  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2016-2025 Jonas Bernoulli
+
+;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
+;; Homepage: https://github.com/magit/ghub
+;; Keywords: tools
+
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;; This file is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Deprecated Ghub functions.
+
+;;; Code:
+
+(require 'ghub-graphql)
+
+(cl-defun ghub-graphql (graphql
+                        &optional variables
+                        &key username auth host forge
+                        headers silent
+                        callback errorback value extra)
+  (cl-assert (not (stringp variables)))
+  (cl-assert (or (stringp graphql)
+                 (memq (car-safe graphql) '(query mutation))))
+  (unless (stringp graphql)
+    (setq graphql (gsexp-encode (ghub--graphql-prepare-query graphql))))
+  (ghub-request "POST"
+                (if (eq forge 'gitlab) "/api/graphql" "/graphql")
+                nil
+                :payload `((query . ,graphql)
+                           ,@(and variables `((variables ,@variables))))
+                :headers headers :silent silent
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback
+                :extra extra :value value))
+
+(cl-defun ghub--graphql (graphql
+                         &optional variables
+                         &key username auth host forge
+                         headers
+                         callback errorback)
+  (ghub--graphql-vacuum graphql variables callback nil
+                        :username  username
+                        :auth      auth
+                        :host      host
+                        :forge     forge
+                        :headers   headers
+                        :errorback errorback))
+
+(cl-defun ghub--graphql-vacuum
+    ( query variables callback
+      &optional until
+      &key narrow username auth host forge
+      headers paginate errorback noerror synchronous)
+  (ghub-query query variables
+    :until until :narrow narrow :headers headers :paginate paginate
+    :callback callback
+    :errorback errorback :noerror noerror :synchronous synchronous
+    :username username :auth auth :host host :forge forge))
+
+(defconst ghub-fetch-repository-sparse
+  '(query
+    (repository
+     [(owner $owner String!)
+      (name  $name  String!)]
+     name
+     id
+     createdAt
+     updatedAt
+     nameWithOwner
+     (parent nameWithOwner)
+     description
+     homepageUrl
+     (defaultBranchRef name)
+     isArchived
+     isFork
+     isLocked
+     isMirror
+     isPrivate
+     hasDiscussionsEnabled
+     hasIssuesEnabled
+     hasWikiEnabled
+     (licenseInfo name)
+     (stargazers totalCount)
+     (watchers totalCount))))
+
+(defconst ghub-fetch-repository
+  `(query
+    (repository
+     ,@(cdr (cadr ghub-fetch-repository-sparse))
+     (assignableUsers [(:edges t)]
+                      id
+                      login
+                      name)
+     (discussionCategories [(:edges t)]
+                           id
+                           name
+                           emoji
+                           isAnswerable
+                           description)
+     (discussions    [(:edges t)
+                      (:singular discussion number)
+                      (orderBy ((field UPDATED_AT) (direction DESC)))]
+                     id
+                     databaseId
+                     number
+                     url
+                     stateReason
+                     ;; Discussions lack isReadByViewer.
+                     (answer id)
+                     (author login)
+                     title
+                     createdAt
+                     updatedAt
+                     closedAt
+                     locked
+                     (category id)
+                     body
+                     (comments  [(:edges t)]
+                                id
+                                databaseId
+                                (author login)
+                                createdAt
+                                updatedAt
+                                body
+                                (replies [(:edges 20)]
+                                         id
+                                         databaseId
+                                         (author login)
+                                         createdAt
+                                         updatedAt
+                                         body))
+                     (labels    [(:edges t)]
+                                id))
+     (issues         [(:edges t)
+                      (:singular issue number)
+                      (orderBy ((field UPDATED_AT) (direction DESC)))]
+                     number
+                     id
+                     state
+                     stateReason
+                     isReadByViewer
+                     (author login)
+                     title
+                     createdAt
+                     updatedAt
+                     closedAt
+                     locked
+                     (milestone id)
+                     body
+                     (assignees [(:edges t)]
+                                id)
+                     (comments  [(:edges t)]
+                                id
+                                databaseId
+                                (author login)
+                                createdAt
+                                updatedAt
+                                body)
+                     (labels    [(:edges t)]
+                                id))
+     (labels         [(:edges t)
+                      (:singular label id)]
+                     id
+                     name
+                     color
+                     description)
+     (milestones     [(:edges t)
+                      (:singular milestone id)]
+                     id
+                     number
+                     title
+                     createdAt
+                     updatedAt
+                     dueOn
+                     closedAt
+                     description)
+     (pullRequests   [(:edges t)
+                      (:singular pullRequest number)
+                      (orderBy ((field UPDATED_AT) (direction DESC)))]
+                     number
+                     id
+                     state
+                     isReadByViewer
+                     (author login)
+                     title
+                     createdAt
+                     updatedAt
+                     closedAt
+                     mergedAt
+                     isDraft
+                     locked
+                     maintainerCanModify
+                     isCrossRepository
+                     (milestone id)
+                     body
+                     (baseRef name
+                              (repository nameWithOwner))
+                     baseRefOid
+                     (headRef name
+                              (repository (owner login)
+                                          nameWithOwner))
+                     headRefOid
+                     (assignees [(:edges t)]
+                                id)
+                     (reviewRequests [(:edges t)]
+                                     (requestedReviewer "... on User { id }\n"))
+                     (comments  [(:edges t)]
+                                id
+                                databaseId
+                                (author login)
+                                createdAt
+                                updatedAt
+                                body)
+                     (labels    [(:edges t)]
+                                id)))))
+
+(defconst ghub-fetch-repository-review-threads
+  '(query
+    (repository
+     [(owner $owner String!)
+      (name  $name  String!)]
+     (pullRequests   [(:edges t)
+                      (:singular pullRequest number)
+                      (orderBy ((field UPDATED_AT) (direction DESC)))]
+                     number
+                     baseRefOid
+                     headRefOid
+                     (reviewThreads [(:edges t)]
+                                    id
+                                    line
+                                    originalLine
+                                    diffSide
+                                    (resolvedBy login)
+                                    (comments [(:edges t)]
+                                              id
+                                              databaseId
+                                              (author login)
+                                              createdAt
+                                              updatedAt
+                                              body
+                                              (replyTo databaseId)
+                                              (originalCommit oid)
+                                              path))))))
+
+(cl-defun ghub-fetch-repository ( owner name callback
+                                  &optional until
+                                  &key username auth host forge
+                                  headers paginate errorback sparse)
+  "Asynchronously fetch forge data about the specified repository.
+Once all data has been collected, CALLBACK is called with the
+data as the only argument."
+  (ghub-query (if sparse
+                  ghub-fetch-repository-sparse
+                ghub-fetch-repository)
+              `((owner . ,owner)
+                (name  . ,name))
+              :until     until
+              :narrow    '(repository)
+              :username  username
+              :auth      auth
+              :host      host
+              :forge     forge
+              :headers   headers
+              :paginate  paginate
+              :callback  callback
+              :errorback errorback))
+
+(cl-defun ghub-fetch-discussion ( owner name number callback
+                                  &optional until
+                                  &key username auth host forge
+                                  headers errorback)
+  "Asynchronously fetch forge data about the specified discussion.
+Once all data has been collected, CALLBACK is called with the
+data as the only argument."
+  (ghub-query (ghub--graphql-prepare-query
+               ghub-fetch-repository
+               `(repository discussions (discussion . ,number)))
+              `((owner . ,owner)
+                (name  . ,name))
+              :until     until
+              :narrow    '(repository discussion)
+              :username  username
+              :auth      auth
+              :host      host
+              :forge     forge
+              :headers   headers
+              :callback  callback
+              :errorback errorback))
+
+(cl-defun ghub-fetch-issue ( owner name number callback
+                             &optional until
+                             &key username auth host forge
+                             headers paginate errorback)
+  "Asynchronously fetch forge data about the specified issue.
+Once all data has been collected, CALLBACK is called with the
+data as the only argument."
+  (ghub-query (ghub--graphql-narrow-query
+               ghub-fetch-repository
+               `(repository issues (issue . ,number)))
+              `((owner . ,owner)
+                (name  . ,name))
+              :until     until
+              :narrow    '(repository issue)
+              :username  username
+              :auth      auth
+              :host      host
+              :forge     forge
+              :headers   headers
+              :paginate  paginate
+              :callback  callback
+              :errorback errorback))
+
+(cl-defun ghub-fetch-pullreq ( owner name number callback
+                               &optional until
+                               &key username auth host forge
+                               headers paginate errorback)
+  "Asynchronously fetch forge data about the specified pull-request.
+Once all data has been collected, CALLBACK is called with the
+data as the only argument."
+  (ghub-query (ghub--graphql-narrow-query
+               ghub-fetch-repository
+               `(repository pullRequests (pullRequest . ,number)))
+              `((owner . ,owner)
+                (name  . ,name))
+              :until     until
+              :narrow    '(repository pullRequest)
+              :username  username
+              :auth      auth
+              :host      host
+              :forge     forge
+              :headers   headers
+              :paginate  paginate
+              :callback  callback
+              :errorback errorback))
+
+(cl-defun ghub-fetch-review-threads ( owner name number callback
+                                      &optional until
+                                      &key username auth host forge
+                                      headers paginate errorback)
+  "Asynchronously fetch forge data about the review threads from a pull-request.
+Once all data has been collected, CALLBACK is called with the
+data as the only argument."
+  (ghub-query (ghub--graphql-narrow-query
+               ghub-fetch-repository-review-threads
+               `(repository pullRequests (pullRequest . ,number)))
+              `((owner . ,owner)
+                (name  . ,name))
+              :until     until
+              :narrow    '(repository pullRequest)
+              :username  username
+              :auth      auth
+              :host      host
+              :forge     forge
+              :headers   headers
+              :paginate  paginate
+              :callback  callback
+              :errorback errorback))
+
+;;; _
+(provide 'ghub-legacy)
+;;; ghub-legacy.el ends here
diff --git a/elpa/ghub-20251130.1842/ghub-pkg.el b/elpa/ghub-20251130.1842/ghub-pkg.el
new file mode 100644 (file)
index 0000000..432944d
--- /dev/null
@@ -0,0 +1,14 @@
+;; -*- no-byte-compile: t; lexical-binding: nil -*-
+(define-package "ghub" "20251130.1842"
+  "Client libraries for Git forge APIs."
+  '((emacs    "29.1")
+    (compat   "30.1")
+    (cond-let "0.2")
+    (llama    "1.0")
+    (treepy   "0.1.2"))
+  :url "https://github.com/magit/ghub"
+  :commit "9f416605d560ed2a6b62a87d1f624549901b1102"
+  :revdesc "9f416605d560"
+  :keywords '("tools")
+  :authors '(("Jonas Bernoulli" . "emacs.ghubNOSPAMjonas.bernoulli.dev"))
+  :maintainers '(("Jonas Bernoulli" . "emacs.ghubNOSPAMjonas.bernoulli.dev")))
diff --git a/elpa/ghub-20251130.1842/ghub.el b/elpa/ghub-20251130.1842/ghub.el
new file mode 100644 (file)
index 0000000..317fe32
--- /dev/null
@@ -0,0 +1,826 @@
+;;; ghub.el --- Client libraries for Git forge APIs  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2016-2025 Jonas Bernoulli
+
+;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
+;; Homepage: https://github.com/magit/ghub
+;; Keywords: tools
+
+;; Package-Version: 20251130.1842
+;; Package-Revision: 9f416605d560
+;; Package-Requires: (
+;;     (emacs   "29.1")
+;;     (compat  "30.1")
+;;     (cond-let "0.2")
+;;     (llama    "1.0")
+;;     (treepy "0.1.2"))
+
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;; This file is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Ghub provides basic support for using the APIs of various Git forges
+;; from Emacs packages.  Originally it only supported the Github REST
+;; API, but now it also supports the Github GraphQL API as well as the
+;; REST APIs of Gitlab, Gitea, Gogs and Bitbucket.
+
+;; Ghub abstracts access to API resources using only a handful of basic
+;; functions such as `ghub-get'.  These are convenience wrappers around
+;; `ghub-request'.
+
+;; When accessing Github, then Ghub handles the creation and storage of
+;; access tokens using a setup wizard to make it easier for users to get
+;; started.  The tokens for other forges have to be created manually.
+
+;; Ghub is intentionally limited to only provide these two essential
+;; features — basic request functions and guided setup — to avoid being
+;; too opinionated, which would hinder wide adoption.  It is assumed that
+;; wide adoption would make life easier for users and maintainers alike,
+;; because then all packages that talk to forge APIs could be configured
+;; the same way.
+
+;; Please consult the manual (info "ghub") for more information.
+
+;;; Code:
+
+(require 'auth-source)
+(require 'cl-lib)
+(require 'compat)
+(require 'cond-let)
+(require 'gnutls)
+(require 'let-alist)
+(require 'llama)
+(require 'url)
+(require 'url-auth)
+(require 'url-http)
+
+(eval-when-compile (require 'subr-x))
+
+(defvar url-callback-arguments)
+(defvar url-http-end-of-headers)
+(defvar url-http-extra-headers)
+(defvar url-http-response-status)
+
+;;; Settings
+
+(defvar ghub-default-host-alist
+  '((github    . "api.github.com")
+    (gitlab    . "gitlab.com/api/v4")
+    (gitea     . "localhost:3000/api/v1")
+    (gogs      . "localhost:3000/api/v1")
+    (bitbucket . "api.bitbucket.org/2.0"))
+  "Alist of default hosts used when the respective `FORGE.host' is not set.")
+
+(defvar ghub-github-token-scopes '(repo)
+  "The Github API scopes that your private tools need.
+
+You have to manually create or update the token at
+https://github.com/settings/tokens.  This variable
+only serves as documentation.")
+
+(defvar ghub-insecure-hosts nil
+  "List of hosts that use http instead of https.")
+
+(defvar ghub-debug nil
+  "Record additional debug information.")
+
+;;; Request
+;;;; Object
+
+(cl-defstruct (ghub--req
+               (:constructor ghub--make-req)
+               (:copier nil))
+  (url         nil :read-only nil)
+  (forge       nil :read-only t)
+  (silent      nil :read-only t)
+  (method      nil :read-only t)
+  (headers     nil :read-only t)
+  (handler     nil :read-only t)
+  (unpaginate  nil :read-only nil)
+  (noerror     nil :read-only t)
+  (reader      nil :read-only t)
+  (buffer      nil :read-only t)
+  (synchronous nil :read-only t)
+  (callback    nil :read-only t)
+  (errorback   nil :read-only t)
+  (value       nil :read-only nil)
+  (extra       nil :read-only nil))
+
+(defalias 'ghub-req-extra #'ghub--req-extra)
+
+;;;; API
+
+(define-error 'ghub-error "Ghub/Url Error" 'error)
+(define-error 'ghub-http-error "HTTP Error" 'ghub-error)
+
+(defvar ghub-response-headers nil
+  "The headers returned in response to the last request.
+`ghub-request' returns the response body and stores the
+response headers in this variable.")
+
+(cl-defun ghub-head (resource
+                     &optional params
+                     &key query payload headers
+                     silent unpaginate noerror reader
+                     username auth host
+                     callback errorback extra)
+  "Make a `HEAD' request for RESOURCE, with optional query PARAMS.
+Like calling `ghub-request' (which see) with \"HEAD\" as METHOD."
+  (ghub-request "HEAD" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-get (resource
+                    &optional params
+                    &key query payload headers
+                    silent unpaginate noerror reader
+                    username auth host forge
+                    callback errorback extra)
+  "Make a `GET' request for RESOURCE, with optional query PARAMS.
+Like calling `ghub-request' (which see) with \"GET\" as METHOD."
+  (ghub-request "GET" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-put (resource
+                    &optional params
+                    &key query payload headers
+                    silent unpaginate noerror reader
+                    username auth host forge
+                    callback errorback extra)
+  "Make a `PUT' request for RESOURCE, with optional payload PARAMS.
+Like calling `ghub-request' (which see) with \"PUT\" as METHOD."
+  (ghub-request "PUT" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-post (resource
+                     &optional params
+                     &key query payload headers
+                     silent unpaginate noerror reader
+                     username auth host forge
+                     callback errorback extra)
+  "Make a `POST' request for RESOURCE, with optional payload PARAMS.
+Like calling `ghub-request' (which see) with \"POST\" as METHOD."
+  (ghub-request "POST" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-patch (resource
+                      &optional params
+                      &key query payload headers
+                      silent unpaginate noerror reader
+                      username auth host forge
+                      callback errorback extra)
+  "Make a `PATCH' request for RESOURCE, with optional payload PARAMS.
+Like calling `ghub-request' (which see) with \"PATCH\" as METHOD."
+  (ghub-request "PATCH" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-delete (resource
+                       &optional params
+                       &key query payload headers
+                       silent unpaginate noerror reader
+                       username auth host forge
+                       callback errorback extra)
+  "Make a `DELETE' request for RESOURCE, with optional payload PARAMS.
+Like calling `ghub-request' (which see) with \"DELETE\" as METHOD."
+  (ghub-request "DELETE" resource params
+                :query query :payload payload :headers headers
+                :silent silent :unpaginate unpaginate
+                :noerror noerror :reader reader
+                :username username :auth auth :host host :forge forge
+                :callback callback :errorback errorback :extra extra))
+
+(cl-defun ghub-request ( method resource
+                         &optional params
+                         &key query payload headers
+                         silent unpaginate noerror reader
+                         username auth host forge
+                         callback errorback value extra)
+  "Make a request for RESOURCE and return the response body.
+
+Also place the response headers in `ghub-response-headers'.
+
+METHOD is the HTTP method, given as a string.
+RESOURCE is the resource to access, given as a string beginning
+  with a slash.
+
+PARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify
+  data.  The Github API documentation is vague on how data has
+  to be transmitted and for a particular resource usually just
+  talks about \"parameters\".  Generally speaking when the METHOD
+  is \"HEAD\" or \"GET\", then they have to be transmitted as a
+  query, otherwise as a payload.
+Use PARAMS to automatically transmit like QUERY or PAYLOAD would
+  depending on METHOD.
+Use QUERY to explicitly transmit data as a query.
+Use PAYLOAD to explicitly transmit data as a payload.
+  Instead of an alist, PAYLOAD may also be a string, in which
+  case it gets encoded as UTF-8 but is otherwise transmitted as-is.
+Use HEADERS for those rare resources that require that the data
+  is transmitted as headers instead of as a query or payload.
+  When that is the case, then the API documentation usually
+  mentions it explicitly.
+
+If SILENT is non-nil, then don't message progress reports and
+  the like.
+
+If UNPAGINATE is t, then make as many requests as necessary to
+  get all values.  If UNPAGINATE is a natural number, then get
+  at most that many pages.  For any other non-nil value raise
+  an error.
+If NOERROR is non-nil, then do not raise an error if the request
+  fails and return nil instead.  If NOERROR is `return', then
+  return the error payload instead of nil.
+If READER is non-nil, then it is used to read and return from the
+  response buffer.  The default is `ghub--read-json-payload'.
+  For the very few resources that do not return JSON, you might
+  want to use `ghub--decode-payload'.
+
+If USERNAME is non-nil, then make a request on behalf of that
+  user.  It is better to specify the user using the Git variable
+  `github.user' for \"api.github.com\", or `github.HOST.user' if
+  connecting to a Github Enterprise instance.
+
+Each package that uses `ghub' should use its own token.  If AUTH
+  is nil, then the generic `ghub' token is used instead.  This
+  is only acceptable for personal utilities.  A packages that
+  is distributed to other users should always use this argument
+  to identify itself, using a symbol matching its name.
+
+  Package authors who find this inconvenient should write a
+  wrapper around this function and possibly for the
+  method-specific functions as well.
+
+  Some symbols have a special meaning.  `none' means to make an
+  unauthorized request.  `basic' means to make a password based
+  request.  If the value is a string, then it is assumed to be
+  a valid token.  `basic' and an explicit token string are only
+  intended for internal and debugging uses.
+
+If HOST is non-nil, then connect to that Github instance.  This
+  defaults to \"api.github.com\".  When a repository is connected
+  to a Github Enterprise instance, then it is better to specify
+  that using the Git variable `github.host' instead of using this
+  argument.
+
+If optional FORGE is nil, then it is assumed that HOST is a
+  Github host.  When connecting to another forge type, then
+  FORGE must be one of `gitlab', `gitea', `gogs' or `bitbucket'.
+
+If CALLBACK and/or ERRORBACK is non-nil, then make one or more
+  asynchronous requests and call CALLBACK or ERRORBACK when
+  finished.  If no error occurred, then call CALLBACK, unless
+  that is nil.
+
+  If an error occurred, then call ERRORBACK, or if that is nil,
+  then CALLBACK.  ERRORBACK can also be t, in which case an error
+  is signaled instead.  NOERROR is ignored for all asynchronous
+  requests.
+
+Both callbacks are called with four arguments.
+  1. For CALLBACK, the combined value of the retrieved pages.
+     For ERRORBACK, the error that occurred when retrieving the
+     last page.
+  2. The headers of the last page as an alist.
+  3. Status information provided by `url-retrieve'. Its `:error'
+     property holds the same information as ERRORBACK's first
+     argument.
+  4. A `ghub--req' struct, which can be passed to `ghub-continue'
+     (which see) to retrieve the next page, if any."
+  (declare (indent defun))
+  (cl-assert (or (booleanp unpaginate) (natnump unpaginate)))
+  (unless (string-prefix-p "/" resource)
+    (setq resource (concat "/" resource)))
+  (unless host
+    (setq host (ghub--host forge)))
+  (unless (or username (stringp auth) (eq auth 'none))
+    (setq username (ghub--username host forge)))
+  (cond ((not params))
+        ((member method '("GET" "HEAD"))
+         (when query
+           (error "PARAMS and QUERY are mutually exclusive for METHOD %S"
+                  method))
+         (setq query params))
+        (t
+         (when payload
+           (error "PARAMS and PAYLOAD are mutually exclusive for METHOD %S"
+                  method))
+         (setq payload params)))
+  (when (or callback errorback)
+    (setq noerror t))
+  (ghub--retrieve
+   (ghub--encode-payload payload)
+   (ghub--make-req
+    :url         (ghub--encode-url host resource query)
+    :forge       forge
+    :silent      silent
+    :method      (encode-coding-string method 'utf-8) ;#35
+    :headers     (ghub--headers headers host auth username forge)
+    :handler     #'ghub--handle-response
+    :unpaginate  unpaginate
+    :noerror     noerror
+    :reader      reader
+    :buffer      (current-buffer)
+    :synchronous (not (or callback errorback))
+    :callback    callback
+    :errorback   errorback
+    :value       value
+    :extra       extra)))
+
+(defun ghub-continue (req)
+  "If there is a next page, then retrieve that.
+
+This function is only intended to be called from callbacks.  If
+there is a next page, then retrieve that and return the buffer
+that the result will be loaded into, or t if the process has
+already completed.  If there is no next page, then return nil.
+
+Callbacks are called with four arguments (see `ghub-request').
+The forth argument is a `ghub--req' struct, intended to be passed
+to this function.  A callback may use the struct's `extra' slot
+to pass additional information to the callback that will be
+called after the next request has finished.  Use the function
+`ghub-req-extra' to get and set the value of this slot."
+  (and (assq 'next (ghub-response-link-relations req))
+       (or (ghub--retrieve nil req) t)))
+
+(cl-defun ghub-wait (resource
+                     &optional duration
+                     &key username auth host forge)
+  "Busy-wait up to DURATION seconds for RESOURCE to become available.
+
+DURATION specifies how many seconds to wait at most.  It defaults
+to 64 seconds.  The first attempt is made immediately, the second
+after two seconds, and each subsequent attempt is made after
+waiting as long again as we already waited between all preceding
+attempts combined.
+
+See `ghub-request' for information about the other arguments."
+  (unless duration
+    (setq duration 64))
+  (with-local-quit
+    (let ((total 0))
+      (while (not (ghub-request "GET" resource nil
+                                :noerror t
+                                :username username
+                                :auth auth
+                                :host host
+                                :forge forge))
+        (message "Waited (%3ss of %ss) for %s..." total duration resource)
+        (if (= total duration)
+            (error "%s is taking too long to create %s"
+                   (if forge (capitalize (symbol-name forge)) "Github")
+                   resource)
+          (if (> total 0)
+              (let ((wait (min total (- duration total))))
+                (sit-for wait)
+                (cl-incf total wait))
+            (sit-for (setq total 2))))))))
+
+(defun ghub-response-link-relations (req &optional headers payload)
+  "Return an alist of link relations in HEADERS.
+If optional HEADERS is nil, then return those that were
+previously stored in the variable `ghub-response-headers'.
+
+When accessing a Bitbucket instance then the link relations
+are in PAYLOAD instead of HEADERS, making their API merely
+RESTish and forcing this function to append those relations
+to the value of `ghub-response-headers', for later use when
+this function is called with nil for PAYLOAD."
+  (if (eq (ghub--req-forge req) 'bitbucket)
+      (if payload
+          (let* ((page (seq-keep (##assq % payload)
+                                 '(size page pagelen next previous)))
+                 (headers (cons (cons 'link-alist page) headers)))
+            (if (and req (or (ghub--req-callback req)
+                             (ghub--req-errorback req)))
+                (setq-local ghub-response-headers headers)
+              (setq-default ghub-response-headers headers))
+            page)
+        (cdr (assq 'link-alist ghub-response-headers)))
+    (and-let* ((headers (or headers ghub-response-headers))
+               (rels (cdr (or (assoc "Link" headers)
+                              (assoc "link" headers)))))
+      (mapcar (lambda (elt)
+                (pcase-let ((`(,url ,rel) (split-string elt "; ")))
+                  (cons (intern (substring rel 5 -1))
+                        (substring url 1 -1))))
+              (split-string rels ", ?")))))
+
+(cl-defun ghub-repository-id (owner name &key username auth host forge noerror)
+  "Return the id of the specified repository.
+Signal an error if the id cannot be determined."
+  (or (pcase forge
+        ((or 'nil 'github)
+         (let-alist (ghub-graphql
+                     '(query (repository [(owner $owner String!)
+                                          (name  $name  String!)]
+                                         id))
+                     `((owner . ,owner)
+                       (name  . ,name))
+                     :username username :auth auth :host host)
+           .data.repository.id))
+        ('gitlab
+         (number-to-string
+          (alist-get
+           'id (ghub-get (format "/projects/%s%%2F%s"
+                                 (string-replace "/" "%2F" owner)
+                                 name)
+                         nil :forge 'gitlab
+                         :username username :auth auth :host host))))
+        ((or 'forgejo 'gitea 'gogs)
+         (number-to-string
+          (alist-get
+           'id (ghub-get (format "/repos/%s/%s" owner name)
+                         nil :forge forge
+                         :username username :auth auth :host host))))
+        ('bitbucket
+         (substring
+          (alist-get 'uuid
+                     (ghub-get (format "/repositories/%s/%s" owner name)
+                               nil :forge 'bitbucket
+                               :username username :auth auth :host host))
+          1 -1))
+        (_ (error "ghub-repository-id: Forge type `%s' is unknown" forge)))
+      (and (not noerror)
+           (error "Repository %S does not exist on %S.\n%s%S?"
+                  (concat owner "/" name)
+                  (or host (ghub--host forge))
+                  "Maybe it was renamed and you have to update "
+                  "remote.<remote>.url"))))
+
+;;;; Internal
+
+(cl-defun ghub--retrieve (payload req)
+  (pcase-let*
+      (((cl-struct ghub--req headers method url handler silent synchronous) req)
+       (url-request-extra-headers
+        (if (functionp headers) (funcall headers) headers))
+       (url-request-method method)
+       (url-request-data payload)
+       (url-show-status nil))
+    (if synchronous
+        (if-let ((buf (url-retrieve-synchronously url silent)))
+            (with-current-buffer buf
+              (funcall handler (car url-callback-arguments) req))
+          (error "ghub--retrieve: No buffer returned"))
+      (url-retrieve url handler (list req) silent))))
+
+(defun ghub--handle-response (status req)
+  (let ((buf (current-buffer)))
+    (unwind-protect
+        (progn
+          (set-buffer-multibyte t)
+          (let* ((unpaginate (ghub--req-unpaginate req))
+                 (headers (ghub--handle-response-headers status req))
+                 (payload (ghub--handle-response-payload req))
+                 (payload (ghub--handle-response-error status payload req))
+                 (value   (ghub--handle-response-value payload req))
+                 (prev    (ghub--req-url req))
+                 (next    (cdr (assq 'next (ghub-response-link-relations
+                                            req headers payload)))))
+            (when (numberp unpaginate)
+              (cl-decf unpaginate))
+            (setf (ghub--req-url req)
+                  (url-generic-parse-url next))
+            (setf (ghub--req-unpaginate req) unpaginate)
+            (or (and next
+                     unpaginate
+                     (or (eq unpaginate t)
+                         (>  unpaginate 0))
+                     (ghub-continue req))
+                (let ((req-buf   (ghub--req-buffer req))
+                      (callback  (ghub--req-callback req))
+                      (errorback (ghub--req-errorback req))
+                      (err       (plist-get status :error)))
+                  (cond ((and err errorback)
+                         (setf (ghub--req-url req) prev)
+                         (funcall (if (eq errorback t)
+                                      'ghub--errorback
+                                    errorback)
+                                  err headers status req))
+                        (callback
+                         (save-current-buffer
+                           (when (buffer-live-p req-buf)
+                             (set-buffer req-buf))
+                           (funcall callback value headers status req)))
+                        (t value))))))
+      (when (and (buffer-live-p buf)
+                 (not (buffer-local-value 'ghub-debug buf)))
+        (kill-buffer buf)))))
+
+(defun ghub--handle-response-headers (_status req)
+  (let (headers)
+    (when (memq url-http-end-of-headers '(nil 0))
+      (unless url-debug (setq url-debug t))
+      (error "BUG: Missing headers in response buffer %s" (current-buffer)))
+    (goto-char (point-min))
+    (forward-line 1)
+    (while (re-search-forward "^\\([^:]*\\): \\(.+\\)"
+                              url-http-end-of-headers t)
+      (push (cons (match-string 1)
+                  (match-string 2))
+            headers))
+    (setq headers (nreverse headers))
+    (goto-char (1+ url-http-end-of-headers))
+    (if (and req (or (ghub--req-callback req)
+                     (ghub--req-errorback req)))
+        (setq-local ghub-response-headers headers)
+      (setq-default ghub-response-headers headers))
+    headers))
+
+(defun ghub--handle-response-error (status payload req)
+  (if-let ((err (plist-get status :error)))
+      (if-let ((noerror (ghub--req-noerror req)))
+          (if (eq noerror 'return)
+              payload
+            (setcdr (last err) (list payload))
+            nil)
+        (ghub--signal-error err payload req))
+    payload))
+
+(defun ghub--signal-error (err &optional payload req)
+  (pcase-let ((`(,symb . ,data) err))
+    (if (eq symb 'error)
+        (if (eq (car-safe data) 'http)
+            (signal 'ghub-http-error
+                    (let ((code (car (cdr-safe data))))
+                      (list code
+                            (nth 2 (assq code url-http-codes))
+                            (and req (url-recreate-url (ghub--req-url req)))
+                            payload)))
+          (signal 'ghub-error data))
+      (signal symb data))))
+
+(defun ghub--errorback (err _headers _status req)
+  (ghub--signal-error err (nth 3 err) req))
+
+(defun ghub--handle-response-value (payload req)
+  (setf (ghub--req-value req)
+        (nconc (ghub--req-value req)
+               (if-let ((nested (and (eq (ghub--req-forge req) 'bitbucket)
+                                     (assq 'values payload))))
+                   (cdr nested)
+                 payload))))
+
+(defun ghub--handle-response-payload (req)
+  (funcall (or (ghub--req-reader req)
+               'ghub--read-json-payload)
+           url-http-response-status))
+
+(defun ghub--read-json-payload (_status &optional json-type-args)
+  (and-let* ((payload (ghub--decode-payload)))
+    (progn
+      (ghub--assert-json-available)
+      (condition-case nil
+          (apply #'json-parse-string payload
+                 (or json-type-args
+                     '( :object-type alist
+                        :array-type list
+                        :null-object nil
+                        :false-object nil)))
+        (json-parse-error
+         (when ghub-debug
+           (pop-to-buffer (current-buffer)))
+         (setq-local ghub-debug t)
+         `((message . ,(if (looking-at "<!DOCTYPE html>")
+                           (if (re-search-forward
+                                "<p>\\(?:<strong>\\)?\\([^<]+\\)" nil t)
+                               (match-string 1)
+                             "error description missing")
+                         (string-trim (buffer-substring (point) (point-max)))))
+           (documentation_url
+            . "https://github.com/magit/ghub/wiki/Github-Errors")))))))
+
+(defun ghub--decode-payload (&optional _status)
+  (and (not (eobp))
+       (decode-coding-string
+        (buffer-substring-no-properties (point) (point-max))
+        'utf-8)))
+
+(defun ghub--encode-payload (payload)
+  (cl-typecase payload
+    (null nil)
+    (string (encode-coding-string payload 'utf-8))
+    (t (ghub--assert-json-available)
+       (encode-coding-string
+        (json-serialize payload
+                        :null-object :null
+                        :false-object nil)
+        'utf-8))))
+
+(defun ghub--encode-url (host resource &optional query)
+  (url-generic-parse-url
+   (concat (if (member host ghub-insecure-hosts) "http://" "https://")
+           ;; Needed for some Github Enterprise instances.
+           (cond
+            ((and (equal resource "/graphql")
+                  (string-suffix-p "/v3" host))
+             (substring host 0 -3))
+            ;; Needed for all Gitlab instances.
+            ((and (equal resource "/api/graphql")
+                  (string-suffix-p "/api/v4" host))
+             (substring host 0 -7))
+            (host))
+           resource
+           (and query (concat "?" (ghub--url-encode-params query))))))
+
+(defun ghub--url-encode-params (params)
+  (mapconcat (lambda (param)
+               (pcase-let ((`(,key . ,val) param))
+                 (concat (url-hexify-string (symbol-name key)) "="
+                         (cl-typecase val
+                           (integer (number-to-string val))
+                           (boolean (if val "true" "false"))
+                           (t (url-hexify-string val))))))
+             params "&"))
+
+(defun ghub--assert-json-available ()
+  (unless (and (fboundp 'json-available-p)
+               (json-available-p))
+    (error "Ghub requires Emacs 29 --with-json or Emacs >= 30")))
+
+;;; Authentication
+;;;; API
+
+;;;###autoload
+(defun ghub-clear-caches ()
+  "Clear all caches that might negatively affect Ghub.
+
+If a library that is used by Ghub caches incorrect information
+such as a mistyped password, then that can prevent Ghub from
+asking the user for the correct information again.
+
+Set `url-http-real-basic-auth-storage' to nil
+and call `auth-source-forget+'."
+  (interactive)
+  (setq url-http-real-basic-auth-storage nil)
+  (auth-source-forget+))
+
+;;;; Internal
+
+(defun ghub--headers (headers host auth username forge)
+  (push (cons "Content-Type" "application/json") headers)
+  (if (eq auth 'none)
+      headers
+    (unless (or username (stringp auth))
+      (setq username (ghub--username host forge)))
+    (lambda ()
+      (if (eq auth 'basic)
+          (cons (cons "Authorization" (ghub--basic-auth host username))
+                headers)
+        (cons (ghub--auth host auth username forge) headers)))))
+
+(cl-defgeneric ghub--auth (host auth &optional username forge)
+  (unless username
+    (setq username (ghub--username host forge)))
+  (if (eq auth 'basic)
+      (pcase-exhaustive forge
+        ((or 'nil 'forgejo 'gitea 'gogs 'bitbucket)
+         (cons "Authorization" (ghub--basic-auth host username)))
+        ((or 'github 'gitlab)
+         (error "%s does not support basic authentication"
+                (capitalize (symbol-name forge)))))
+    (cons (pcase-exhaustive forge
+            ((or 'nil 'forgejo 'github 'gitea 'gogs 'bitbucket) "Authorization")
+            ('gitlab "Private-Token"))
+          (if (eq forge 'bitbucket)
+              ;; For some undocumented reason Bitbucket supports
+              ;; values of the form "token <token>" only for GET
+              ;; requests.  For PUT requests we have to use basic
+              ;; authentication.  Note that the secret is a token
+              ;; (aka "app password"), not the actual password.
+              ;; The documentation fails to mention this little
+              ;; detail.  See #97.
+              (concat "Basic "
+                      (base64-encode-string
+                       (concat username ":"
+                               (ghub--token host username auth nil forge))
+                       t))
+            (concat
+             (and (not (eq forge 'gitlab)) "token ")
+             (encode-coding-string
+              (cl-typecase auth
+                (string auth)
+                (null   (ghub--token host username 'ghub nil forge))
+                (symbol (ghub--token host username auth  nil forge))
+                (t (signal 'wrong-type-argument
+                           `((or stringp symbolp) ,auth))))
+              'utf-8))))))
+
+(defun ghub--basic-auth (host username)
+  (let ((url (url-generic-parse-url
+              (if (member host ghub-insecure-hosts) "http://" "https://"))))
+    (setf (url-user url) username)
+    (url-basic-auth url t)))
+
+(defun ghub--token (host username package &optional nocreate forge)
+  (let* ((user (ghub--ident username package))
+         (token (or (ghub--auth-source-get :secret :host host :user user)
+                    (and (string-match "\\`\\([^/]+\\)" host)
+                         (ghub--auth-source-get :secret
+                           :host (match-string 1 host)
+                           :user user)))))
+    (unless (or token nocreate)
+      (error "\
+Required %s token (%S for %s%S) does not exist.
+See https://docs.magit.vc/ghub/Getting-Started.html
+or (info \"(ghub)Getting Started\") for instructions."
+             (capitalize (symbol-name (or forge 'github)))
+             user
+             (if (string-match "\\`\\([^/]+\\)" host)
+                 (format "either %S or " (match-string 1 host))
+               "")
+             host))
+    (if (functionp token) (funcall token) token)))
+
+(cl-defmethod ghub--host (&optional forge)
+  (let ((forge (or forge 'github)))
+    (or (ghub--git-get (format "%s.host" forge))
+        (alist-get forge ghub-default-host-alist))))
+
+(cl-defmethod ghub--username (host &optional forge)
+  (let* ((forge (or forge 'github))
+         (host (or host (ghub--host forge)))
+         (var (format "%s.%s.user" forge host))
+         (default-var (format "%s.user" forge)))
+    (cond ((ghub--git-get var))
+          ((not (equal host (alist-get forge ghub-default-host-alist)))
+           (user-error "Cannot determine username; `%s' is unset" var))
+          ((ghub--git-get default-var))
+          ((user-error "%s; `%s' and `%s' are both unset"
+                       "Cannot determine username" var default-var)))))
+
+(defun ghub--ident (username package)
+  (format "%s^%s" username package))
+
+(defun ghub--auth-source-get (keys &rest spec)
+  (declare (indent 1))
+  (if-let ((plist (car (apply #'auth-source-search spec))))
+      (if (keywordp keys)
+          (plist-get plist keys)
+        (mapcar (##plist-get plist %) keys))
+    ;; Auth-Source caches the information that there is no value, but in
+    ;; our case that is a situation that needs fixing, so we want to keep
+    ;; trying, by invalidating that information.
+    (auth-source-forget spec)
+    nil))
+
+(define-advice auth-source-netrc-parse (:around (fn &rest args) handle-symlink)
+  "Follow symlinks for FILE before comparing modification times."
+  (let ((file (plist-get args :file)))
+    (when (and (stringp file)
+               (file-exists-p file))
+      (setq args (plist-put args :file (file-chase-links file)))))
+  (apply fn args))
+
+(defun ghub--git-get (var)
+  (catch 'non-zero
+    (car (process-lines-handling-status
+          "git" (##unless (zerop %) (throw 'non-zero nil))
+          ;; Beginning with Git v2.46 we could use "get".
+          "config" "--get" var))))
+
+;;; _
+;; Local Variables:
+;; read-symbol-shorthands: (
+;;   ("and-let"   . "cond-let--and-let")
+;;   ("if-let"    . "cond-let--if-let")
+;;   ("when-let"  . "cond-let--when-let")
+;;   ("while-let" . "cond-let--while-let"))
+;; End:
+(provide 'ghub)
+(require 'ghub-graphql)
+(require 'ghub-legacy)
+;;; ghub.el ends here
diff --git a/elpa/ghub-20251130.1842/ghub.info b/elpa/ghub-20251130.1842/ghub.info
new file mode 100644 (file)
index 0000000..8cfce13
--- /dev/null
@@ -0,0 +1,987 @@
+This is ghub.info, produced by makeinfo version 6.8 from ghub.texi.
+
+     Copyright (C) 2017-2025 Jonas Bernoulli
+     <emacs.ghubNOSPAMjonas.bernoulli.dev>
+
+     You can redistribute this document and/or modify it under the terms
+     of the GNU General Public License as published by the Free Software
+     Foundation, either version 3 of the License, or (at your option)
+     any later version.
+
+     This document is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* Ghub: (ghub).         Client library for the Github API.
+END-INFO-DIR-ENTRY
+
+\1f
+File: ghub.info,  Node: Top,  Next: Introduction,  Up: (dir)
+
+Ghub User and Developer Manual
+******************************
+
+Ghub is an Emacs library that is used by various packages to access the
+APIs of various instances of various Git forge implementations.
+
+This manual is for Ghub version 5.0.2.
+
+     Copyright (C) 2017-2025 Jonas Bernoulli
+     <emacs.ghubNOSPAMjonas.bernoulli.dev>
+
+     You can redistribute this document and/or modify it under the terms
+     of the GNU General Public License as published by the Free Software
+     Foundation, either version 3 of the License, or (at your option)
+     any later version.
+
+     This document is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+* Menu:
+
+* Introduction::
+* Getting Started::
+* API::
+* Notes::
+* Function Index::
+* Variable Index::
+
+— The Detailed Node Listing —
+
+Getting Started
+
+* Basic Concepts, Arguments and Variables: Basic Concepts Arguments and Variables.
+* Setting the Username::
+* Creating and Storing a Token::
+* Github Configuration Variables::
+
+API
+
+* Their APIs::
+* Making REST Requests::
+* Making GraphQL Requests::
+* Github Convenience Wrappers::
+
+Notes
+
+* Using Ghub in Personal Scripts::
+* Using Ghub in Your Own Package::
+* Forge Limitations and Notes::
+
+
+\1f
+File: ghub.info,  Node: Introduction,  Next: Getting Started,  Prev: Top,  Up: Top
+
+1 Introduction
+**************
+
+Ghub is an Emacs library that is used by various packages to access the
+APIs of various instances of various Git forge implementations.
+
+   A forge is a web-based collaborative software platform for developing
+and distributing computer applications.  Examples include Github and
+Gitlab.
+
+\1f
+File: ghub.info,  Node: Getting Started,  Next: API,  Prev: Introduction,  Up: Top
+
+2 Getting Started
+*****************
+
+This manual guides you through the steps that are necessary to use the
+Forge package and/or to make a request using just Ghub itself, such as
+this:
+
+     (ghub-request "GET" "/user")
+
+   To be able to do that, Ghub needs to know who you want to talk to,
+who you are, and how you are going to prove the latter to the former.
+
+   Additionally Ghub wants to know on behalf of which Emacs package it
+is making a request.  So the question of "who is making the request" has
+to be rephrased as "which human (or bot) is using what (Emacs) package
+to make the request".  If, for example, the human known as "tarsius" is
+using the ‘forge’ package, then that is represented in some places using
+the string "tarsius^forge".
+
+* Menu:
+
+* Basic Concepts, Arguments and Variables: Basic Concepts Arguments and Variables.
+* Setting the Username::
+* Creating and Storing a Token::
+* Github Configuration Variables::
+
+\1f
+File: ghub.info,  Node: Basic Concepts Arguments and Variables,  Next: Setting the Username,  Up: Getting Started
+
+2.1 Basic Concepts, Arguments and Variables
+===========================================
+
+(If you are trying to configure Forge for <https://github.com> and/or
+<https://gitlab.com>, then you can skip this section.)
+
+   Originally Ghub supported only Github but now it also supports
+Gitlab, Gitea, Gogs and Bitbucket.  Because of that, the function
+‘ghub-request’ defaults to acting on a ‘github’ forge, but can be told
+to act on other forges using the FORGE argument.
+
+   The FORGE argument only specifies what kind of forge we are
+accessing, not which host specifically.  The HOST argument can be used
+to select the instance.  For some forges a default instance is defined:
+
+   • Forge ‘github’ defaults to host ‘api.github.com’.
+   • Forge ‘gitlab’ defaults to host ‘gitlab.com/api/v4’.
+   • Forge ‘bitbucket’ defaults to host ‘api.bitbucket.org/2.0’.
+   • No canonical host exists for the ‘gitea’ and ‘gogs’ forges and
+     ‘localhost:3000/api/v1’ is used as the default host in both cases.
+
+   Together the FORGE and HOST arguments specify the forge type and
+instance.  In addition to that, it is also necessary to specify on whose
+behalf the request is being made, which can be done using the USERNAME
+and AUTH arguments.  For example:
+
+     (ghub-request "GET" "/user" nil
+                   :forge 'github
+                   :host "api.github.com"
+                   :username "tarsius"
+                   :auth 'forge)
+
+   Having to specify these arguments for every request is inconvenient.
+Additional variables and convenience functions can be used to make that
+unnecessary in most cases.
+
+   (But for debugging purposes the above explicit form is very useful.
+You will obviously have to change the value of USERNAME and you should
+use ‘ghub’ as AUTH when first trying this at home.)
+
+   These variables can be set globally and/or for a specific repository.
+
+   • For "api.github.com" (aka the API of <https://github.com>) the Git
+     variable ‘github.user’ specifies the user.
+   • For another ‘github’ instance the Git variable ‘github.HOST.user’
+     specifies the user.  The HOST in that variable name is the same as
+     the value of the HOST argument of the called function.
+   • Instead of specifying the HOST in every function call, the Git
+     variable ‘github.host’ can be used.  This should only be set
+     locally.
+
+   These ‘github’ specific variables are discussed in more detail in
+*note Github Configuration Variables::.
+
+For ‘gitlab’ and ‘bitbucket’ forges similar variables are available:
+
+   • ‘gitlab.user’ specifies the <https://gitlab.com> user.
+   • ‘gitlab.HOST.user’ specifies the user for the HOST ‘gitlab’
+     instance.
+   • ‘gitlab.host’ specifies the ‘gitlab’ host, unless the HOST argument
+     is non-‘nil’
+   • ‘bitbucket.user’ specifies the <https://bitbucket.org> user.
+   • ‘bitbucket.HOST.user’ specifies the user for the HOST ‘bitbucket’
+     instance.
+   • ‘bitbucket.host’ specifies the ‘bitbucket’ host, unless the HOST
+     argument is non-‘nil’.
+
+   For the ‘gitea’ and ‘gogs’ forges some similar variables are
+available, however for some of the ‘ghub.*’ variables no equivalent
+variable exist for these two forges:
+
+   • ‘gitea.user’ is *not* used because no canonical ‘gitea’ instance
+     exists.
+   • ‘gitea.HOST.user’ specifies the user for the HOST ‘gitea’ instance.
+   • ‘gitea.host’ specifies the ‘gitea’ host, unless the HOST argument
+     is non-‘nil’
+   • ‘gogs.user’ is *not* used because no canonical ‘gogs’ instance
+     exists.
+   • ‘gogs.HOST.user’ specifies the user for the HOST ‘gogs’ instance.
+   • ‘gogs.host’ specifies the ‘gogs’ host, unless the HOST argument is
+     non-‘nil’
+
+\1f
+File: ghub.info,  Node: Setting the Username,  Next: Creating and Storing a Token,  Prev: Basic Concepts Arguments and Variables,  Up: Getting Started
+
+2.2 Setting the Username
+========================
+
+Ghub needs to know your username, which you use on the host that you
+want it to connect to.  For each host a different Git variable has to be
+set, to specify the username on that host.  More than one variable is
+needed, because you might use different usernames on different hosts.
+
+Setting your Github.com Username
+--------------------------------
+
+To inform Ghub about your "github.com" username do this:
+
+     git config --global github.user USERNAME
+
+   If you need to identify as another user in a particular repository,
+then you have to set that variable locally:
+
+     cd /path/to/repo
+     git config --local github.user USERNAME
+
+Setting your Gitlab.com Username
+--------------------------------
+
+To inform Ghub about your "gitlab.com" username do this:
+
+     git config --global gitlab.user USERNAME
+
+   If you need to identify as another user in a particular repository,
+then you have to set that variable locally:
+
+     cd /path/to/repo
+     git config --local gitlab.user USERNAME
+
+   Make sure you use the correct USERNAME for this forge/host.  It might
+not be the same as on "github.com"!
+
+Setting your Github Enterprise Username
+---------------------------------------
+
+For Github Enterprise instances you have to specify where the API can be
+accessed and a different variable has to be used to set the username.
+
+   For example if the API is available at ‘https://example.com/api/v3’,
+then you should do this:
+
+     git config --global github.example.com/api/v3.user USERNAME
+
+   Make sure you use the correct USERNAME for this instance.  It might
+not be the same as on "github.com"!
+
+   Doing this only tells Ghub who you are on this host, additionally you
+have to tell Ghub which repositories are connected to that forge/host,
+like so:
+
+     cd /path/to/repo
+     git config --local github.host example.com/api/v3
+
+Setting your Username for Other Hosts and/or Forges
+---------------------------------------------------
+
+To inform Ghub about your username on HOST (a FORGE instance) do this:
+
+     git config --global FORGE.HOST.user USERNAME
+
+   FORGE can be one of ‘bitbucket’, ‘gitea’ or ‘gogs’.  It can also be
+‘github’ or ‘gitlab’; but if that is the case, then you should look at
+the preceding sections instead, which discuss these cases specifically.
+
+   HOST identifies the instance.  This actually points at the top-level
+endpoint of the API and may contain path components, e.g.:
+‘example.com/api’.
+
+   If you need to identify as another user in a particular repository,
+then you have to set that variable locally:
+
+     cd /path/to/repo
+     git config --local FORGE.HOST.user USERNAME
+
+\1f
+File: ghub.info,  Node: Creating and Storing a Token,  Next: Github Configuration Variables,  Prev: Setting the Username,  Up: Getting Started
+
+2.3 Creating and Storing a Token
+================================
+
+2.3.1 Creating a Token
+----------------------
+
+To create a token, use the web interface of the host you want to connect
+to.  Here is a list of pages to do this for certain popular hosts:
+
+   • <https://github.com/settings/tokens>
+   • <https://gitlab.com/-/user_settings/personal_access_tokens>
+
+   For other forges we cannot provide a functioning URL because they
+contain unknown values such as your name.  Just go to the general
+settings page of the respective host and then go from there.
+
+   Except on ‘gitea’ and ‘gogs’ each token can be limited to certain
+"scopes", i.e., it is possible to limit for which purposes any given
+token can be used.
+
+   Before you create a token to be used for a certain package, you
+should consult the documentation of that package, which in turn should
+tell you which scopes are needed and why.  The Forge package for example
+does so in *note (forge)Token Creation::.
+
+2.3.2 Storing a Token
+---------------------
+
+Please also see *note (auth)Top:: for all the gory details about
+Auth-Source.
+
+   The variable ‘auth-sources’ controls how and where Auth-Source keeps
+its secrets.  The default value is a list of three files:
+‘("~/.authinfo" "~/.authinfo.gpg" "~/.netrc")’, but to avoid confusion
+you should make sure that only one of these files exists, and then you
+should also adjust the value of the variable to only ever use that file,
+for example:
+
+     (setq auth-sources '("~/.authinfo"))
+
+   In ‘~/.authinfo’ secrets are stored in plain text.  If you don’t want
+that, then you should use the encrypted ‘~/.authinfo.gpg’ instead:
+
+     (setq auth-sources '("~/.authinfo.gpg"))
+
+   Auth-Source also supports storing secrets in various external
+key-chains.  See *note (auth)Top:: for more information.
+
+   The default Auth-Source backends only support storing three values
+per entry; the "machine", the "login" and the "password".  Because Ghub
+uses separate tokens for each package, it has to squeeze four values
+into those three slots, and it does that by using "USERNAME^PACKAGE" as
+the "login".
+
+   Assuming your *Github* username is "ziggy", the package is named
+"forge", and you want to access *Github.com* with the *token*
+"012345abcdef...", an entry in one of the three mentioned files would
+then look like this:
+
+     machine api.github.com login ziggy^forge password 012345abcdef...
+
+   Assuming your *Gitlab* username is "ziggy", the package is named
+"forge", and you want to access *Gitlab.com* with the *token*
+"012345abcdef...", an entry in one of the three mentioned files would
+then look like this:
+
+     machine gitlab.com/api/v4 login ziggy^forge password 012345abcdef...
+
+\1f
+File: ghub.info,  Node: Github Configuration Variables,  Prev: Creating and Storing a Token,  Up: Getting Started
+
+2.4 Github Configuration Variables
+==================================
+
+The username and, unless you only use Github.com itself, the Github
+Enterprise instance have to be configured using Git variables.  In rare
+cases it might also be necessary to specify the identity of the local
+machine, which is done using a lisp variable.
+
+ -- Variable: github.user
+     The Github.com username.  This should be set globally and if you
+     have multiple Github.com user accounts, then you should set this
+     locally only for those repositories that you want to access using
+     the secondary identity.
+
+ -- Variable: github.HOST.user
+     This variable serves the same purpose as ‘github.user’ but for the
+     Github Enterprise instance identified by ‘HOST’.
+
+     The reason why separate variables are used is that this makes it
+     possible to set both values globally instead of having to set one
+     of the values locally in each and every repository that is
+     connected to the Github Enterprise instance, not Github.com.
+
+ -- Variable: github.host
+     This variable should only be set locally for a repository and
+     specifies the Github Enterprise edition that that repository is
+     connected to.  You should not set this globally because then each
+     and every repository becomes connected to the specified Github
+     Enterprise instance, including those that should actually be
+     connected to Github.com.
+
+     When this is undefined, then "api.github.com" is used (defined in
+     the constant ‘ghub-default-host’, which you should never attempt to
+     change.)
+
+\1f
+File: ghub.info,  Node: API,  Next: Notes,  Prev: Getting Started,  Up: Top
+
+3 API
+*****
+
+* Menu:
+
+* Their APIs::
+* Making REST Requests::
+* Making GraphQL Requests::
+* Github Convenience Wrappers::
+
+\1f
+File: ghub.info,  Node: Their APIs,  Next: Making REST Requests,  Up: API
+
+3.1 Their APIs
+==============
+
+Of course this manual does not cover the APIs of all forges that it
+supports, but for your convenience, here are the links to their API
+manuals:
+
+   • Github:
+        • <https://docs.github.com/en/graphql> (GraphQl)
+        • <https://docs.github.com/en/rest> (REST)
+   • Gitlab:
+        • <https://docs.gitlab.com/api>
+   • Gitea:
+        • <https://docs.gitea.com/next/development/api-usage>
+        • <https://demo.gitea.com>
+   • Gogs:
+        • <https://gogs.io/docs>
+   • Bitbucket:
+        • <https://developer.atlassian.com/cloud/bitbucket>
+
+\1f
+File: ghub.info,  Node: Making REST Requests,  Next: Making GraphQL Requests,  Prev: Their APIs,  Up: API
+
+3.2 Making REST Requests
+========================
+
+ -- Function: ghub-request method resource &optional params &key query
+          payload headers unpaginate noerror reader username auth host
+          callback errorback url value error extra method*
+     This function makes a request for ‘RESOURCE’ using ‘METHOD’.
+     ‘PARAMS’, ‘QUERY’, ‘PAYLOAD’ and/or ‘HEADERS’ are alists holding
+     additional request data.  The response body is returned and the
+     response headers are stored in the variable
+     ‘ghub-response-headers’.
+
+        • ‘METHOD’ is the HTTP method, given as a string.
+        • ‘RESOURCE’ is the resource to access, given as a string
+          beginning with a slash.
+
+        • ‘PARAMS’, ‘QUERY’, ‘PAYLOAD’ and ‘HEADERS’ are alists and are
+          used to specify request data.  All these arguments are alists
+          that resemble the JSON expected and returned by the Github
+          API.  The keys are symbols and the values stored in the ‘cdr’
+          (not the ‘cadr’) can be strings, integers, or lists of strings
+          and integers.
+
+          The Github API documentation is vague on how data has to be
+          transmitted and for a particular resource usually just talks
+          about "parameters".  Generally speaking when the ‘METHOD’ is
+          "HEAD" or "GET", then they have to be transmitted as a query,
+          otherwise as a payload.
+
+             • Use ‘PARAMS’ to automatically transmit like ‘QUERY’ or
+               ‘PAYLOAD’ would depending on ‘METHOD’.
+             • Use ‘QUERY’ to explicitly transmit data as a query.
+             • Use ‘PAYLOAD’ to explicitly transmit data as a payload.
+               Instead of an alist, ‘PAYLOAD’ may also be a string, in
+               which case it gets encoded as UTF-8 but is otherwise
+               transmitted as-is.
+             • Use ‘HEADERS’ for those rare resources that require that
+               the data is transmitted as headers instead of as a query
+               or payload.  When that is the case, then the Github API
+               documentation usually mentions it explicitly.
+
+        • If ‘SILENT’ is non-‘nil’, then progress reports and the like
+          are not messaged.
+
+        • If ‘UNPAGINATE’ is ‘t’, then this function makes as many
+          requests as necessary to get all values.  If ‘UNPAGINATE’ is a
+          natural number, then it gets at most that many pages.  For any
+          other non-‘nil’ value it raises an error.
+
+        • If ‘NOERROR’ is non-‘nil’, then no error is raised if the
+          request fails and ‘nil’ is returned instead.  If ‘NOERROR’ is
+          ‘return’, then the error payload is returned instead of ‘nil’.
+
+        • If ‘READER’ is non-‘nil’, then it is used to read and return
+          from the response buffer.  The default is
+          ‘ghub--read-json-payload’.  For the very few resources that do
+          not return JSON, you might want to use ‘ghub--decode-payload’.
+
+        • If ‘USERNAME’ is non-‘nil’, then the request is made on behalf
+          of that user.  It is better to specify the user using the Git
+          variable ‘github.user’ for "api.github.com", or
+          ‘github.HOST.user’ if connecting to a Github Enterprise
+          instance.
+
+        • Each package that uses Ghub should use its own token.  If
+          ‘AUTH’ is ‘nil’ or unspecified, then the generic ‘ghub’ token
+          is used instead.  This is only acceptable for personal
+          utilities.  A package that is distributed to other users
+          should always use this argument to identify itself, using a
+          symbol matching its name.
+
+          Package authors who find this inconvenient should write a
+          wrapper around this function and possibly for the
+          method-specific functions as well.
+
+          Beside ‘nil’, some other symbols have a special meaning too.
+          ‘none’ means to make an unauthorized request.  ‘basic’ means
+          to make a password based request.  If the value is a string,
+          then it is assumed to be a valid token.  ‘basic’ and an
+          explicit token string are only intended for internal and
+          debugging uses.
+
+          If ‘AUTH’ is a package symbol, then the scopes are specified
+          using the variable ‘AUTH-github-token-scopes’.  It is an error
+          if that is not specified.  See ‘ghub-github-token-scopes’ for
+          an example.
+
+        • If ‘HOST’ is non-‘nil’, then connect to that Github instance.
+          This defaults to "api.github.com".  When a repository is
+          connected to a Github Enterprise instance, then it is better
+          to specify that using the Git variable ‘github.host’ instead
+          of using this argument.
+
+        • If ‘FORGE’ is ‘gitlab’, then connect to Gitlab.com or,
+          depending on ‘HOST’, to another Gitlab instance.
+
+        • If ‘CALLBACK’ and/or ‘ERRORBACK’ is non-‘nil’, then this
+          function makes one or more asynchronous requests and calls
+          ‘CALLBACK’ or ‘ERRORBACK’ when finished.  If no error
+          occurred, then it calls ‘CALLBACK’, unless that is ‘nil’.
+
+          If an error occurred, then it calls ‘ERRORBACK’, or if that is
+          ‘nil’, then ‘CALLBACK’.  ‘ERRORBACK’ can also be ‘t’, in which
+          case it signals instead.  ‘NOERROR’ is ignored for all
+          asynchronous requests.
+
+          Both callbacks are called with four arguments.
+
+            1. For ‘CALLBACK’, the combined value of the retrieved
+               pages.  For ‘ERRORBACK’, the error that occurred when
+               retrieving the last page.
+            2. The headers of the last page as an alist.
+            3. Status information provided by ‘url-retrieve’.  Its
+               ‘:error’ property holds the same information as the first
+               argument to ‘ERRORBACK’.
+            4. A ‘ghub--req’ struct, which can be passed to
+               ‘ghub-continue’ (which see) to retrieve the next page, if
+               any.
+
+ -- Function: ghub-continue args
+     If there is a next page, then this function retrieves that.
+
+     This function is only intended to be called from callbacks.  If
+     there is a next page, then that is retrieved and the buffer that
+     the result will be loaded into is returned, or ‘t’ if the process
+     has already completed.  If there is no next page, then return
+     ‘nil’.
+
+     Callbacks are called with four arguments (see ‘ghub-request’).  The
+     forth argument is a ‘ghub--req’ struct, intended to be passed to
+     this function.  A callback may use the struct’s ‘extra’ slot to
+     pass additional information to the callback that will be called
+     after the next request.  Use the function ‘ghub-req-extra’ to get
+     and set the value of that slot.
+
+     As an example, using ‘ghub-continue’ in a callback like so:
+
+          (ghub-get "/users/tarsius/repos" nil
+                    :callback (lambda (value _headers _status req)
+                                (unless (ghub-continue req)
+                                  (setq my-value value))))
+
+     is equivalent to:
+
+          (ghub-get "/users/tarsius/repos" nil
+                    :unpaginate t
+                    :callback (lambda (value _headers _status _req)
+                                (setq my-value value)))
+
+     To demonstrate how to pass information from one callback to the
+     next, here we record when we start fetching each page:
+
+          (ghub-get "/users/tarsius/repos" nil
+                    :extra (list (current-time))
+                    :callback (lambda (value _headers _status req)
+                                (push (current-time) (ghub-req-extra req))
+                                (unless (ghub-continue req)
+                                  (setq my-times (ghub-req-extra req))
+                                  (setq my-value value))))
+
+ -- Variable: ghub-response-headers
+     A select few Github API resources respond by transmitting data in
+     the response header instead of in the response body.  Because there
+     are so few of these inconsistencies, ‘ghub-request’ always returns
+     the response body.
+
+     To access the response headers use this variable after
+     ‘ghub-request’ has returned.
+
+ -- Function: ghub-response-link-relations req headers payload
+     This function returns an alist of the link relations in ‘HEADERS’,
+     or if optional ‘HEADERS’ is ‘nil’, then those in
+     ‘ghub-response-headers’.
+
+     When accessing a Bitbucket instance then the link relations are in
+     ‘PAYLOAD’ instead of ‘HEADERS’, making their API merely RESTish and
+     forcing this function to append those relations to the value of
+     ‘ghub-response-headers’, for later use when this function is called
+     with ‘nil’ for ‘PAYLOAD’.
+
+\1f
+File: ghub.info,  Node: Making GraphQL Requests,  Next: Github Convenience Wrappers,  Prev: Making REST Requests,  Up: API
+
+3.3 Making GraphQL Requests
+===========================
+
+ -- Function: ghub-graphql graphql &optional variables &key username
+          auth host callback silent callback errorback value extra
+     This function makes a GraphQL request using ‘GRAPHQL’ and
+     ‘VARIABLES’ as inputs.  ‘GRAPHQL’ is a GraphQL string.  ‘VARIABLES’
+     is a JSON-like alist.  The other arguments behave as for
+     ‘ghub-request’ (which see).
+
+     The response is returned as a JSON-like alist.  Even if the
+     response contains ‘errors’, this function does not raise an error.
+     Cursor-handling is likewise left to the caller.
+
+   ‘ghub-graphql’ is a thin convenience wrapper around ‘ghub-request’,
+similar to ‘ghub-post’ and friends.  While the latter only hard-code the
+value of the ‘METHOD’ argument, the former also hard-codes ‘RESOURCE’
+and constructs ‘PAYLOAD’ from ‘GRAPHQL’ and ‘VARIABLES’.  It also drops
+‘UNPAGINATE’, ‘NOERROR’, ‘READER’ (internal functions expect alist-ified
+JSON) and ‘FORGE’ (only Github currently supports GraphQL).
+
+   ‘ghub-graphql’ does not account for the fact that pagination works
+differently in GraphQL than it does in REST, so users of this function
+have to deal with that themselves.  Likewise error handling works
+differently and has to be done by the caller too.
+
+   An early attempt at implementing automatic unpaginating for GraphQL
+can be found in the ‘faithful-graphql’ branch, provided I haven’t
+deleted that by now.  On that branch I try to do things as intended by
+the designers of GraphQL, using variables and fragments, and drowning in
+a sea of boilerplate.
+
+   The problem with that approach is that it only works for applications
+that fetch specific information on demand and actually want things to be
+paginated.  I am convinced that GraphQL is very nice for web apps.
+
+   However the Forge package for which I have implemented all of this
+has very different needs.  It wants to fetch "all the data" and "cache"
+it locally, so that it is available even when there is no internet
+connection.  GraphQL was designed around the idea that you should be
+able to "ask for what you need and get exactly that".  But when that
+boils down to "look, if I persist, then you are going to hand me over
+all the data anyway, so just caught it up already", then things start to
+fall apart.  If Github’s GraphQL allowed pagination to be turned off
+completely, then teaching ‘ghub-graphql’ about error handling would be
+enough.
+
+   But it doesn’t and when doing things as intended, then that leads to
+huge amounts of repetitive boilerplate, which is so boring to write that
+doing it without introducing bugs left and right is near impossible; so
+I decided to give up on GraphQL variables, fragments and conditions, and
+instead implement something more powerful, though also more opinionated.
+
+ -- Function: ghub--graphql-vacuum query variables callback &optional
+          until &key narrow username auth host forge
+     This function is an opinionated alternative to ‘ghub-graphql’.  It
+     relies on dark magic to get the job done.
+
+     It makes an initial request using ‘QUERY’.  It then looks for
+     paginated edges in the returned data and makes more requests to
+     resolve them.  In order to do so it automatically transforms the
+     initial ‘QUERY’ into another query suitable for that particular
+     edge.  The data retrieved by subsequent requests is then injected
+     into the data of the original request before that is returned or
+     passed to the callback.  If subsequently retrieved data features
+     new paginated edges, then those are followed recursively.
+
+     The end result is essentially the same as using ‘ghub-graphql’, if
+     only it were possible to say "do not paginate anything".  The
+     implementation is much more complicated because it is not possible
+     to do that.
+
+     ‘QUERY’ is a GraphQL query expressed as an s-expression.  The
+     bundled ‘gsexp’ library is used to turn that into a GraphQL query
+     string.  Only a subset of the GraphQL features are supported;
+     fragments for example are not, and magical stuff happens to
+     variables.  This is not documented yet, I am afraid.  Look at
+     existing callers.
+
+     ‘VARIABLES’ is a JSON-like alist as for ‘ghub-graphql’.
+
+     ‘UNTIL’ is an alist ‘((EDGE-until . VALUE)...)’.  When unpaginating
+     ‘EDGE’ try not to fetch beyond the element whose first field has
+     the value ‘VALUE’ and remove that element as well as all "lesser"
+     elements from the retrieved data if necessary.  Look at
+     ‘forge--pull-repository’ for an example.  This is only useful if
+     you "cache" the response locally and want to avoid fetching data
+     again that you already have.
+
+     Other arguments behave as for ‘ghub-graphql’ and ‘ghub-request’,
+     more or less.  If ‘CALLBACK’ is ‘nil’, pretty-print the response.
+
+   Using ‘ghub--graphql-vacuum’, the following resource specific
+functions are implemented.  These functions are not part of the public
+API yet and are very much subject to change.
+
+ -- Function: ghub-fetch-repository owner name callback &optional until
+          &key username auth host forge
+     This function asynchronously fetches forge data about the specified
+     repository.  Once all data has been collected, ‘CALLBACK’ is called
+     with the data as the only argument.
+
+ -- Function: ghub-fetch-issue owner name callback &optional until &key
+          username auth host forge
+     This function asynchronously fetches forge data about the specified
+     issue.  Once all data has been collected, ‘CALLBACK’ is called with
+     the data as the only argument.
+
+ -- Function: ghub-fetch-pullreq owner name callback &optional until
+          &key username auth host forge
+     This function asynchronously fetches forge data about the specified
+     pull-request.  Once all data has been collected, ‘CALLBACK’ is
+     called with the data as the only argument.
+
+   Note that in order to avoid duplication all of these functions base
+their initial query on the query stored in ‘ghub-fetch-repository’.  The
+latter two pass that query through ‘ghub--graphql-prepare-query’, which
+then uses ‘ghub--graphql-narrow-query’ to remove parts the caller is not
+interested in.  These two functions are also used internally, when
+unpaginating, but as demonstrated here they can be useful even before
+making an initial request.
+
+\1f
+File: ghub.info,  Node: Github Convenience Wrappers,  Prev: Making GraphQL Requests,  Up: API
+
+3.4 Github Convenience Wrappers
+===============================
+
+ -- Function: ghub-head resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+ -- Function: ghub-get resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+     These functions are simple wrappers around ‘ghub-request’.  Their
+     signature is identical to that of the latter, except that they do
+     not have an argument named ‘METHOD’.  The HTTP method is instead
+     given by the second word in the function name.
+
+     As described in the documentation for ‘ghub-request’, it depends on
+     the used method whether the value of the ‘PARAMS’ argument is used
+     as the query or the payload.  For the "HEAD" and "GET" methods it
+     is used as the query.
+
+ -- Function: ghub-put resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+ -- Function: ghub-post resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+ -- Function: ghub-patch resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+ -- Function: ghub-delete resource &optional params &key query payload
+          headers unpaginate noerror reader username auth host callback
+          errorback
+     These functions are simple wrappers around ‘ghub-request’.  Their
+     signature is identical to that of the latter, except that they do
+     not have an argument named ‘METHOD’.  The HTTP method is instead
+     given by the second word in the function name.
+
+     As described in the documentation for ‘ghub-request’, it depends on
+     the used method whether the value of the ‘PARAMS’ argument is used
+     as the query or the payload.  For the "PUT", "POST", "PATCH" and
+     "DELETE" methods it is used as the payload.
+
+ -- Function: ghub-wait resource &optional duration &key username auth
+          host
+     Some API requests result in an immediate successful response even
+     when the requested action has not actually been carried out yet.
+     An example is the request for the creation of a new repository,
+     which doesn’t cause the repository to immediately become available.
+     The Github API documentation usually mentions this when describing
+     an affected resource.
+
+     If you want to do something with some resource right after making a
+     request for its creation, then you might have to wait for it to
+     actually be created.  This function can be used to do so.  It
+     repeatedly tries to access the resource until it becomes available
+     or until a timeout is reached.  In the latter case it signals
+     ‘ghub-error’.
+
+     ‘RESOURCE’ specifies the resource that this function waits for.
+
+     ‘DURATION’ specifies the maximum number of seconds to wait for,
+     defaulting to 64 seconds.  Emacs will block during that time, but
+     the user can abort using ‘C-g’.
+
+     The first attempt is made immediately and will often succeed.  If
+     not, then another attempt is made after two seconds, and each
+     subsequent attempt is made after waiting as long as we already
+     waited between all preceding attempts combined.
+
+     See ‘ghub-request’’s documentation above for information about the
+     other arguments.
+
+\1f
+File: ghub.info,  Node: Notes,  Next: Function Index,  Prev: API,  Up: Top
+
+4 Notes
+*******
+
+* Menu:
+
+* Using Ghub in Personal Scripts::
+* Using Ghub in Your Own Package::
+* Forge Limitations and Notes::
+
+\1f
+File: ghub.info,  Node: Using Ghub in Personal Scripts,  Next: Using Ghub in Your Own Package,  Up: Notes
+
+4.1 Using Ghub in Personal Scripts
+==================================
+
+You can of course use ‘ghub-request’ and its wrapper functions in your
+personal scripts.  Unlike when you use Ghub in a package that you
+distribute for others to use, you don’t have to explicitly specify a
+package in personal scripts.
+
+     ;; This is perfectly acceptable in personal scripts ...
+     (ghub-get "/user")
+
+     ;; ... and actually equals to
+     (ghub-get "/user" nil :auth 'ghub)
+
+     ;; In packages you have to specify the package using AUTH.
+     (ghub-get "/user" nil :auth 'some-package)
+
+   When the ‘AUTH’ argument is not specified, then a request is made on
+behalf of the ‘ghub’ package itself.  Like for any other package you
+have to create a dedicated token of course.
+
+\1f
+File: ghub.info,  Node: Using Ghub in Your Own Package,  Next: Forge Limitations and Notes,  Prev: Using Ghub in Personal Scripts,  Up: Notes
+
+4.2 Using Ghub in Your Own Package
+==================================
+
+Every package should use its own token.  This allows you as the author
+of some package to only request access to API scopes that are actually
+needed, which in turn might make it easier for users to trust your
+package not to do unwanted things.
+
+   You have to tell ‘ghub-request’ on behalf of which package a request
+is being made by passing the symbol ‘PACKAGE’ as the value of its ‘AUTH’
+argument.
+
+     (ghub-request "GET" "/user" nil :auth 'PACKAGE)
+
+   Keep in mind that the users of your package will have to manually
+create a suitable token.  To make that easier, you should not only link
+to this manual but also prominently mention the scopes the token needs;
+and explain what they are needed for.
+
+\1f
+File: ghub.info,  Node: Forge Limitations and Notes,  Prev: Using Ghub in Your Own Package,  Up: Notes
+
+4.3 Forge Limitations and Notes
+===============================
+
+   • There are no default Gitea and Gogs instances so the variables
+     ‘gitea.host’ and ‘gogs.host’ are not taken into account.
+
+   • Gitea and Gogs do not support limiting a token to certain scopes.
+
+   • The Bitbucket API is fairly broken and my willingness to deal with
+     that is extremely limited unless someone pays me vast amounts of
+     money.
+
+   • The Gitlab API documentation is not always accurate, though I don’t
+     have an example at hand.  It also isn’t structured well, making it
+     occasionally difficult to find the information one is looking for.
+
+   • Where one would use ‘user/repo’ when accessing another forge, one
+     has to use ‘user%2Frepo’ when accessing Gitlab, e.g.:
+
+          (ghub-get "/projects/python-mode-devs%2Fpython-mode"
+                    nil :forge 'gitlab)
+
+\1f
+File: ghub.info,  Node: Function Index,  Next: Variable Index,  Prev: Notes,  Up: Top
+
+Appendix A Function Index
+*************************
+
+\0\b[index\0\b]
+* Menu:
+
+* ghub--graphql-vacuum:                  Making GraphQL Requests.
+                                                              (line  56)
+* ghub-continue:                         Making REST Requests.
+                                                              (line 122)
+* ghub-delete:                           Github Convenience Wrappers.
+                                                              (line  31)
+* ghub-fetch-issue:                      Making GraphQL Requests.
+                                                              (line 105)
+* ghub-fetch-pullreq:                    Making GraphQL Requests.
+                                                              (line 111)
+* ghub-fetch-repository:                 Making GraphQL Requests.
+                                                              (line  99)
+* ghub-get:                              Github Convenience Wrappers.
+                                                              (line   9)
+* ghub-graphql:                          Making GraphQL Requests.
+                                                              (line   6)
+* ghub-head:                             Github Convenience Wrappers.
+                                                              (line   6)
+* ghub-patch:                            Github Convenience Wrappers.
+                                                              (line  28)
+* ghub-post:                             Github Convenience Wrappers.
+                                                              (line  25)
+* ghub-put:                              Github Convenience Wrappers.
+                                                              (line  22)
+* ghub-request:                          Making REST Requests.
+                                                              (line   6)
+* ghub-response-link-relations:          Making REST Requests.
+                                                              (line 172)
+* ghub-wait:                             Github Convenience Wrappers.
+                                                              (line  44)
+
+\1f
+File: ghub.info,  Node: Variable Index,  Prev: Function Index,  Up: Top
+
+Appendix B Variable Index
+*************************
+
+\0\b[index\0\b]
+* Menu:
+
+* ghub-response-headers:                 Making REST Requests.
+                                                              (line 163)
+* github.host:                           Github Configuration Variables.
+                                                              (line  26)
+* github.HOST.user:                      Github Configuration Variables.
+                                                              (line  17)
+* github.user:                           Github Configuration Variables.
+                                                              (line  11)
+
+
+\1f
+Tag Table:
+Node: Top\7f773
+Node: Introduction\7f2207
+Node: Getting Started\7f2612
+Node: Basic Concepts Arguments and Variables\7f3639
+Node: Setting the Username\7f7643
+Ref: Setting your Githubcom Username\7f8131
+Ref: Setting your Gitlabcom Username\7f8487
+Ref: Setting your Github Enterprise Username\7f8953
+Ref: Setting your Username for Other Hosts and/or Forges\7f9686
+Node: Creating and Storing a Token\7f10492
+Ref: Creating a Token\7f10705
+Ref: Storing a Token\7f11622
+Node: Github Configuration Variables\7f13365
+Node: API\7f15076
+Node: Their APIs\7f15278
+Node: Making REST Requests\7f15960
+Node: Making GraphQL Requests\7f25270
+Node: Github Convenience Wrappers\7f31959
+Node: Notes\7f35623
+Node: Using Ghub in Personal Scripts\7f35830
+Node: Using Ghub in Your Own Package\7f36721
+Node: Forge Limitations and Notes\7f37656
+Node: Function Index\7f38668
+Node: Variable Index\7f40936
+\1f
+End Tag Table
+
+\1f
+Local Variables:
+coding: utf-8
+End:
diff --git a/elpa/ghub-20251130.1842/gsexp.el b/elpa/ghub-20251130.1842/gsexp.el
new file mode 100644 (file)
index 0000000..a1fac79
--- /dev/null
@@ -0,0 +1,102 @@
+;;; gsexp.el --- GraphQl as S-expressions  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2016-2025 Jonas Bernoulli
+
+;; Author: Jonas Bernoulli <emacs.ghubNOSPAMjonas.bernoulli.dev>
+;; Homepage: https://github.com/magit/ghub
+;; Keywords: tools
+
+;; SPDX-License-Identifier: GPL-3.0-or-later
+
+;; This file is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation, either version 3 of the License,
+;; or (at your option) any later version.
+;;
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library encodes S-expressions as GraphQl documents.  Currently
+;; it is rather incomplete and only intended for use by `ghub-graphql'
+;; but I might fill the gaps and add documentation eventually.  I am
+;; not in a hurry though.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defvar gsexp-one-variable-per-line nil)
+
+(defun gsexp-encode (document)
+  (gsexp--pp (gsexp--encode-field document)))
+
+(defun gsexp--encode-field (field)
+  (cond
+   ((stringp field)
+    field)
+   ((symbolp field)
+    (symbol-name field))
+   ((listp (car field))
+    (concat (format "%s: " (caar field))
+            (gsexp--encode-field (cons (car (cdar field))
+                                       (cdr field)))))
+   ((concat
+     (pcase (pop field)
+       (`[] "")
+       ((and (pred symbolp) op) (symbol-name op))
+       (`[,op] (symbol-name op))
+       (`[,op ,name] (format "%s %s" op name)))
+     (and (vectorp (car field))
+          (format " (%s%s)"
+                  (if gsexp-one-variable-per-line "\n" "")
+                  (mapconcat #'gsexp--encode-argument
+                             (append (pop field) nil)
+                             (if gsexp-one-variable-per-line ",\n" ","))))
+     (and field
+          (format " {\n%s\n}"
+                  (mapconcat #'gsexp--encode-field field "\n")))))))
+
+(cl-defun gsexp--encode-argument ((argument value))
+  (format "%s: %s" argument (gsexp--encode-value value)))
+
+(defun gsexp--encode-value (value)
+  (cond
+   ((numberp value)
+    (number-to-string value))
+   ((symbolp value) ; including variables, enums, booleans and null
+    (symbol-name value))
+   ((stringp value)
+    (prin1-to-string value))
+   ((vectorp value)
+    (format "(%s)" (mapconcat #'gsexp--encode-value value "")))
+   ((listp value)
+    (format "{%s}" (mapconcat
+                    (pcase-lambda (`(,name ,value))
+                      (format "%s: %s" name (gsexp--encode-value value)))
+                    value ", ")))
+   ((error "Invalid field value: %S" value))))
+
+(defun gsexp--pp (string)
+  (with-temp-buffer
+    (save-excursion
+      (insert string))
+    (while (< (point) (point-max))
+      (unless (and (bolp) (eolp))
+        (save-excursion
+          (let ((level (car (syntax-ppss (line-beginning-position)))))
+            (when (looking-at "\\s-*\\s)")
+              (cl-decf level))
+            (indent-line-to (* 2 level)))))
+      (forward-line 1))
+    (buffer-string)))
+
+;;; _
+(provide 'gsexp)
+;;; gsexp.el ends here