;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2019, 2022 Ludovic Courtès ;;; Copyright © 2021, 2022, 2023 Ricardo Wurmus ;;; Copyright © 2021 Hugo Lecomte ;;; Copyright © 2022 Marius Bakke ;;; Copyright © 2022 Maxim Cournoyer ;;; ;;; 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. I
aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2013 Cyril Roelandt <tipecaml@gmail.com>
;;; Copyright © 2013-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2014, 2016, 2019, 2021 Eric Bavier <bavier@posteo.net>
;;; Copyright © 2015-2024 Flashner <efraim@flashner.co.il>
;;; Copyright © 2015, 2018, 2020, 2021, 2022 Kyle Meyer <kyle@kyleam.com>
;;; Copyright © 2015, 2017, 2018, 2020 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2016, 2017 Leo Famulari <leo@famulari.name>
;;; Copyright © 2016, 2017, 2018 Nikita <nikita@n0.is>
;;; Copyright © 2017–2022 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2017 Vasile Dumitrascu <va511e@yahoo.com>
;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
;;; Copyright © 2017, 2020 EuAndreh <eu@euandre.org>
;;; Copyright © 2017, 2018, 2020, 2022 Marius Bakke <marius@gnu.org>
;;; Copyright © 2017 Stefan Reichör <stefan@xsteve.at>
;;; Copyright © 2017, 2020, 2024 Oleg Pykhalov <go.wigust@gmail.com>
;;; Copyright © 2018 Sou Bunnbu <iyzsong@member.fsf.org>
;;; Copyright © 2018 Christopher Baines <mail@cbaines.net>
;;; Copyright © 2018 Timothy Sample <samplet@ngyro.com>
;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
;;; Copyright © 2019 Jovany Leandro G.C <bit4bit@riseup.net>
;;; Copyright © 2019 Kei Kebreau <kkebreau@posteo.net>
;;; Copyright © 2019, 2020 Alex Griffin <a@ajgrf.com>
;;; Copyright © 2020 Roel Janssen <roel@gnu.org>
;;; Copyright © 2020, 2021 Brice Waegeneire <brice@waegenei.re>
;;; Copyright © 2020 John D. Boy <jboy@bius.moe>
;;; Copyright © 2020, 2023, 2024 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2020, 2021, 2022, 2023 Vinicius Monego <monego@posteo.net>
;;; Copyright © 2020 Tanguy Le Carrour <tanguy@bioneland.org>
;;; Copyright © 2020, 2021, 2022 Michael Rohleder <mike@rohleder.de>
;;; Copyright © 2021 Greg Hogan <code@greghogan.com>
;;; Copyright © 2021, 2022, 2023, 2024 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2021 Chris Marusich <cmmarusich@gmail.com>
;;; Copyright © 2021 Léo Le Bouter <lle-bout@zaclys.net>
;;; Copyright © 2021 LibreMiami <packaging-guix@libremiami.org>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2021 François J. <francois-oss@avalenn.eu>
;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2021 Guillaume Le Vaillant <glv@posteo.net>
;;; Copyright © 2021, 2024 jgart <jgart@dismail.de>
;;; Copyright © 2021 Foo Chuan Wei <chuanwei.foo@hotmail.com>
;;; Copyright © 2022 Jai Vetrivelan <jaivetrivelan@gmail.com>
;;; Copyright © 2022 Maxime Devos <maximedevos@telenet.be>
;;; Copyright © 2022 Dhruvin Gandhi <contact@dhruvin.dev>
;;; Copyright © 2015, 2022 David Thompson <davet@gnu.org>
;;; Copyright © 2023 Nicolas Graves <ngraves@ngraves.fr>
;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;; Copyright © 2023 Kjartan Oli Agustsson <kjartanoli@disroot.org>
;;; Copyright © 2023 Steve George <steve@futurile.net>
;;; Copyright © 2023 Josselin Poiret <dev@jpoiret.xyz>
;;; Copyright © 2024 Hilton Chain <hako@ultrarare.space>
;;; Copyright © 2023 Zheng Junjie <873216071@qq.com>
;;; Copyright © 2024 Suhail Singh <suhail@bayesians.ca>
;;;
;;; 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 packages version-control)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix utils)
  #:use-module (guix packages)
  #:use-module (guix deprecation)
  #:use-module (guix gexp)
  #:use-module (guix download)
  #:use-module (guix git-download)
  #:use-module (guix hg-download)
  #:use-module (guix build-system cargo)
  #:use-module (guix build-system cmake)
  #:use-module (guix build-system copy)
  #:use-module (guix build-system gnu)
  #:use-module (guix build-system go)
  #:use-module (guix build-system perl)
  #:use-module (guix build-system pyproject)
  #:use-module (guix build-system python)
  #:use-module (guix build-system qt)
  #:use-module (guix build-system trivial)
  #:use-module (gnu packages apr)
  #:use-module (gnu packages autotools)
  #:use-module (gnu packages documentation)
  #:use-module (gnu packages base)
  #:use-module (gnu packages bash)
  #:use-module (gnu packages bison)
  #:use-module (gnu packages boost)
  #:use-module (gnu packages check)
  #:use-module (gnu packages cook)
  #:use-module (gnu packages crates-io)
  #:use-module (gnu packages crates-vcs)
  #:use-module (gnu packages curl)
  #:use-module (gnu packages databases)
  #:use-module (gnu packages docbook)
  #:use-module (gnu packages file)
  #:use-module (gnu packages flex)
  #:use-module (gnu packages freedesktop)
  #:use-module (gnu packages gettext)
  #:use-module (gnu packages gl)
  #:use-module (gnu packages glib)
  #:use-module (gnu packages gnome)
  #:use-module (gnu packages gnupg)
  #:use-module (gnu packages golang)
  #:use-module (gnu packages golang-build)
  #:use-module (gnu packages golang-check)
  #:use-module (gnu packages golang-crypto)
  #:use-module (gnu packages golang-web)
  #:use-module (gnu packages golang-xyz)
  #:use-module (gnu packages groff)
  #:use-module (gnu packages guile)
  #:use-module (gnu packages guile-xyz)
  #:use-module (gnu packages image)
  #:use-module (gnu packages imagemagick)
  #:use-module (gnu packages linux)
  #:use-module (gnu packages mail)
  #:use-module (gnu packages man)
  #:use-module (gnu packages maths)
  #:use-module (gnu packages ncurses)
  #:use-module (gnu packages ssh)
  #:use-module (gnu packages web)
  #:use-module (gnu packages patchutils)
  #:use-module (gnu packages pcre)
  #:use-module (gnu packages perl)
  #:use-module (gnu packages perl-check)
  #:use-module (gnu packages php)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages python)
  #:use-module (gnu packages python-build)
  #:use-module (gnu packages python-check)
  #:use-module (gnu packages python-crypto)
  #:use-module (gnu packages python-web)
  #:use-module (gnu packages python-xyz)
  #:use-module (gnu packages readline)
  #:use-module (gnu packages ruby)
  #:use-module (gnu packages sqlite)
  #:use-module (gnu packages texinfo)
  #:use-module (gnu packages text-editors)
  #:use-module (gnu packages admin)
  #:use-module (gnu packages xml)
  #:use-module (gnu packages emacs)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages sdl)
  #:use-module (gnu packages swig)
  #:use-module (gnu packages sync)
  #:use-module (gnu packages tcl)
  #:use-module (gnu packages textutils)
  #:use-module (gnu packages time)
  #:use-module (gnu packages tls)
  #:use-module (gnu packages)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)
  #:export (make-gitolite))

