[PATCH] Add gitile and gitile service

DoneSubmitted by Julien Lepiller.
Details
3 participants
  • Julien Lepiller
  • Ludovic Courtès
  • Maxime Devos
Owner
unassigned
Severity
normal
J
J
Julien Lepiller wrote on 5 Aug 03:51 +0200
(address . guix-patches@gnu.org)
20210805035159.3959e01e@tachikoma.lepiller.eu
Hi guix!
Attached is a small patch series that adds gitile and the associatedservice type. Gitile is a small git forge project I have, and some ofyou expressed their interest, so here it is :)
From 38773e575b313caedfc788d4e28fd219265b4254 Mon Sep 17 00:00:00 2001From: Julien Lepiller <julien@lepiller.eu>Date: Thu, 5 Aug 2021 02:57:32 +0200Subject: [PATCH 1/2] gnu: Add gitile.
* gnu/packages/version-control.scm (gitile): New variable.--- gnu/packages/version-control.scm | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
Toggle diff (143 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex ac61b97f59..29dc86be8c 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -39,6 +39,7 @@ ;;; 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> ;;; ;;; This file is part of GNU Guix. ;;;@@ -93,6 +94,7 @@ #:use-module (gnu packages golang) #: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 linux) #:use-module (gnu packages mail)@@ -114,6 +116,7 @@ #:use-module (gnu packages readline) #:use-module (gnu packages rsync) #:use-module (gnu packages sqlite)+ #:use-module (gnu packages texinfo) #:use-module (gnu packages admin) #:use-module (gnu packages xml) #:use-module (gnu packages emacs)@@ -1517,6 +1520,112 @@ also walk each side of a merge and test those changes individually.") control to Git repositories.") (license license:gpl2))) +;; gitile requires a more recent version than the latest release.+(define guile-syntax-highlight-for-gitile+ (let ((commit "51727cbb7fc05ef743aab2d7b16314ea1ed790e4")+ (revision "0"))+ (package+ (inherit guile-syntax-highlight)+ (version (git-version "0.1" revision commit))+ (source (origin+ (method git-fetch)+ (uri (git-reference+ (url "https://git.dthompson.us/guile-syntax-highlight.git")+ (commit commit)))+ (file-name (git-file-name "guile-syntax-highlight" version))+ (sha256+ (base32+ "1cvacy4y5qxajygb1qg8hvhjdf2xnnwnm5j918cabsi8wfwchig7"))))+ (native-inputs+ `(("autoconf" ,autoconf)+ ("automake" ,automake)+ ("texinfo" ,texinfo)+ ,@(package-native-inputs guile-syntax-highlight))))))++(define-public gitile+ (package+ (name "gitile")+ (version "0.1")+ (source+ (origin+ (method git-fetch)+ (uri (git-reference+ (url "https://git.lepiller.eu/git/gitile")+ (commit version)))+ (file-name (git-file-name name version))+ (sha256+ (base32 "1ciwvqlc0nnzcxx3wjdsrm8i1h9965clv56nzcw7yyhml8ds42dk"))))+ (build-system gnu-build-system)+ (arguments+ `(#:modules ((guix build utils)+ (guix build gnu-build-system)+ (ice-9 rdelim)+ (ice-9 popen))+ #:make-flags (list "GUILE_AUTO_COMPILE=0")+ #:phases+ (modify-phases %standard-phases+ (add-after 'install 'install-assets+ (lambda* (#:key outputs #:allow-other-keys)+ (let ((assets (string-append (assoc-ref outputs "out")+ "/share/gitile/assets")))+ (mkdir-p assets)+ (copy-recursively "assets" assets))))+ (add-after 'install 'install-bin+ (lambda* (#:key outputs #:allow-other-keys)+ (install-file "scripts/gitile"+ (string-append (assoc-ref outputs "out")+ "/bin"))))+ (add-after 'install-bin 'wrap-program+ (lambda* (#:key inputs outputs #:allow-other-keys)+ ;; Wrap the 'cuirass' command to refer to the right modules.+ (let* ((out (assoc-ref outputs "out"))+ (commonmark (assoc-ref inputs "guile-commonmark"))+ (git (assoc-ref inputs "guile-git"))+ (bytes (assoc-ref inputs "guile-bytestructures"))+ (fibers (assoc-ref inputs "guile-fibers"))+ (gcrypt (assoc-ref inputs "guile-gcrypt"))+ (syntax-highlight (assoc-ref inputs "guile-syntax-highlight"))+ (deps (list out commonmark git bytes fibers gcrypt+ syntax-highlight))+ (guile (assoc-ref %build-inputs "guile"))+ (effective (read-line+ (open-pipe* OPEN_READ+ (string-append guile "/bin/guile")+ "-c" "(display (effective-version))")))+ (mods (string-drop-right ;drop trailing colon+ (string-join deps+ (string-append "/share/guile/site/"+ effective ":")+ 'suffix)+ 1))+ (objs (string-drop-right+ (string-join deps+ (string-append "/lib/guile/" effective+ "/site-ccache:")+ 'suffix)+ 1)))+ (wrap-program (string-append out "/bin/gitile")+ `("GUILE_LOAD_PATH" ":" prefix (,mods))+ `("GUILE_LOAD_COMPILED_PATH" ":" prefix (,objs)))))))))+ (native-inputs+ `(("autoconf" ,autoconf)+ ("automake" ,automake)+ ("guile" ,guile-3.0)+ ("pkg-config" ,pkg-config)))+ (inputs+ `(("guile" ,guile-3.0)+ ("guile-commonmark" ,guile-commonmark)+ ("guile-fibers" ,guile-fibers)+ ("guile-gcrypt" ,guile-gcrypt)+ ("guile-git" ,guile-git)+ ("guile-syntax-highlight" ,guile-syntax-highlight)+ ("gnutls" ,gnutls)))+ (home-page "https://git.lepiller.eu/gitile")+ (synopsis "Simple git forge written in Guile")+ (description "Gitile is a git forge written in Guile that lets you+visualize your public Git repositories on a web interface.")+ (license license:agpl3+)))+ (define-public pre-commit (package (name "pre-commit")-- 2.32.0
From 3cd7ef0ae922d77ff5d29c831dbdf8d350210fb7 Mon Sep 17 00:00:00 2001From: Julien Lepiller <julien@lepiller.eu>Date: Thu, 5 Aug 2021 03:46:40 +0200Subject: [PATCH 2/2] gnu: version-control: Add gitile service.
* gnu/services/version-control.scm (gitile-service-type): New variable.* doc/guix.texi (Version Control Services): Document it.--- doc/guix.texi | 79 ++++++++++++++++++++ gnu/services/version-control.scm | 124 ++++++++++++++++++++++++++++++- 2 files changed, 202 insertions(+), 1 deletion(-)
Toggle diff (238 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex a826171f34..e5e989c223 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -31440,6 +31440,85 @@ This setting controls the commands and features to enable within Gitolite. @end deftp +@subsubheading Gitile Service++@cindex Gitile service+@cindex Git, forge+@uref{https://git.lepiller.eu/gitile, Gitile} is a Git forge for viewing+public git repository contents from a web browser.++Gitile works best in collaboration with Gitolite, and will serve the public+repositories from Gitolite by default.++The following example will configure Gitile to serve repositories from a+custom location, with some default messages for the home page and the+footers.++@lisp+(service gitile-service-type+ (gitile-configuration+ (repositories "/srv/git")+ (base-git-url "https://myweb.site/git")+ (index-title "My git repositories")+ (intro '((p "This is all my public work!")))+ (footer '((p "This is the end")))+ (nginx-server-block+ (nginx-server-configuration+ (ssl-certificate+ "/etc/letsencrypt/live/myweb.site/fullchain.pem")+ (ssl-certificate-key+ "/etc/letsencrypt/live/myweb.site/privkey.pem")+ (listen '("443 ssl http2" "[::]:443 ssl http2"))+ (locations+ (list+ (git-http-nginx-location-configuration+ (git-http-configuration+ (uri-path "/git/")+ (git-root "/var/lib/gitolite/repositories")))))))))+@end lisp++@deftp {Data Type} gitile-configuration+Data type representing the configuration for @code{gitile-service-type}.++@table @asis+@item @code{package} (default: @var{gitile})+Gitile package to use.++@item @code{host} (default: @code{"localhost"})+The host on which gitile is listening.++@item @code{port} (default: @code{8080})+The port on which gitile is listening.++@item @code{database} (default: @code{"/var/lib/gitile/gitile-db.sql"})+The location of the database.++@item @code{repositories} (default: @code{"/var/lib/gitolite/repositories"})+The location of the repositories. Note that only public repositories will+be shown by Gitile. To make a repository public, add an empty+@file{git-daemon-export-ok} file at the root of that repository.++@item @code{base-git-url}+The base git url that will be used to show clone commands.++@item @code{index-title} (default: @code{"Index"})+The page title for the index page that lists all the available repositories.++@item @code{intro} (default: @code{'()})+The intro content, as a list of sxml expressions. This is shown above the list+of repositories, on the index page.++@item @code{footer} (default: @code{'()})+The footer content, as a list of sxml expressions. This is shown on every+page served by Gitile.++@item @code{nginx-server-block}+An nginx server block that will be extended and used as a reverse proxy by+Gitile to serve its pages, and as a normal web server to serve its assets.+@end table+@end deftp++ @node Game Services @subsection Game Services diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 8cb5633165..f28206b239 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -4,6 +4,7 @@ ;;; 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. ;;;@@ -58,7 +59,22 @@ gitolite-rc-file-roles gitolite-rc-file-enable - gitolite-service-type))+ gitolite-service-type++ <gitile-configuration>+ 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-server-block++ gitile-service-type)) ;;; Commentary: ;;;@@ -380,3 +396,109 @@ access to exported repositories under @file{/srv/git}." 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 "localhost"))+ (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-server-block nginx-configuration-nginx-server-block))++(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-server-block)+ (list (nginx-server-configuration+ (inherit nginx-server-block)+ (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-server-block))))))))++(define gitile-shepherd-service+ (match-lambda+ (($ <gitile-configuration> package host port database repositories+ base-git-url index-title intro footer nginx-server-block)+ (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-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)+ (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)))))-- 2.32.0
M
M
Maxime Devos wrote on 5 Aug 16:58 +0200
ce8fa1553cfe2cde7a10f4f3828ef5f711b44aeb.camel@telenet.be
Julien Lepiller schreef op do 05-08-2021 om 03:51 [+0200]:
Toggle quote (4 lines)> + (add-after 'install-bin 'wrap-program> + (lambda* (#:key inputs outputs #:allow-other-keys)> + ;; Wrap the 'cuirass' command to refer to the right modules.
'gitile' isn't "cuirass".
Toggle quote (11 lines)> + (let* ((out (assoc-ref outputs "out"))> + (commonmark (assoc-ref inputs "guile-commonmark"))> + (git (assoc-ref inputs "guile-git"))> + (bytes (assoc-ref inputs "guile-bytestructures"))> + (fibers (assoc-ref inputs "guile-fibers"))> + (gcrypt (assoc-ref inputs "guile-gcrypt"))> + (syntax-highlight (assoc-ref inputs "guile-syntax-highlight"))> + (deps (list out commonmark git bytes fibers gcrypt> + syntax-highlight))> + (guile (assoc-ref %build-inputs "guile"))
I wold use 'inputs' instead of '%build-inputs' here.
Greetings,Maxime.
-----BEGIN PGP SIGNATURE-----
iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYQv8pRccbWF4aW1lZGV2b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7kCFAPwOVVkguOlHZ2g3xlfP3KcEdChImeaDye4S0xG2vnlMJQEAqPcafweVmkpSjsBkRkWC8IiEFFvcdxLd0OrJYOqtIQ8==nML3-----END PGP SIGNATURE-----

L
L
Ludovic Courtès wrote on 10 Aug 12:38 +0200
Re: bug#49886: [PATCH] Add gitile and gitile service
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 49886@debbugs.gnu.org)
87lf59shyi.fsf@gnu.org
Hello!
Julien Lepiller <julien@lepiller.eu> skribis:
Toggle quote (4 lines)> Attached is a small patch series that adds gitile and the associated> service type. Gitile is a small git forge project I have, and some of> you expressed their interest, so here it is :)
Woohoo, nice! To complement Maxime’s comments:
Toggle quote (7 lines)> From 38773e575b313caedfc788d4e28fd219265b4254 Mon Sep 17 00:00:00 2001> From: Julien Lepiller <julien@lepiller.eu>> Date: Thu, 5 Aug 2021 02:57:32 +0200> Subject: [PATCH 1/2] gnu: Add gitile.>> * gnu/packages/version-control.scm (gitile): New variable.
[...]
Toggle quote (3 lines)> + (synopsis "Simple git forge written in Guile")> + (description "Gitile is a git forge written in Guile that lets you
s/git/Git/
Toggle quote (8 lines)> From 3cd7ef0ae922d77ff5d29c831dbdf8d350210fb7 Mon Sep 17 00:00:00 2001> From: Julien Lepiller <julien@lepiller.eu>> Date: Thu, 5 Aug 2021 03:46:40 +0200> Subject: [PATCH 2/2] gnu: version-control: Add gitile service.>> * gnu/services/version-control.scm (gitile-service-type): New variable.> * doc/guix.texi (Version Control Services): Document it.
[...]
Toggle quote (7 lines)> +@subsubheading Gitile Service> +> +@cindex Gitile service> +@cindex Git, forge> +@uref{https://git.lepiller.eu/gitile, Gitile} is a Git forge for viewing> +public git repository contents from a web browser.
s/git/Git/
Toggle quote (30 lines)> +Gitile works best in collaboration with Gitolite, and will serve the public> +repositories from Gitolite by default.> +> +The following example will configure Gitile to serve repositories from a> +custom location, with some default messages for the home page and the> +footers.> +> +@lisp> +(service gitile-service-type> + (gitile-configuration> + (repositories "/srv/git")> + (base-git-url "https://myweb.site/git")> + (index-title "My git repositories")> + (intro '((p "This is all my public work!")))> + (footer '((p "This is the end")))> + (nginx-server-block> + (nginx-server-configuration> + (ssl-certificate> + "/etc/letsencrypt/live/myweb.site/fullchain.pem")> + (ssl-certificate-key> + "/etc/letsencrypt/live/myweb.site/privkey.pem")> + (listen '("443 ssl http2" "[::]:443 ssl http2"))> + (locations> + (list> + (git-http-nginx-location-configuration> + (git-http-configuration> + (uri-path "/git/")> + (git-root "/var/lib/gitolite/repositories")))))))))> +@end lisp
Could you write a couple of lines about the nginx server block? It’squite intimidating and it’s not introduced in the paragraph above.

[...]
Toggle quote (2 lines)> + <gitile-configuration>
No need to export the record type descriptor.
Toggle quote (8 lines)> + (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))
As a followup it’d be interesting to see if it can run in‘make-forkexec-constructor/container’.
Toggle quote (11 lines)> +(define gitile-service-type> + (service-type> + (name 'gitile)> + (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)))))
Please add a ‘description’ field.
Would be great if you could add a system test too.
Otherwise LGTM, it’s exciting to get more Guilish tooling! :-)
Ludo’.
J
J
Julien Lepiller wrote on 25 Aug 23:31 +0200
Re: bug#49886: [PATCH v2] Add gitile and gitile service
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 49886@debbugs.gnu.org)
20210825233136.450d778b@tachikoma.lepiller.eu
Thanks for the feedback!
attached is a v2 of the series. I added a small change to gitolite thatallows changing UNSAFE_PATT (a regex that matches configuration valuesthat contain unsafe characters). I wanted to link to it and to thenginx configuration sections in the manual, but I don't know how tocreate that link? I see the @subsubheading NGINX for instance, but Ican't @ref{NGINX}.
I had to update gitile for the tests to pass and had a few falsestarts, but now the tests pass and gitile is working even better thanbefore :)
From d43a77241defdea7848ab4596b427c33675f050e Mon Sep 17 00:00:00 2001From: Julien Lepiller <julien@lepiller.eu>Date: Thu, 5 Aug 2021 02:57:32 +0200Subject: [PATCH 1/3] gnu: Add gitile.
* gnu/packages/version-control.scm (gitile): New variable.--- gnu/packages/version-control.scm | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
Toggle diff (143 lines)diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scmindex ac61b97f59..c378ff5bca 100644--- a/gnu/packages/version-control.scm+++ b/gnu/packages/version-control.scm@@ -39,6 +39,7 @@ ;;; 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> ;;; ;;; This file is part of GNU Guix. ;;;@@ -93,6 +94,7 @@ #:use-module (gnu packages golang) #: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 linux) #:use-module (gnu packages mail)@@ -114,6 +116,7 @@ #:use-module (gnu packages readline) #:use-module (gnu packages rsync) #:use-module (gnu packages sqlite)+ #:use-module (gnu packages texinfo) #:use-module (gnu packages admin) #:use-module (gnu packages xml) #:use-module (gnu packages emacs)@@ -1517,6 +1520,112 @@ also walk each side of a merge and test those changes individually.") control to Git repositories.") (license license:gpl2))) +;; gitile requires a more recent version than the latest release.+(define guile-syntax-highlight-for-gitile+ (let ((commit "897fa5156ff41588e0d281eb00e4e94de63ccd8a")+ (revision "0"))+ (package+ (inherit guile-syntax-highlight)+ (version (git-version "0.1" revision commit))+ (source (origin+ (method git-fetch)+ (uri (git-reference+ (url "https://git.dthompson.us/guile-syntax-highlight.git")+ (commit commit)))+ (file-name (git-file-name "guile-syntax-highlight" version))+ (sha256+ (base32+ "18zlg4mkgd3swgv2ggfz91ivnnzc0zhvc9ybgrxg1y762va9hyvj"))))+ (native-inputs+ `(("autoconf" ,autoconf)+ ("automake" ,automake)+ ("texinfo" ,texinfo)+ ,@(package-native-inputs guile-syntax-highlight))))))++(define-public gitile+ (package+ (name "gitile")+ (version "0.1.3")+ (source+ (origin+ (method git-fetch)+ (uri (git-reference+ (url "https://git.lepiller.eu/git/gitile")+ (commit version)))+ (file-name (git-file-name name version))+ (sha256+ (base32 "1fnmgrrsdc24mvicj2gkv3vasag7h5x27xc12w55i0id9vw7k9sw"))))+ (build-system gnu-build-system)+ (arguments+ `(#:modules ((guix build utils)+ (guix build gnu-build-system)+ (ice-9 rdelim)+ (ice-9 popen))+ #:make-flags (list "GUILE_AUTO_COMPILE=0")+ #:phases+ (modify-phases %standard-phases+ (add-after 'install 'install-assets+ (lambda* (#:key outputs #:allow-other-keys)+ (let ((assets (string-append (assoc-ref outputs "out")+ "/share/gitile/assets")))+ (mkdir-p assets)+ (copy-recursively "assets" assets))))+ (add-after 'install 'install-bin+ (lambda* (#:key outputs #:allow-other-keys)+ (install-file "scripts/gitile"+ (string-append (assoc-ref outputs "out")+ "/bin"))))+ (add-after 'install-bin 'wrap-program+ (lambda* (#:key inputs outputs #:allow-other-keys)+ ;; Wrap the 'cuirass' command to refer to the right modules.+ (let* ((out (assoc-ref outputs "out"))+ (commonmark (assoc-ref inputs "guile-commonmark"))+ (git (assoc-ref inputs "guile-git"))+ (bytes (assoc-ref inputs "guile-bytestructures"))+ (fibers (assoc-ref inputs "guile-fibers"))+ (gcrypt (assoc-ref inputs "guile-gcrypt"))+ (syntax-highlight (assoc-ref inputs "guile-syntax-highlight"))+ (deps (list out commonmark git bytes fibers gcrypt+ syntax-highlight))+ (guile (assoc-ref inputs "guile"))+ (effective (read-line+ (open-pipe* OPEN_READ+ (string-append guile "/bin/guile")+ "-c" "(display (effective-version))")))+ (mods (string-drop-right ;drop trailing colon+ (string-join deps+ (string-append "/share/guile/site/"+ effective ":")+ 'suffix)+ 1))+ (objs (string-drop-right+ (string-join deps+ (string-append "/lib/guile/" effective+ "/site-ccache:")+ 'suffix)+ 1)))+ (wrap-program (string-append out "/bin/gitile")+ `("GUILE_LOAD_PATH" ":" prefix (,mods))+ `("GUILE_LOAD_COMPILED_PATH" ":" prefix (,objs)))))))))+ (native-inputs+ `(("autoconf" ,autoconf)+ ("automake" ,automake)+ ("guile" ,guile-3.0)+ ("pkg-config" ,pkg-config)))+ (inputs+ `(("guile" ,guile-3.0)+ ("guile-commonmark" ,guile-commonmark)+ ("guile-fibers" ,guile-fibers)+ ("guile-gcrypt" ,guile-gcrypt)+ ("guile-git" ,guile-git)+ ("guile-syntax-highlight" ,guile-syntax-highlight-for-gitile)+ ("gnutls" ,gnutls)))+ (home-page "https://git.lepiller.eu/gitile")+ (synopsis "Simple Git forge written in Guile")+ (description "Gitile is a Git forge written in Guile that lets you+visualize your public Git repositories on a web interface.")+ (license license:agpl3+)))+ (define-public pre-commit (package (name "pre-commit")-- 2.32.0
From 2652e5515c84505c63072309f3b3e7837649cdb9 Mon Sep 17 00:00:00 2001From: Julien Lepiller <julien@lepiller.eu>Date: Wed, 25 Aug 2021 03:00:44 +0200Subject: [PATCH 2/3] gnu: gitolite: Add unsafe-patt configuration option.
* gnu/services/version-control.scm (gitolite-rc-file): Add unsafe-pattfield.(gitolite-rc-file-compiler): Write it.* doc/guix.texi (Version Control Services): Document it.--- doc/guix.texi | 9 +++++++++ gnu/services/version-control.scm | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-)
Toggle diff (62 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex a826171f34..29a2fffdfd 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -31426,6 +31426,15 @@ A value like @code{#o0027} will give read access to the group used by Gitolite (by default: @code{git}). This is necessary when using Gitolite with software like cgit or gitweb. +@item @code{unsafe-patt} (default: @code{#f})+An optional pattern for catching unsafe configurations in the configuration+file. See+@uref{https://gitolite.com/gitolite/git-config.html#compensating-for-unsafe_patt,+Gitolite's documentation} for more information.++When the value is not @code{#f}, it should be a string containing a Perl+regular expression, such as @samp{"[`~#\$\&()|;<>]"}.+ @item @code{git-config-keys} (default: @code{""}) Gitolite allows you to set git config values using the @samp{config} keyword. This setting allows control over the config keys to accept.diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex 8cb5633165..d0ac2e4a18 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -54,6 +54,7 @@ <gitolite-rc-file> gitolite-rc-file gitolite-rc-file-umask+ gitolite-rc-file-unsafe-patt gitolite-rc-file-git-config-keys gitolite-rc-file-roles gitolite-rc-file-enable@@ -226,6 +227,8 @@ access to exported repositories under @file{/srv/git}." gitolite-rc-file? (umask gitolite-rc-file-umask (default #o0077))+ (unsafe-patt gitolite-rc-file-unsafe-patt+ (default #f)) (git-config-keys gitolite-rc-file-git-config-keys (default "")) (roles gitolite-rc-file-roles@@ -245,7 +248,7 @@ access to exported repositories under @file{/srv/git}." (define-gexp-compiler (gitolite-rc-file-compiler (file <gitolite-rc-file>) system target) (match file- (($ <gitolite-rc-file> umask git-config-keys roles enable)+ (($ <gitolite-rc-file> umask unsafe-patt git-config-keys roles enable) (apply text-file* "gitolite.rc" `("%RC = (\n" " UMASK => " ,(format #f "~4,'0o" umask) ",\n"@@ -264,6 +267,9 @@ access to exported repositories under @file{/srv/git}." " ],\n" ");\n" "\n"+ ,(if unsafe-patt+ (string-append "$UNSAFE_PATT = qr(" unsafe-patt ");")+ "") "1;\n"))))) (define-record-type* <gitolite-configuration>-- 2.32.0
From a80c856fce646eee7257239e4c05e67ac292b5fc Mon Sep 17 00:00:00 2001From: Julien Lepiller <julien@lepiller.eu>Date: Thu, 5 Aug 2021 03:46:40 +0200Subject: [PATCH 3/3] gnu: version-control: Add gitile service.
* gnu/services/version-control.scm (gitile-service-type): New variable.* doc/guix.texi (Version Control Services): Document it.* gnu/tests/version-control.scm (%test-gitile): New variable.--- doc/guix.texi | 128 ++++++++++++++++++++++++++++ gnu/services/version-control.scm | 128 +++++++++++++++++++++++++++- gnu/tests/version-control.scm | 138 ++++++++++++++++++++++++++++++- 3 files changed, 391 insertions(+), 3 deletions(-)
Toggle diff (451 lines)diff --git a/doc/guix.texi b/doc/guix.texiindex 29a2fffdfd..94d9301238 100644--- a/doc/guix.texi+++ b/doc/guix.texi@@ -31449,6 +31449,134 @@ This setting controls the commands and features to enable within Gitolite. @end deftp +@subsubheading Gitile Service++@cindex Gitile service+@cindex Git, forge+@uref{https://git.lepiller.eu/gitile, Gitile} is a Git forge for viewing+public git repository contents from a web browser.++Gitile works best in collaboration with Gitolite, and will serve the public+repositories from Gitolite by default. The service should listen only on+a local port, and a webserver should be configured to serve static resources.+The gitile service provides an easy way to extend the Nginx service.++The following example will configure Gitile to serve repositories from a+custom location, with some default messages for the home page and the+footers.++@lisp+(service gitile-service-type+ (gitile-configuration+ (repositories "/srv/git")+ (base-git-url "https://myweb.site/git")+ (index-title "My git repositories")+ (intro '((p "This is all my public work!")))+ (footer '((p "This is the end")))+ (nginx-server-block+ (nginx-server-configuration+ (ssl-certificate+ "/etc/letsencrypt/live/myweb.site/fullchain.pem")+ (ssl-certificate-key+ "/etc/letsencrypt/live/myweb.site/privkey.pem")+ (listen '("443 ssl http2" "[::]:443 ssl http2"))+ (locations+ (list+ ;; Allow for https anonymous fetch on /git/ urls.+ (git-http-nginx-location-configuration+ (git-http-configuration+ (uri-path "/git/")+ (git-root "/var/lib/gitolite/repositories")))))))))+@end lisp++In addition to the configuration record, you should configure your git+repositories to contain some optional information. First, your public+repositories need to contain the @file{.git-daemon-export-ok} magic file+that allows Git to export the repository. Gitile uses the presence of this+file to detect public repositories it should make accessible. To do so with+Gitolite for instance, modify your @file{conf/gitolite.conf} to include+this in the repositories you want to make public:++@example+repo foo+ R = daemon+@end example++In addition, Gitile can read the repository configuration to display more+infomation on the repository. Gitile uses the gitweb namespace for its+configuration. As an example, you can use the following in your+@file{conf/gitolite.conf}:++@example+repo foo+ R = daemon+ desc = A long description, optionally with <i>HTML</i>, shown on the index page+ config gitweb.name = The Foo Project+ config gitweb.synopsis = A short description, shown on the main page of the project+@end example++Do not forget to commit and push these changes once you are satisfied. You+may need to change your gitolite configuration to allow the previous+configuration options to be set. One way to do that is to add the+following service definition:++@lisp+(service gitolite-service-type+ (gitolite-configuration+ (admin-pubkey (local-file "key.pub"))+ (rc-file+ (gitolite-rc-file+ (umask #o0027)+ (git-config-keys ".*")+ (unsafe-patt "^$")))))+@end lisp++@deftp {Data Type} gitile-configuration+Data type representing the configuration for @code{gitile-service-type}.++@table @asis+@item @code{package} (default: @var{gitile})+Gitile package to use.++@item @code{host} (default: @code{"localhost"})+The host on which gitile is listening.++@item @code{port} (default: @code{8080})+The port on which gitile is listening.++@item @code{database} (default: @code{"/var/lib/gitile/gitile-db.sql"})+The location of the database.++@item @code{repositories} (default: @code{"/var/lib/gitolite/repositories"})+The location of the repositories. Note that only public repositories will+be shown by Gitile. To make a repository public, add an empty+@file{git-daemon-export-ok} file at the root of that repository.++@item @code{base-git-url}+The base git url that will be used to show clone commands.++@item @code{index-title} (default: @code{"Index"})+The page title for the index page that lists all the available repositories.++@item @code{intro} (default: @code{'()})+The intro content, as a list of sxml expressions. This is shown above the list+of repositories, on the index page.++@item @code{footer} (default: @code{'()})+The footer content, as a list of sxml expressions. This is shown on every+page served by Gitile.++@item @code{nginx-server-block}+An nginx server block that will be extended and used as a reverse proxy by+Gitile to serve its pages, and as a normal web server to serve its assets.++You can use this block to add more custom URLs to your domain, such as a+@code{/git/} URL for anonymous clones, or serving any other files you would+like to serve.+@end table+@end deftp++ @node Game Services @subsection Game Services diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scmindex d0ac2e4a18..4cb648eb3e 100644--- a/gnu/services/version-control.scm+++ b/gnu/services/version-control.scm@@ -4,6 +4,7 @@ ;;; 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. ;;;@@ -59,7 +60,21 @@ gitolite-rc-file-roles gitolite-rc-file-enable - gitolite-service-type))+ 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: ;;;@@ -386,3 +401,114 @@ access to exported repositories under @file{/srv/git}." 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)))))diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scmindex d3cf19c913..a7cde1f163 100644--- a/gnu/tests/version-control.scm+++ b/gnu/tests/version-control.scm@@ -38,7 +38,8 @@ #:use-module (guix modules) #:export (%test-cgit %test-git-http- %test-gitolite))+ %test-gitolite+ %test-gitile)) (define README-contents "Hello! This is what goes inside the 'README' file.")@@ -63,7 +64,10 @@ (invoke git "commit" "-m" "That's a commit.")) (mkdir-p "/srv/git")- (rename-file "/tmp/test-repo/.git" "/srv/git/test")))))+ (rename-file "/tmp/test-repo/.git" "/srv/git/test")+ (with-output-to-file "/srv/git/test/git-daemon-export-ok"+ (lambda _+ (display ""))))))) (define %test-repository-service ;; Service that creates /srv/git/test.@@ -416,3 +420,133 @@ HTTP-PORT." (name "gitolite") (description "Clone the Gitolite admin repository.") (value (run-gitolite-test))))++;;;+;;; Gitile.+;;;++(define %gitile-configuration-nginx+ (nginx-server-configuration+ (root "/does/not/exists")+ (try-files (list "$uri" "=404"))+ (listen '("19418"))+ (ssl-certificate #f)+ (ssl-certificate-key #f)))++(define %gitile-os+ ;; Operating system under test.+ (simple-operating-system+ (service dhcp-client-service-type)+ (simple-service 'srv-git activation-service-type+ #~(mkdir-p "/srv/git"))+ (service gitile-service-type+ (gitile-configuration+ (base-git-url "http://localhost")+ (repositories "/srv/git")+ (nginx %gitile-configuration-nginx)))+ %test-repository-service))++(define* (run-gitile-test #:optional (http-port 19418))+ "Run tests in %GITOLITE-OS, which has nginx running and listening on+HTTP-PORT."+ (define os+ (marionette-operating-system+ %gitile-os+ #:imported-modules '((gnu services herd)+ (guix combinators))))++ (define vm+ (virtual-machine+ (operating-system os)+ (port-forwardings `((8081 . ,http-port)))))++ (define test+ (with-imported-modules '((gnu build marionette))+ #~(begin+ (use-modules (srfi srfi-11) (srfi srfi-64)+ (gnu build marionette)+ (web uri)+ (web client)+ (web response))++ (define marionette+ (make-marionette (list #$vm)))++ (mkdir #$output)+ (chdir #$output)++ (test-begin "gitile")++ ;; XXX: Shepherd reads the config file *before* binding its control+ ;; socket, so /var/run/shepherd/socket might not exist yet when the+ ;; 'marionette' service is started.+ (test-assert "shepherd socket ready"+ (marionette-eval+ `(begin+ (use-modules (gnu services herd))+ (let loop ((i 10))+ (cond ((file-exists? (%shepherd-socket-file))+ #t)+ ((> i 0)+ (sleep 1)+ (loop (- i 1)))+ (else+ 'failure))))+ marionette))++ ;; Wait for nginx to be up and running.+ (test-assert "nginx running"+ (marionette-eval+ '(begin+ (use-modules (gnu services herd))+ (start-service 'nginx))+ marionette))++ ;; Make sure the PID file is created.+ (test-assert "PID file"+ (marionette-eval+ '(file-exists? "/var/run/nginx/pid")+ marionette))++ ;; Make sure Git test repository is created.+ (test-assert "Git test repository"+ (marionette-eval+ '(file-exists? "/srv/git/test")+ marionette))++ (sleep 2)++ ;; Make sure we can access pages that correspond to our repository.+ (letrec-syntax ((test-url+ (syntax-rules ()+ ((_ path code)+ (test-equal (string-append "GET " path)+ code+ (let-values (((response body)+ (http-get (string-append+ "http://localhost:8081"+ path))))+ (response-code response))))+ ((_ path)+ (test-url path 200)))))+ (test-url "/")+ (test-url "/css/gitile.css")+ (test-url "/test")+ (test-url "/test/commits")+ (test-url "/test/tree" 404)+ (test-url "/test/tree/-")+ (test-url "/test/tree/-/README")+ (test-url "/test/does-not-exist" 404)+ (test-url "/test/tree/-/does-not-exist" 404)+ (test-url "/does-not-exist" 404))++ (test-end)+ (exit (= (test-runner-fail-count (test-runner-current)) 0)))))++ (gexp->derivation "gitile-test" test))++(define %test-gitile+ (system-test+ (name "gitile")+ (description "Connect to a running Gitile server.")+ (value (run-gitile-test))))-- 2.32.0
L
L
Ludovic Courtès wrote on 30 Aug 14:49 +0200
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 49886@debbugs.gnu.org)
87tuj7ayh7.fsf@gnu.org
Hi Julien!
Julien Lepiller <julien@lepiller.eu> skribis:
Toggle quote (7 lines)> attached is a v2 of the series. I added a small change to gitolite that> allows changing UNSAFE_PATT (a regex that matches configuration values> that contain unsafe characters). I wanted to link to it and to the> nginx configuration sections in the manual, but I don't know how to> create that link? I see the @subsubheading NGINX for instance, but I> can't @ref{NGINX}.
Right, you cannot cross-reference a heading; you’d need either a node oran anchor so you can cross-reference it.
Toggle quote (4 lines)> I had to update gitile for the tests to pass and had a few false> starts, but now the tests pass and gitile is working even better than> before :)
Yay! :-)
Toggle quote (7 lines)> From d43a77241defdea7848ab4596b427c33675f050e Mon Sep 17 00:00:00 2001> From: Julien Lepiller <julien@lepiller.eu>> Date: Thu, 5 Aug 2021 02:57:32 +0200> Subject: [PATCH 1/3] gnu: Add gitile.>> * gnu/packages/version-control.scm (gitile): New variable.
LGTM!
Toggle quote (10 lines)> From 2652e5515c84505c63072309f3b3e7837649cdb9 Mon Sep 17 00:00:00 2001> From: Julien Lepiller <julien@lepiller.eu>> Date: Wed, 25 Aug 2021 03:00:44 +0200> Subject: [PATCH 2/3] gnu: gitolite: Add unsafe-patt configuration option.>> * gnu/services/version-control.scm (gitolite-rc-file): Add unsafe-patt> field.> (gitolite-rc-file-compiler): Write it.> * doc/guix.texi (Version Control Services): Document it.
[...]
Toggle quote (8 lines)> --- a/doc/guix.texi> +++ b/doc/guix.texi> @@ -31426,6 +31426,15 @@ A value like @code{#o0027} will give read access to the group used by Gitolite> (by default: @code{git}). This is necessary when using Gitolite with software> like cgit or gitweb.> > +@item @code{unsafe-patt} (default: @code{#f})
I’d call this field ‘unsafe-pattern’ for clarity.
Toggle quote (2 lines)> +An optional pattern for catching unsafe configurations in the configuration
s/pattern/Perl regular expression/ ?
Toggle quote (7 lines)> +file. See> +@uref{https://gitolite.com/gitolite/git-config.html#compensating-for-unsafe_patt,> +Gitolite's documentation} for more information.> +> +When the value is not @code{#f}, it should be a string containing a Perl> +regular expression, such as @samp{"[`~#\$\&()|;<>]"}.
“such as @samp{…}, which catches XYZ.”
OK with changes along these lines!
Toggle quote (9 lines)> From a80c856fce646eee7257239e4c05e67ac292b5fc Mon Sep 17 00:00:00 2001> From: Julien Lepiller <julien@lepiller.eu>> Date: Thu, 5 Aug 2021 03:46:40 +0200> Subject: [PATCH 3/3] gnu: version-control: Add gitile service.>> * gnu/services/version-control.scm (gitile-service-type): New variable.> * doc/guix.texi (Version Control Services): Document it.> * gnu/tests/version-control.scm (%test-gitile): New variable.
LGTM, thank you!
Ludo’.
M
M
Maxime Devos wrote on 30 Aug 18:54 +0200
Re: [bug#49886] [PATCH v2] Add gitile and gitile service
(address . 49886@debbugs.gnu.org)
7f8054226ce4857aa98c847fb1f14c7ea4d8805d.camel@telenet.be
Julien Lepiller schreef op wo 25-08-2021 om 23:31 [+0200]:
Toggle quote (4 lines)> + (add-after 'install-bin 'wrap-program> + (lambda* (#:key inputs outputs #:allow-other-keys)> + ;; Wrap the 'cuirass' command to refer to the right modules.
I think you meant 'gitile' here.
Toggle quote (15 lines)> + (let* ((out (assoc-ref outputs "out"))> + (commonmark (assoc-ref inputs "guile-commonmark"))> + (git (assoc-ref inputs "guile-git"))> + (bytes (assoc-ref inputs "guile-bytestructures"))> + (fibers (assoc-ref inputs "guile-fibers"))> + (gcrypt (assoc-ref inputs "guile-gcrypt"))> + (syntax-highlight (assoc-ref inputs "guile-syntax-highlight"))> + (deps (list out commonmark git bytes fibers gcrypt> + syntax-highlight))> + (guile (assoc-ref inputs "guile"))> + (effective (read-line> + (open-pipe* OPEN_READ> + (string-append guile "/bin/guile")> + "-c" "(display (effective-version))")))
You can use "target-guile-effective-version" from (guix build guile-build-system)here.
Greetings,Maxime.
-----BEGIN PGP SIGNATURE-----
iI0EABYKADUWIQTB8z7iDFKP233XAR9J4+4iGRcl7gUCYS0NQBccbWF4aW1lZGV2b3NAdGVsZW5ldC5iZQAKCRBJ4+4iGRcl7jIIAQDPsIGMbETFeclYTCsbrMiZBkjbI8zcMHmKZK4WRT/oLAD/UNJX4bHH9LP7V6TQVZEmkt57G0oMseNox4hCTAUsFw8==wiVW-----END PGP SIGNATURE-----

J
J
Julien Lepiller wrote on 3 Sep 00:04 +0200
Re: bug#49886: [PATCH v2] Add gitile and gitile service
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 49886-done@debbugs.gnu.org)
20210903000454.421d34ff@tachikoma.lepiller.eu
Pushed, thanks!
Closed
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send email to 49886@debbugs.gnu.org