;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014 David Thompson ;;; Copyright © 2015, 2017, 2019, 2020, 2021, 2023 Ricardo Wurmus ;;; Copyright © 2015, 2016, 2017 Leo Famulari ;;; Copyright © 2016 Hartmut Goebel ;;; Copyright © 2016-2019, 2022, 2023 Marius Bakke ;;; Copyright © 2017 Danny Milosavljevic ;;; Copyright © 2017, 2018, 2020 Tobias Geerinckx-Rice ;;; Copyright © 2017 Frederick M. Muriithi ;;; Copyright © 2017 Christine Lemmer-Webber ;;; Copyright © 2017 Julien Lepiller ;;; Copyright © 2019, 2021, 2022 Efraim Flashner ;;; Copyright © 2019, 2021, 2023 Nicolas Goaziou ;;; Copyright © 2019 Alexandros Theodotou ;;; Copyright © 2019 Brett Gilio ;;; Copyright © 2020 Giacomo Leidi ;;; Copyright © 2021 Eric Bavier ;;; Copyright © 2021, 2022 Vinicius Monego ;;; Copyright © 2021 Hugo Lecomte ;;; Copyright © 2021, 2022 Maxim Cournoyer ;;; Copyright © 2024 Troy Figiel ;;; ;;; This file is part of GNU Guix. ;;; ;;; GNU Guix 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. ;;; ;;; GNU Guix 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 P
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016 Nikita <nikita@n0.is>
;;; Copyright © 2016 Sou Bunnbu <iyzsong@member.fsf.org>
;;; Copyright © 2017 Oleg Pykhalov <go.wigust@gmail.com>
;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
;;; Copyright © 2018 Christopher Baines <mail@cbaines.net>
;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix 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.
;;;
;;; GNU Guix 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 GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu services version-control)
  #:use-module (gnu services)
  #:use-module (gnu services base)
  #:use-module (gnu services shepherd)
  #:use-module (gnu services web)
  #:use-module (gnu system shadow)
  #:use-module (gnu packages version-control)
  #:use-module (gnu packages admin)
  #:use-module (guix deprecation)
  #:use-module (guix records)
  #:use-module (guix gexp)
  #:use-module (guix store)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-26)
  #:use-module (ice-9 format)
  #:use-module (ice-9 match)
  #:export (git-daemon-service
            git-daemon-service-type
            git-daemon-configuration
            git-daemon-configuration?

            git-http-configuration
            git-http-configuration?
            git-http-nginx-location-configuration

            <gitolite-configuration>
            gitolite-configuration
            gitolite-configuration-package
            gitolite-configuration-user
            gitolite-configuration-rc-file
            gitolite-configuration-admin-pubkey

            <gitolite-rc-file>
            gitolite-rc-file
            gitolite-rc-file-local-code
            gitolite-rc-file-umask
            gitolite-rc-file-unsafe-pattern
            gitolite-rc-file-git-config-keys
            gitolite-rc-file-roles
            gitolite-rc-file-enable

            gitolite-service-type

            gitile-configuration
            gitile-configuration-package
            gitile-configuration-host
            gitile-configuration-port
            gitile-configuration-database
            gitile-configuration-repositories
            gitile-configuration-git-base-url
            gitile-configuration-index-title
            gitile-configuration-intro
            gitile-configuration-footer
            gitile-configuration-nginx

            gitile-service-type))

;;; Commentary:
;;;
;;; Version Control related services.
;;;
;;; Code:


;;;
;;; Git daemon.
;;;