(define-public breezy
  (package
    (name "breezy")
    (version "3.2.2")
    (source
     (origin
       (method url-fetch)
       (uri (string-append "https://launchpad.net/brz/"
                           (version-major+minor version) "/" version
                           "/+download/breezy-" version ".tar.gz"))
       (modules '((guix build utils)))
       ;; Delete pre-generated Cython C files.
       (snippet '(for-each delete-file (find-files "." "\\pyx.c$")))
       (sha256
        (base32
         "1md4b6ajawf5h50fqizmjj0g833ihc674dh7fn0mvl4d412nwyhq"))
       (patches (search-patches "breezy-fix-gio.patch"))))
    (build-system python-build-system)
    (arguments
     (list
      #:tests? #f                       ;FIXME: the test suite hangs
      #:phases
      #~(modify-phases %standard-phases
          (add-after 'unpack 'patch-test-shebangs
            (lambda _
              (substitute* (append (find-files "breezy/bzr/tests")
                                   (find-files "breezy/tests"))
                (("#!/bin/sh")
                 (format #f "#!~a" (which "sh"))))))
          (replace 'check
            (lambda* (#:key tests? #:allow-other-keys)
              (when tests?
                ;; The test_read_bundle tests fails with "TypeError: a
                ;; bytes-like object is required, not '_ResultTuple'" (see:
                ;; https://bugs.launchpad.net/brz/+bug/1968415/comments/4).
                (substitute* "breezy/bzr/tests/__init__.py"
                  (("'test_read_bundle'," all)
                   (string-append "# " all)))
                (setenv "BZR_EDITOR" "nano")
                (setenv "HOME" "/tmp")
                (invoke "testr" "init")
                (invoke "testr" "run")))))))
    (native-inputs
     (list nano                         ;for tests
           python-cython
           python-docutils
           python-subunit
           python-testrepository))
    (inputs
     (list gettext-minimal
           python-configobj
           python-dulwich
           python-fastbencode
           python-fastimport
           python-launchpadlib
           python-paramiko
           python-patiencediff
           python-pycryptodome
           python-pygobject
           python-pygpgme))
    (home-page "https://www.breezy-vcs.org/")
    (synopsis "Decentralized revision control system")
    (description
     "Breezy (@command{brz}) is a decentralized revision control system.  By
default, Breezy provides support for both the
@uref{https://bazaar.canonical.com/, Bazaar} and @uref{https://www.git-scm.com,
Git} file formats.  Breezy is backwabrds compatible with Bazaar's disk format
and protocols.  One of the key differences with Bazaar is that Breezy runs on
Python 3.3 and later, rather than on Python 2.")
    (license license:gpl2+)))

(define-public bazaar
  (deprecated-package "bazaar" breezy))

(define git-cross-configure-flags
  #~(list "ac_cv_fread_reads_directories=yes"
          "ac_cv_snprintf_returns_bogus=no"
          "ac_cv_iconv_omits_bom=no"))

;; The size of the closure of 'git-minimal' is two thirds that of 'git'.
;; Its test suite runs slightly faster and most importantly it doesn't
;; depend on packages that are expensive to build such as Subversion.
(define-public git-minimal
  (package
    (name "git-minimal")
    (version "2.45.2")
    (source (origin
             (method url-fetch)
             (uri (string-append "mirror://kernel.org/software/scm/git/git-"
                                 version ".tar.xz"))
             (sha256
              (base32
               "1nws1vjgj54sv32wxl1h3n1jkcpabqv7a605hhafsby0n5zfigsi"))))
    (build-system gnu-build-system)
    (arguments
     (list
      #:modules `((srfi srfi-1)
                  (srfi srfi-26)
                  (ice-9 format)
                  (ice-9 textual-ports)
                  ((guix build gnu-build-system) #:prefix gnu:)
                  ,@%default-gnu-modules)
      ;; Make sure the full bash does not end up in the final closure.
      #:disallowed-references (list bash perl)
      #:test-target "test"
      #:configure-flags
      (if (%current-target-system)
          git-cross-configure-flags
          #~(list))
      #:make-flags
      #~(list "V=1"                     ;more verbose compilation
              (string-append "SHELL_PATH="
                             #+(this-package-native-input "bash-minimal")
                             "/bin/sh")

              ;; Tests require a bash with completion support.
              (string-append "TEST_SHELL_PATH="
                             #+(this-package-native-input "bash")
                             "/bin/bash")

              ;; By default 'make install' creates hard links for
              ;; things in 'libexec/git-core', which leads to huge
              ;; nars; see <https://bugs.gnu.org/21949>.
              "NO_INSTALL_HARDLINKS=indeed")
      #:phases
      #~(modify-phases %standard-phases
          #$@(if (%current-target-system)
                 ;; The git build system assumes build == host
                 #~((add-after 'unpack  'use-host-uname_S
                      (lambda _
                        (substitute* "config.mak.uname"
                          (("uname_S := .*" all)
                           (if (equal? #$(%current-target-system) "i586-pc-gnu")
                               "uname_S := GNU\n"
                               all))))))
                 ;; We do not have a full bash when cross-compiling.
                 #~((add-after 'unpack 'modify-PATH
                      (lambda* (#:key inputs #:allow-other-keys)
                        (let ((path (string-split (getenv "PATH") #\:))
                              (bash-full #$(this-package-native-input "bash")))
                          ;; Drop the test bash from PATH so that (which "sh")
                          ;; and similar does the right thing.
                          (setenv "PATH"
                                  (string-join
                                   (remove (cut string-prefix? bash-full <>)
                                           path)
                                   ":")))))))
          #$@(if (system-hurd?)
                 #~((add-after 'unpack 'delete-tests/hurd
                      (lambda _
                        (delete-file "t/t0052-simple-ipc.sh")
                        (delete-file "t/t5562-http-backend-content-length.sh")
                        (delete-file "t/t9902-completion.sh"))))
                 #~())
          ;; Add cross curl-config script to PATH when cross-compiling.
          #$@(if (%current-target-system)
                 #~((add-before 'configure 'add-cross-curl-config
                      (lambda* (#:key inputs #:allow-other-keys)
                        (setenv "PATH"
                                (string-append
                                 (dirname (search-input-file
                                           inputs "bin/curl-config"))
                                 ":" (getenv "PATH"))))))
                 #~())
          (add-after 'unpack 'patch-commands
            (lambda* (#:key inputs #:allow-other-keys)
              (define (prepend-string-to-file text file)
                "Prepend TEXT to FILE."
                (let ((content (call-with-input-file file
                                 (cut get-string-all <>))))
                  (call-with-output-file file
                    (lambda (port)
                      (display text port)
                      (display content port)))))

              (define PATH-variable-definition
                (format #f "PATH=~{~a~^:~}${PATH:+:}$PATH~%~%"
                        (map (compose dirname (cut search-input-file inputs <>))
                             '("bin/basename"
                               "bin/sed"))))

              ;; Ensure that coreutils (for basename) and sed are on PATH
              ;; for any script that sources the 'git-sh-setup.sh' file.
              (prepend-string-to-file PATH-variable-definition
                                      "git-sh-setup.sh")

              ;; Avoid depending on util-linux; it's only used to detect
              ;; whether the system is MinGW, which we can detect at build
              ;; time.
              (substitute* "git-sh-setup.sh"
                (("\\$\\(uname -s)")
                 (if #$(target-mingw?)
                     "MINGW"
                     "GNU")))           ;matched against '*'

              ;; git-submodule sources 'git-sh-setup.sh', but not before
              ;; invoking the basename and sed commands... patch them to their
              ;; absolute location.
              (substitute* "git-submodule.sh"
                (("\\$\\(basename")
                 (string-append "$(" (search-input-file inputs "bin/basename")))
                (("sed -e")
                 (string-append (search-input-file inputs "bin/sed") " -e")))))
          (add-after 'configure 'patch-makefiles
            (lambda _
              (substitute* "Makefile"
                (("/usr/bin/perl") (which "perl")))))
          (add-after 'configure 'add-PM.stamp
            (lambda _
              ;; Add the "PM.stamp" to avoid "no rule to make target".
              (call-with-output-file "perl/PM.stamp" (const #t))))
          (add-before 'check 'patch-tests
            (lambda _
              (let ((store-directory (%store-directory)))
                ;; These files contain some funny bytes that Guile is unable
                ;; to decode for shebang patching. Just delete them.
                (for-each delete-file '("t/t4201-shortlog.sh"
                                        "t/t7813-grep-icase-iso.sh"))
                ;; Many tests contain inline shell scripts (hooks etc).
                (substitute* (find-files "t" "\\.sh$")
                  (("#!/bin/sh") (string-append "#!" (which "sh"))))
                ;; Un-do shebang patching here to prevent checksum mismatch.
                (substitute* '("t/t4034/perl/pre" "t/t4034/perl/post")
                  (("^#!.*/bin/perl") "#!/usr/bin/perl"))
                (substitute* "t/t5003-archive-zip.sh"
                  (("cp /bin/sh") (string-append "cp " (which "sh"))))
                (substitute* "t/t6030-bisect-porcelain.sh"
                  (("\"/bin/sh\"") (string-append "\"" (which "sh") "\"")))
                ;; FIXME: This test runs `git commit` with a bogus EDITOR
                ;; and empty commit message, but does not fail the way it's
                ;; expected to. The test passes when invoked interactively.
                (substitute* "t/t7508-status.sh"
                  (("\tcommit_template_commented") "\ttrue"))
                ;; More checksum mismatches due to odd shebangs.
                (substitute* "t/t9100-git-svn-basic.sh"
                  (((string-append "\"#!" store-directory ".*/bin/sh"))
                   "\"#!/bin/sh") )
                (substitute* "t/t9300-fast-import.sh"
                  (((string-append "\t#!" store-directory ".*/bin/sh"))
                   "\t#!/bin/sh")
                  (((string-append "'#!" store-directory ".*/bin/sh"))
                   "'#!/bin/sh"))
                ;; FIXME: Some hooks fail with "basename: command not found".
                ;; See 't/trash directory.t9164.../svn-hook.log'.
                (delete-file "t/t9164-git-svn-dcommit-concurrent.sh")

                ;; XXX: These tests fail intermittently for unknown reasons:
                ;; <https://bugs.gnu.org/29546>.
                (for-each delete-file
                          '("t/t9128-git-svn-cmd-branch.sh"
                            "t/t9167-git-svn-cmd-branch-subproject.sh"
                            "t/t9141-git-svn-multiple-branches.sh")))))
          (add-after 'install 'install-shell-completion
            (lambda _
              (let ((bash (string-append #$output "/etc/bash_completion.d"))
                    (zsh  (string-append #$output "/share/zsh/site-functions")))
                ;; TODO: Install the tcsh completions in the right place.
                (for-each mkdir-p (list bash zsh))
                (copy-file "contrib/completion/git-completion.bash"
                           (string-append bash "/git"))
                (copy-file "contrib/completion/git-prompt.sh"
                           (string-append #$output "/bin/git-prompt"))
                (copy-file "contrib/completion/git-completion.zsh"
                           (string-append zsh "/_git")))))
          (add-after 'install 'remove-unusable-perl-commands
            (lambda _
              (let ((bin     (string-append #$output "/bin"))
                    (libexec (string-append #$output "/libexec")))
                (for-each (lambda (file)
                            (delete-file (string-append libexec
                                                        "/git-core/" file)))
                          '("git-svn" "git-cvsimport" "git-archimport"
                            "git-cvsserver" "git-request-pull"

                            ;; git-add--interactive was removed in Git 2.40 but
                            ;; this phase is inherited by older versions.
                            #$@(if (version>=? (package-version this-package)
                                               "2.40.1")
                                   #~()
                                   #~("git-add--interactive"))

                            "git-cvsexportcommit"
                            "git-instaweb" "git-send-email"))
                (delete-file (string-append bin "/git-cvsserver"))

                ;; These templates typically depend on Perl.  Remove them.
                (delete-file-recursively
                 (string-append #$output "/share/git-core/templates/hooks"))

                ;; Gitweb depends on Perl as well.
                (delete-file-recursively
                 (string-append #$output "/share/gitweb")))))
          (add-after 'install 'restore-sample-hooks-shebang
            (lambda _
              (let* ((dir (string-append #$output
                                         "/share/git-core/templates/hooks")))
                (for-each (lambda (file)
                            (format #t "restoring shebang on `~a'~%" file)
                            (substitute* file
                              (("^#!.*/bin/sh") "#!/bin/sh")))
                          (find-files dir ".*"))))))))
    (native-inputs
     ;; Add bash-minimal explicitly to ensure it comes before bash-for-tests,
     ;; see <https://bugs.gnu.org/39513>.
     (list bash-minimal
           bash
           gettext-minimal
           perl))
    (inputs
     (list coreutils-minimal
           curl                         ;for HTTP(S) access
           expat                        ;for 'git push' over HTTP(S)
           openssl
           perl
           sed
           zlib))
    (native-search-paths
     ;; For HTTPS access, Git needs a single-file certificate bundle, specified
     ;; with $GIT_SSL_CAINFO.
     (list (search-path-specification
            (variable "GIT_SSL_CAINFO")
            (file-type 'regular)
            (separator #f)              ;single entry
            (files '("etc/ssl/certs/ca-certificates.crt")))
           (search-path-specification
            (variable "GIT_EXEC_PATH")
            (separator #f)              ;single entry
            (files '("libexec/git-core")))))
    (synopsis "Distributed version control system")
    (description
     "Git is a free distributed version control system designed to handle
everything from small to very large projects with speed and efficiency.")
    ;; XXX: Ignore this CVE to work around a name clash with the unrelated
    ;; "cpe:2.3:a:jenkins:git" package.  The proper fix is for (guix cve) to
    ;; account for "vendor names".
    (properties '((lint-hidden-cve . ("CVE-2018-1000182"
                                      "CVE-2018-1000110"
                                      "CVE-2019-1003010"
                                      "CVE-2020-2136"
                                      "CVE-2021-21684"
                                      "CVE-2022-30947"
                                      "CVE-2022-30948"
                                      "CVE-2022-30949"
                                      "CVE-2022-36882"
                                      "CVE-2022-36883"
                                      "CVE-2022-36884"))))
    (license license:gpl2)
    (home-page "https://git-scm.com/")))

(define-public git
  (package/inherit git-minimal
    (name "git")
    (outputs '("out"                    ;the core
               "send-email"             ;for git-send-email
               "svn"                    ;git-svn
               "credential-netrc"       ;git-credential-netrc
               "credential-libsecret"   ;git-credential-libsecret
               "subtree"                ;git-subtree
               "gui"))                  ;gitk, git gui
    (arguments
     (substitute-keyword-arguments (package-arguments git-minimal)
       ((#:disallowed-references disallowed-refs ''())
        (delete perl disallowed-refs))
       ((#:make-flags flags #~'())
        #~(cons "USE_LIBPCRE2=yes" #$flags))
       ((#:configure-flags flags #~'())
        ;; The explicit --with-tcltk forces the build system to hardcode the
        ;; absolute file name to 'wish'.
        #~(cons (string-append "--with-tcltk="
                               (search-input-file %build-inputs
                                                  "bin/wish8.6"))
                #$flags))
       ((#:phases phases '%standard-phases)
        #~(modify-phases #$phases
            (delete 'remove-unusable-perl-commands)
            (replace 'patch-makefiles
              (lambda _
                (substitute* "Makefile"
                  (("/usr/bin/perl") (which "perl"))
                  (("/usr/bin/python") (which "python3")))))
            (add-after 'build 'build-subtree
              (lambda* (#:key native-inputs inputs #:allow-other-keys)
                (with-directory-excursion "contrib/subtree"
                  (invoke "make")
                  (invoke "make" "install")
                  (invoke "make" "install-doc")
                  (substitute* "git-subtree"
                    (("/bin/sh") (which "sh"))))))
            (add-after 'install 'install-info-manual
              (lambda* (#:key parallel-build? #:allow-other-keys)
                (define job-count (if parallel-build?
                                      (number->string (parallel-job-count))
                                      "1"))
                (invoke "make" "-C" "Documentation" "install-info"
                        "-j" job-count
                        ;; The Makefile refer to 'docbook2x-texi', but our
                        ;; binary is named 'docbook2texi&a