(define-record-type* <git-daemon-configuration>
  git-daemon-configuration
  make-git-daemon-configuration
  git-daemon-configuration?
  (package          git-daemon-configuration-package        ;file-like
                    (default git))
  (export-all?      git-daemon-configuration-export-all     ;boolean
                    (default #f))
  (base-path        git-daemon-configuration-base-path      ;string | #f
                    (default "/srv/git"))
  (user-path        git-daemon-configuration-user-path      ;string | #f
                    (default #f))
  (listen           git-daemon-configuration-listen         ;list of string
                    (default '()))
  (port             git-daemon-configuration-port           ;number | #f
                    (default #f))
  (whitelist        git-daemon-configuration-whitelist      ;list of string
                    (default '()))
  (extra-options    git-daemon-configuration-extra-options  ;list of string
                    (default '())))

(define git-daemon-shepherd-service
  (match-lambda
    (($ <git-daemon-configuration>
        package export-all? base-path user-path
        listen port whitelist extra-options)
     (let* ((git     (file-append package "/bin/git"))
            (command `(,git
                       "daemon" "--syslog" "--reuseaddr"
                       ,@(if export-all?
                             '("--export-all")
                             '())
                       ,@(if base-path
                             `(,(string-append "--base-path=" base-path))
                             '())
                       ,@(if user-path
                             `(,(string-append "--user-path=" user-path))
                             '())
                       ,@(map (cut string-append "--listen=" <>) listen)
                       ,@(if port
                             `(,(string-append
                                 "--port=" (number->string port)))
                             '())
                       ,@extra-options
                       ,@whitelist)))
       (list (shepherd-service
              (documentation "Run the git-daemon.")
              (requirement '(networking))
              (provision '(git-daemon))
              (start #~(make-forkexec-constructor '#$command
                                                  #:user "git-daemon"
                                                  #:group "git-daemon"))
              (stop #~(make-kill-destructor))))))))

(define %git-daemon-accounts
  ;; User account and group for git-daemon.
  (list (user-group
         (name "git-daemon")
         (system? #t))
        (user-account
         (name "git-daemon")
         (system? #t)
         (group "git-daemon")
         (comment "Git daemon user")
         (home-directory "/var/empty")
         (shell (file-append shadow "/sbin/nologin")))))

(define (git-daemon-activation config)
  "Return the activation gexp for git-daemon using CONFIG."
  (let ((base-path (git-daemon-configuration-base-path config)))
    #~(begin
        (use-modules (guix build utils))
        ;; Create the 'base-path' directory when it's not '#f'.
        (and=> #$base-path mkdir-p))))

(define git-daemon-service-type
  (service-type
   (name 'git-daemon)
   (extensions
    (list (service-extension shepherd-root-service-type
                             git-daemon-shepherd-service)
          (service-extension account-service-type
                             (const %git-daemon-accounts))
          (service-extension activation-service-type
                             git-daemon-activation)))
   (description
    "Expose Git repositories over the insecure @code{git://} TCP-based
protocol.")
   (default-value (git-daemon-configuration))))

(define-deprecated (git-daemon-service #:key (config (git-daemon-configuration)))
  git-daemon-service-type
  "Return a service that runs @command{git daemon}, a simple TCP server to
expose repositories over the Git protocol for anonymous access.

The optional @var{config} argument should be a
@code{<git-daemon-configuration>} object, by default it allows read-only
access to exported repositories under @file{/srv/git}."
  (service git-daemon-service-type config))


;;;
;;; HTTP access.  Add the result of calling
;;; git-http-nginx-location-configuration to an nginx-server-configuration's
;;; "locations" field.
;;;

(define-record-type* <git-http-configuration>
  git-http-configuration
  make-git-http-configuration
  git-http-configuration?
  (package          git-http-configuration-package        ;file-like
                    (default git))
  (git-root         git-http-configuration-git-root       ;string
                    (default "/srv/git"))
  (export-all?      git-http-configuration-export-all?    ;boolean
                    (default #f))
  (uri-path         git-http-configuration-uri-path       ;string
                    (default "/git/"))
  (fcgiwrap-socket  git-http-configuration-fcgiwrap-socket ;string
                    (default "127.0.0.1:9000")))

(define* (git-http-nginx-location-configuration #:optional
                                                (config
                                                 (git-http-configuration)))
  (match config
    (($ <git-http-configuration> package git-root export-all?
                                 uri-path fcgiwrap-socket)
     (nginx-location-configuration
      (uri (string-append "~ /" (string-trim-both uri-path #\/) "(/.*)"))
      (body
       (list
        (list "fastcgi_pass " fcgiwrap-socket ";")
        (list "fastcgi_param SCRIPT_FILENAME "
              package "/libexec/git-core/git-http-backend"
              ";")
        "fastcgi_param QUERY_STRING $query_string;"
        "fastcgi_param REQUEST_METHOD $request_method;"
        "fastcgi_param CONTENT_TYPE $content_type;"
        "fastcgi_param CONTENT_LENGTH $content_length;"
        (if export-all?
            "fastcgi_param GIT_HTTP_EXPORT_ALL \"\";"
            "")
        (list "fastcgi_param GIT_PROJECT_ROOT " git-root ";")
        "fastcgi_param PATH_INFO $1;"))))))


;;;
;;; Gitolite
;;;

(define-record-type* <gitolite-rc-file>
  gitolite-rc-file make-gitolite-rc-file
  gitolite-rc-file?
  (umask           gitolite-rc-file-umask
                   (default #o0077))
  (local-code      gitolite-rc-file-local-code
                   (default "$rc{GL_ADMIN_BASE}/local"))
  (unsafe-pattern  gitolite-rc-file-unsafe-pattern
                   (default #f))
  (git-config-keys gitolite-rc-file-git-config-keys
                   (default ""))
  (roles           gitolite-rc-file-roles
                   (default '(("READERS" . 1)
                              ("WRITERS" . 1))))
  (enable          gitolite-rc-file-enable
                   (default '("help"
                              "desc"
                              "info"
                              "perms"
                              "writable"
                              "ssh-authkeys"
                              "git-config"
                              "daemon"
                              "gitweb"))))

(define-gexp-compiler (gitolite-rc-file-compiler
                       (file <gitolite-rc-file>) system target)
  (match file
    (($ <gitolite-rc-file> umask local-code unsafe-pattern git-config-keys roles enable)
     (apply text-file* "gitolite.rc"
      `("%RC = (\n"
        "    UMASK => " ,(format #f "~4,'0o" umask) ",\n"
        "    GIT_CONFIG_KEYS => '" ,git-config-keys "',\n"
        ,(if local-code
             (simple-format #f "    LOCAL_CODE => \"~A\",\n" local-code)
             "")
        "    ROLES => {\n"
        ,@(map (match-lambda
                 ((role . value)
                  (simple-format #f "        ~A => ~A,\n" role value)))
               roles)
        "    },\n"
        "\n"
        "    ENABLE => [\n"
        ,@(map (lambda (value)
                 (simple-format #f "        '~A',\n" value))
               enable)
        "    ],\n"
        ");\n"
        "\n"
        ,(if unsafe-pattern
             (string-append "$UNSAFE_PATT = qr(" unsafe-pattern ");")
             "")
        "1;\n")))))

(define-record-type* <gitolite-configuration>
  gitolite-configuration make-gitolite-configuration
  gitolite-configuration?
  (package        gitolite-configuration-package
                  (default gitolite))
  (user           gitolite-configuration-user
                  (default "git"))
  (group          gitolite-configuration-group
                  (default "git"))
  (home-directory gitolite-configuration-home-directory
                  (default "/var/lib/gitolite"))
  (rc-file        gitolite-configuration-rc-file
                  (default (gitolite-rc-file)))
  (admin-pubkey   gitolite-configuration-admin-pubkey))

(define gitolite-accounts
  (match-lambda
    (($ <gitolite-configuration> package user group home-directory
                                 rc-file admin-pubkey)
     ;; User group and account to run Gitolite.
     (list (user-group (name group) (system? #t))
           (user-account
            (name user)
            (group group)
            (system? #t)
            (comment "Gitolite user")
            (home-directory home-directory))))))

(define gitolite-activation
  (match-lambda
    (($ <gitolite-configuration> package user group home
                                 rc-file admin-pubkey)
     #~(begin
         (use-modules (ice-9 match)
                      (guix build utils))

         (let* ((user-info (getpwnam #$user))
                (admin-pubkey #$admin-pubkey)
                (pubkey-file (string-append
                              #$home "/"
                              (basename
                               (strip-store-file-name admin-pubkey))))
                (rc-file #$(string-append home "/.gitolite.rc")))

           ;; activate-users+groups in (gnu build activation) sets the
           ;; permission flags of home directories to #o700 and mentions that
           ;; services needing looser permissions should chmod it during
           ;; service activation.  We also want the git group to be able to
           ;; read from the gitolite home directory, so a chmod'ing we will
           ;; go!
           (chmod #$home #o750)

           (simple-format #t "guix: gitolite: installing ~A\n" #$rc-file)
           (copy-file #$rc-file rc-file)
           ;; ensure gitolite's user can read the configuration
           (chown rc-file
                  (passwd:uid user-info)
                  (passwd:gid user-info))

           ;; The key must be writable, so copy it from the store
           (copy-file admin-pubkey pubkey-file)

           (chmod pubkey-file #o500)
           (chown pubkey-file
                  (passwd:uid user-info)
                  (passwd:gid user-info))

           ;; Set the git configuration, to avoid gitolite trying to use
           ;; the hostname command, as the network might not be up yet
           (with-output-to-file #$(string-append home "/.gitconfig")
             (lambda ()
               (display "[user]
        name = GNU Guix
        email = guix@localhost
")))
           ;; Run Gitolite setup, as this updates the hooks and include the
           ;; admin pubkey if specified. The admin pubkey is required for
           ;; initial setup, and will replace the previous key if run after
           ;; initial setup
           (match (primitive-fork)
             (0
              ;; Exit with a non-zero status code if an exception is thrown.
              (dynamic-wind
                (const #t)
                (lambda ()
                  (setenv "HOME" (passwd:dir user-info))
                  (setenv "USER" #$user)
                  (setgid (passwd:gid user-info))
                  (setuid (passwd:uid user-info))
                  (primitive-exit
                   (system* #$(file-append package "/bin/gitolite")
                            "setup"
                            "-m" "gitolite setup by GNU Guix"
                            "-pk" pubkey-file)))
                (lambda ()
                  (primitive-exit 1))))
             (pid (waitpid pid)))

           (when (file-exists? pubkey-file)
             (delete-file pubkey-file)))))))

(define gitolite-service-type
  (service-type
   (name 'gitolite)
   (extensions
    (list (service-extension activation-service-type
                             gitolite-activation)
          (service-extension account-service-type
                             gitolite-accounts)
          (service-extension profile-service-type
                             ;; The Gitolite package in Guix uses
                             ;; gitolite-shell in the authorized_keys file, so
                             ;; gitolite-shell needs to be on the PATH for
                             ;; gitolite to work.
                             (lambda (config)
                               (list
                                (gitolite-configuration-package config))))))
   (description
    "Set up @command{gitolite}, a Git hosting tool providing access over SSH.
By default, the @code{git} user is used, but this is configurable.
Additionally, Gitolite can integrate with with tools like gitweb or cgit to
provide a web interface to view selected repositories.")))

;;;
;;; Gitile
;;;

(define-record-type* <gitile-configuration>
  gitile-configuration make-gitile-configuration gitile-configuration?
  (package gitile-configuration-package
           (default gitile))
  (host gitile-configuration-host
        (default "127.0.0.1"))
  (port gitile-configuration-port
        (default 8080))
  (database gitile-configuration-database
            (default "/var/lib/gitile/gitile-db.sql"))
  (repositories gitile-configuration-repositories
                (default "/var/lib/gitolite/repositories"))
  (base-git-url gitile-configuration-base-git-url)
  (index-title gitile-configuration-index-title
               (default "Index"))
  (intro gitile-configuration-intro
         (default '()))
  (footer gitile-configuration-footer
          (default '()))
  (nginx gitile-configuration-nginx))

(define (gitile-config-file host port database repositories base-git-url
                            index-title intro footer)
  (define build
    #~(write `(config
                (port #$port)
                (host #$host)
                (database #$database)
                (repositories #$repositories)
                (base-git-url #$base-git-url)
                (index-title #$index-title)
                (intro #$intro)
                (footer #$footer))
             (open-output-file #$output)))

  (computed-file "gitile.conf" build))

(define gitile-nginx-server-block
  (match-lambda
    (($ <gitile-configuration> package host port database repositories
        base-git-url index-title intro footer nginx)
     (list (nginx-server-configuration
             (inherit nginx)
             (locations
               (append
                 (list
                   (nginx-location-configuration
                            (uri "/")
                            (body
                              (list
                                #~(string-append "proxy_pass http://" #$host
                                                 ":" (number->string #$port)
                                                 "/;")))))
                 (map
                   (lambda (loc)
                     (nginx-location-configuration
                       (uri loc)
                       (body
                         (list
                           #~(string-append "root " #$package "/share/gitile/assets;")))))
                   '("/css" "/js" "/images"))
                 (nginx-server-configuration-locations nginx))))))))

(define gitile-shepherd-service
  (match-lambda
    (($ <gitile-configuration> package host port database repositories
        base-git-url index-title intro footer nginx)
     (list (shepherd-service
             (provision '(gitile))
             (requirement '(loopback))
             (documentation "gitile")
             (start (let ((gitile (file-append package "/bin/gitile")))
                          #~(make-forkexec-constructor
                              `(,#$gitile "-c" #$(gitile-config-file
                                                   host port database
                                                   repositories
                                                   base-git-url index-title
                                                   intro footer))
                              #:user "gitile"
                              #:group "git")))
             (stop #~(make-kill-destructor)))))))

(define %gitile-accounts
  (list (user-group
         (name "git")
         (system? #t))
        (user-account
          (name "gitile")
          (group "git")
          (system? #t)
          (comment "Gitile user")
          (home-directory "/var/empty")
          (shell (file-append shadow "/sbin/nologin")))))

(define gitile-service-type
  (service-type
    (name 'gitile)
    (description "Run Gitile, a small Git forge.  Expose public repositories
on the web.")
    (extensions
      (list (service-extension account-service-type
                               (const %gitile-accounts))
            (service-extension shepherd-root-service-type
                               gitile-shepherd-service)
            (service-extension nginx-service-type
                               gitile-nginx-server-block)))))
(sha256 (base32 "06jzgp213zihnvpcy2y5jy3ykid3apc2ncp2pg6a2g05lhiziglq")))) (build-system python-build-system) (home-page "https://github.com/stephenmcd/sphinx-me") (synopsis "Create a Sphinx documentation shell") (description "Create a Sphinx documentation shell for your project and include the README file as the documentation index. It handles extracting the required meta data such as the project name, author and version from your project for use in your Sphinx docs.") (license license:bsd-2))) (define-public python-sphinx-repoze-autointerface (package (name "python-sphinx-repoze-autointerface") (version "0.8") (source (origin (method url-fetch) (uri (pypi-uri "repoze.sphinx.autointerface" version)) (sha256 (base32 "08ycivzf7bh4a1zcyp31hbyqs1b2c9r26raa3vxjwwmbfqr3iw4f")))) (build-system python-build-system) (arguments '(#:tests? #f)) ; No tests. (propagated-inputs (list python-sphinx python-zope-interface)) (synopsis "Auto-generate Sphinx API docs from Zope interfaces") (description "This package defines an extension for the Sphinx documentation system. The extension allows generation of API documentation by introspection of @code{zope.interface} instances in code.") (home-page "https://github.com/repoze/repoze.sphinx.autointerface") (license license:repoze))) (define-public python-sphinx-prompt (package (name "python-sphinx-prompt") (version "1.5.0") (source (origin (method git-fetch) ; no source release in PyPI (uri (git-reference (url "https://github.com/sbrunner/sphinx-prompt") (commit version))) (file-name (git-file-name name version)) (sha256 (base32 "0x9wmgf04rzivbzp7jv1b7fkhkpi02lpk5w1qf4i7bcgih00ym8a")) (patches (search-patches "python-sphinx-prompt-docutils-0.19.patch")))) (build-system python-build-system) (arguments `(#:phases (modify-phases %standard-phases (replace 'check (lambda* (#:key inputs outputs tests? #:allow-other-keys) (when tests? (add-installed-pythonpath inputs outputs) (invoke "python" "-m" "pytest"))))))) (native-inputs (list python-pytest python-sphinx)) (home-page "https://github.com/sbrunner/sphinx-prompt") (synopsis "Sphinx directive to add unselectable prompt") (description "This package provides a Sphinx directive to add unselectable prompt.") (license license:bsd-3))) (define-public python-sphinx-alabaster-theme (package (name "python-sphinx-alabaster-theme") (version "0.7.12") (source (origin (method url-fetch) (uri (pypi-uri "alabaster" version)) (sha256 (base32 "00nwwjj2d2ym4s2kk217x7jkx1hnczc3fvm8yxbqmsp6b0nxfqd6")))) (build-system python-build-system) (propagated-inputs (list python-pygments)) (home-page "https://alabaster.readthedocs.io/") (synopsis "Configurable sidebar-enabled Sphinx theme") (description "Alabaster is a visually (c)lean, responsive, configurable theme for the Sphinx documentation system. It's the default theme of Sphinx.") (license license:bsd-3))) (define-public python-sphinx-argparse (package (name "python-sphinx-argparse") (version "0.3.1") (source (origin (method url-fetch) (uri (pypi-uri "sphinx-argparse" version)) (sha256 (base32 "07nw68nrbpzsswb5bz8gdb5allgj6jnz8m81afhr9v6c8fyiq5c2")))) (build-system python-build-system) (propagated-inputs (list python-sphinx)) (native-inputs (list python-commonmark python-pytest python-sphinx-rtd-theme)) (home-page "https://github.com/ribozz/sphinx-argparse") (synopsis "Sphinx extension for documenting argparse commands and options") (description "This package is a sphinx extension that automatically documents argparse commands and options") (license license:expat))) ;;; FIXME: Currently broken by Jinja >= 3.10 (see: ;;; https://foss.heptapod.net/doc-utils/cloud_sptheme/-/issues/47). (define-public python-sphinx-cloud-sptheme (package (name "python-sphinx-cloud-sptheme") (version "1.10.1") (source (origin (method hg-fetch) (uri (hg-reference (url "https://foss.heptapod.net/doc-utils/cloud_sptheme") (changeset version))) (file-name (hg-file-name name version)) (sha256 (base32 "0k0pgi0vcn8vdy3k6x11fpp4mqp7p3l6n6pjfi3mir3vwjhdfz7l")))) (build-system python-build-system) (native-inputs (list python-mock)) (propagated-inputs (list python-sphinx)) (home-page "https://foss.heptapod.net/doc-utils/cloud_sptheme") (synopsis "Cloud theme for Sphinx") (description "This package contains the @emph{Cloud} theme for Sphinx and some related extensions.") (license license:bsd-3))) (define-public python-guzzle-sphinx-theme (package (name "python-guzzle-sphinx-theme") (version "0.7.11") (source (origin (method url-fetch) (uri (pypi-uri "guzzle_sphinx_theme" version)) (sha256 (base32 "1rnkzrrsbnifn3vsb4pfaia3nlvgvw6ndpxp7lzjrh23qcwid34v")))) (build-system python-build-system) (propagated-inputs (list python-sphinx)) (home-page "https://github.com/guzzle/guzzle_sphinx_theme") (synopsis "Sphinx theme used by Guzzle") (description "This package provides guzzle_sphinx_theme, a theme for the Sphinx documentation system, used by @uref{http://docs.guzzlephp.org, Guzzle} and several other projects.") (license license:expat))) (define-public python-mpl-sphinx-theme (package (name "python-mpl-sphinx-theme") (version "3.5.0") (source (origin (method url-fetch) (uri (pypi-uri "mpl_sphinx_theme" version)) (sha256 (base32 "0ilsw6s5hfvjzqs3258c8gmg5v3dwa6k69mwmkxsyh1qmv15krpw")))) (build-system python-build-system) (propagated-inputs (list python-pydata-sphinx-theme)) (home-page "https://github.com/matplotlib/mpl-sphinx-theme") (synopsis "Matplotlib theme for Sphinx") (description "This package provides a Matplotlib theme for Sphinx.") (license license:bsd-3))) (define-public python-myst-parser (package (name "python-myst-parser") (version "0.18.1") (source (origin (method git-fetch) ;for tests (uri (git-reference (url "https://github.com/executablebooks/MyST-Parser") (commit (string-append "v" version)))) (file-name (git-file-name name version)) (sha256 (base32 "0lcz9vvy8hbp6cjmbslrlxn3pinf98jykiq8nx5lw5y0lz0mj162")))) (build-system pyproject-build-system) (arguments ;; There are 3 test failures, seemingly due to expecting a slightly ;; different output from Sphinx (see: ;; https://github.com/executablebooks/MyST-Parser/issues/645). (list #:test-flags #~(list "-k" (string-append "not test_basic " "and not test_gettext_html " "and not test_fieldlist_extension")))) (native-inputs (list python-beautifulsoup4 python-docutils python-flit-core python-pytest python-pytest-param-files python-pytest-regressions python-sphinx python-sphinx-pytest)) (propagated-inputs (list python-docutils python-jinja2 python-linkify-it-py python-markdown-it-py python-linkify-it-py python-mdit-py-plugins python-pyyaml python-sphinx python-typing-extensions)) (home-page "https://myst-parser.readthedocs.io/en/latest/") (synopsis "Sphinx and Docutils extension to parse MyST") (description "This package provides a Sphinx and Docutils extension to parse MyST, a rich and extensible flavour of Markdown for authoring technical and scientific documentation.") (license license:expat))) (define-public python-sphinx-rtd-theme (package (name "python-sphinx-rtd-theme") (version "1.0.0") (source (origin (method url-fetch) (uri (pypi-uri "sphinx_rtd_theme" version)) (sha256 (base32 "0p3abj91c3l72ajj5jwblscsdf1jflrnn0djx2h5y6f2wjbx9ipf")))) (build-system python-build-system) (arguments (list #:tests? #f ; No tests. #:phases #~(modify-phases %standard-phases (add-after 'unpack 'allow-newer-docutil (lambda _ (substitute* "setup.py" (("docutils<0.18") "docutils<0.20"))))))) (propagated-inputs (list python-docutils python-sphinx)) (home-page "https://github.com/snide/sphinx_rtd_theme/") (synopsis "ReadTheDocs.org theme for Sphinx") (description "A theme for Sphinx used by ReadTheDocs.org.") (license license:expat))) (define-public python-breathe (package (name "python-breathe") (version "4.35.0") (source (origin (method git-fetch) ;git repo has tests (uri (git-reference (url "https://github.com/breathe-doc/breathe") (commit (string-append "v" version)))) (file-name (git-file-name name version)) (sha256 (base32 "1hlcrhr533yjkz9ds83xnmn8h6z3r6vfzz7qrpy14n9j4ysyz59c")))) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (with-directory-excursion "tests" (invoke "python" "-m" "pytest" "-v")))))))) (native-inputs (list python-pytest)) (propagated-inputs (list python-docutils python-sphinx)) (home-page "https://www.breathe-doc.org") (synopsis "ReStructuredText and Sphinx bridge to Doxygen") (description "This package is an extension to reStructuredText and Sphinx to be able to read and render the Doxygen xml output.") (license license:bsd-3))) (define-public python-sphinx-intl (package (name "python-sphinx-intl") (version "2.0.1") (source (origin (method url-fetch) (uri (pypi-uri "sphinx-intl" version)) (sha256 (base32 "1d1q0sanjp4nkfvhsxi75zf3xjyyi8nzxvl3v7l0jy9ld70nwnmj")))) (build-system python-build-system) (propagated-inputs (list python-sphinx python-click)) (home-page "https://github.com/sphinx-doc/sphinx-intl") (synopsis "Sphinx utility that makes it easy to translate and to apply translation") (description "A utility tool that provides several features that make it easy to translate and to apply translation to Sphinx generated document.") (license license:bsd-2))) (define-public python-sphinxext-opengraph (package (name "python-sphinxext-opengraph") (version "0.6.3") (source (origin (method git-fetch) ; no tests in PyPI release (uri (git-reference (url "https://github.com/wpilibsuite/sphinxext-opengraph") (commit (string-append "v" version)))) (file-name (git-file-name name version)) (sha256 (base32 "1wrgpan9z65fv4hbvisz4sypc4w5ammnxkyn5lhr43wdr6b967k1")))) (build-system python-build-system) (arguments `(#:phases (modify-phases %standard-phases (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest" "-vv"))))))) (native-inputs (list python-beautifulsoup4 python-pytest python-sphinx)) (home-page "https://github.com/wpilibsuite/sphinxext-opengraph") (synopsis "Sphinx Extension to enable OpenGraph support") (description "This package provides a Sphinx Extension to generate OG metadata.") (license license:bsd-3))) (define-public python-sphinx-autobuild (package (name "python-sphinx-autobuild") (version "2021.3.14") (source (origin (method url-fetch) (uri (pypi-uri "sphinx-autobuild" version)) (sha256 (base32 "019z8kvnaw11r41b6pfdy9iz4iwyr0s51hs0a5djn797dsva676y")))) (build-system python-build-system) (arguments '(#:phases (modify-phases %standard-phases (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest" "-vv"))))))) (propagated-inputs (list python-colorama python-livereload python-sphinx)) (native-inputs (list python-pytest)) (home-page "https://github.com/GaretJax/sphinx-autobuild") (synopsis "Rebuild Sphinx documentation when a change is detected") (description "This package lets you watch a Sphinx directory and rebuild the documentation when a change is detected. It also includes a livereload enabled web server.") (license license:expat))) (define-public python-sphinx-autodoc-typehints (package (name "python-sphinx-autodoc-typehints") (version "1.18.3") (source (origin (method git-fetch) ;no tests in pypi archive (uri (git-reference (url "https://github.com/tox-dev/sphinx-autodoc-typehints") (commit version))) (file-name (git-file-name name version)) (sha256 (base32 "049dlay21f4bccig31fkbzq2m8v0h6g63p1cn3dxay9q3h0mzgs0")))) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (add-before 'build 'pretend-version ;; The version string is usually derived via setuptools-scm, but ;; without the git metadata available, the version string is set to ;; '0.0.0'. (lambda _ (setenv "SETUPTOOLS_SCM_PRETEND_VERSION" #$version))) (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest" "-vv" "tests" ;; This test requires to download an objects.inv file ;; from the Sphinx website. "-k" "not test_format_annotation"))))))) (propagated-inputs (list python-sphinx)) (native-inputs (list python-nptyping python-pytest python-setuptools-scm python-sphobjinv python-typing-extensions)) (home-page "https://pypi.org/project/sphinx-autodoc-typehints/") (synopsis "Type hints for the Sphinx autodoc extension") (description "This extension allows you to use Python 3 annotations for documenting acceptable argument types and return value types of functions.") (license license:expat))) (define-public python-sphinx-pytest (package (name "python-sphinx-pytest") (version "0.0.5") (source (origin (method url-fetch) (uri (pypi-uri "sphinx_pytest" version)) (sha256 (base32 "13d3psm5vyb8rdj0mhnpn5m09k8xdaszcxdpng52fpz9sw8pngk7")))) (build-system pyproject-build-system) (native-inputs (list python-flit-core)) (propagated-inputs (list python-pytest python-sphinx)) (home-page "https://github.com/chrisjsewell/sphinx-pytest") (synopsis "Pytest fixtures for Sphinx extensions") (description "This Pytest extension mainly provides some Pytest fixtures to simulate converting some source text to Docutils @acronym{AST, Abstract Syntax Tree} at different stages: before transforms, after transforms, etc.") (license license:expat))) (define-public python-nbsphinx (package (name "python-nbsphinx") (version "0.8.8") (source (origin (method url-fetch) (uri (pypi-uri "nbsphinx" version)) (sha256 (base32 "1v1lzkfx2lslhslqb110zxmm4dmdg6hs2rahf713c2rk9f10q2dm")))) (build-system python-build-system) (propagated-inputs (list python-docutils python-jinja2 python-nbconvert python-nbformat python-sphinx python-traitlets)) (home-page "https://nbsphinx.readthedocs.io/") (synopsis "Jupyter Notebook Tools for Sphinx") (description "@code{python-nbsphinx} is a Sphinx extension that provides a source parser for @code{*.ipynb} files. Custom Sphinx directives are used to show Jupyter Notebook code cells (and of course their results) in both HTML and LaTeX output. Un-evaluated notebooks - i.e. notebooks without stored output cells - will be automatically executed during the Sphinx build process.") (license license:expat))) (define-public python-sphobjinv (package (name "python-sphobjinv") (version "2.0.1") (source (origin (method url-fetch) (uri (pypi-uri "sphobjinv" version)) (sha256 (base32 "126lgm54c94ay3fci512ap4l607gak90pbz0fk98syxvj5izrrzx")))) (build-system python-build-system) (propagated-inputs (list python-attrs python-certifi python-fuzzywuzzy python-jsonschema python-levenshtein)) (home-page "https://github.com/bskinn/sphobjinv") (synopsis "Sphinx cross-reference tool") (description "Sphinx objects.inv inspection/manipulation tool.") (license license:expat))) (define-public python-jupyter-sphinx (package (name "python-jupyter-sphinx") (version "0.3.2") (source (origin ;; Pypi tarball doesn't contain tests. (method git-fetch) (uri (git-reference (url "https://github.com/jupyter/jupyter-sphinx") (commit (string-append "v" version)))) (file-name (git-file-name name version)) (sha256 (base32 "0bsb17vzbgvrzvh87pi88b157hyigdwnf1lhrgvan03i2300h15c")))) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest"))))))) (propagated-inputs (list python-ipython python-ipywidgets python-nbconvert python-nbformat)) (native-inputs (list python-pytest python-sphinx)) (home-page "https://github.com/jupyter/jupyter-sphinx/") (synopsis "Jupyter Sphinx Extensions") (description "Jupyter-sphinx is a Sphinx extension that executes embedded code in a Jupyter kernel, and embeds outputs of that code in the document. It has support for rich output such as images, LaTeX math and even JavaScript widgets, and supports thebelab for live code execution with minimal effort.") (license license:bsd-3))) (define-public python-sphinxcontrib-autoprogram (package (name "python-sphinxcontrib-autoprogram") (version "0.1.8") (source (origin (method url-fetch) (uri (pypi-uri "sphinxcontrib-autoprogram" version)) (sha256 (base32 "02pi450qml429disph075jyqwjrawrhbsjfkqvjf10yjp6fp4sas")))) (build-system python-build-system) (propagated-inputs (list python-six python-sphinx)) (home-page "https://github.com/sphinx-contrib/autoprogram") (synopsis "Documenting CLI programs") (description "This Sphinx extension, @code{sphinxcontrib.autoprogram}, provides an automated way to document command-line programs. It scans @code{argparse.ArgumentParser} object, and then expands it into a set of @code{.. program::} and @code{.. option::} directives.") (license license:bsd-2))) (define-public python-sphinx-theme-builder (package (name "python-sphinx-theme-builder") (version "0.2.0b1") (source (origin (method git-fetch) ;no tests in pypi archive (uri (git-reference (url "https://github.com/pradyunsg/sphinx-theme-builder") (commit version))) (file-name (git-file-name name version)) (sha256 (base32 "15gvwzd4l3wcmd6fns8xvv44yzxmamr1nfn28mp12sdw2y10v2ba")))) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases ;; XXX: PEP 517 manual build copied from python-isort. (replace 'build (lambda _ ;; ZIP does not support timestamps before 1980. (setenv "SOURCE_DATE_EPOCH" "315532800") (invoke "python" "-m" "build" "--wheel" "--no-isolation" "."))) (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest" "-vv")))) (replace 'install (lambda _ (let ((whl (car (find-files "dist" "\\.whl$")))) (invoke "pip" "--no-cache-dir" "--no-input" "install" "--no-deps" "--prefix" #$output whl))))))) (native-inputs (list python-flit-core python-pytest)) (propagated-inputs (list python-pypa-build python-click python-nodeenv python-packaging python-pyproject-metadata python-rich python-sphinx-autobuild python-tomli)) (home-page "https://github.com/pradyunsg/sphinx-theme-builder") (synopsis "Tool for authoring Sphinx themes") (description "This package provides a tool for authoring Sphinx themes with a simple (opinionated) workflow.") (license license:expat))) (define-public python-sphinx-sitemap (package (name "python-sphinx-sitemap") (version "2.2.0") (source (origin (method url-fetch) (uri (pypi-uri "sphinx-sitemap" version)) (sha256 (base32 "0dvpryrz7vn8rvayzy5nrmqy4wyzlaxcx88bl46prc9w4cwxmbb5")))) (build-system python-build-system) (propagated-inputs (list python-sphinx)) (home-page "https://github.com/jdillard/sphinx-sitemap") (synopsis "Sitemap generator for Sphinx") (description "A Sphinx extension to generate multiversion and multilanguage sitemaps.org compliant sitemaps for the HTML version of your Sphinx documentation.") (license license:expat))) (define-public python-pydata-sphinx-theme (package (name "python-pydata-sphinx-theme") ;; TODO: This is not the latest release, but the 0.8.x series introduced a ;; new Sphinx theme build system that complicate things (see: ;; https://github.com/pydata/pydata-sphinx-theme/issues/628 and ;; https://src.fedoraproject.org/rpms/python-pydata-sphinx-theme ;; /blob/rawhide/f/prepare_vendor.sh). (version "0.7.2") (source (origin (method url-fetch) (uri (pypi-uri "pydata-sphinx-theme" version)) (sha256 (base32 "0ph69bnnw9w8vksc7rk45q5yknsrsgk9a19xsbxym46jrmgz67b7")))) (build-system python-build-system) (arguments (list #:phases #~(modify-phases %standard-phases (replace 'check (lambda* (#:key tests? #:allow-other-keys) (when tests? (invoke "pytest" "-vv"))))))) (propagated-inputs (list python-beautifulsoup4 python-docutils python-jinja2 python-sphinx)) (native-inputs (list python-pytest python-pytest-regressions)) (home-page "https://github.com/pydata/pydata-sphinx-theme") (synopsis "Bootstrap-based Sphinx theme") (description "This package provides a Bootstrap-based Sphinx theme from the PyData community.") (license license:bsd-3)))