Subject: Re: [bug#29820] [PATCH] services: cgit: Add more configuration fields.

From: Oleg Pykhalov <[email-masked]>
Date: Thu, 28 Dec 2017 19:45:22 +0300

Hello Clément,

Thank you for review!

Clément Lassieur <[email-masked]> writes:

[...]

>> +(define (serialize-repository-cgit-configuration x)
>> +  (serialize-configuration x repository-cgit-configuration-fields))
>
> 'url' needs to be the first setting specified for each repo.  I think
> you could use something like this to make sure it is:
>
> (define (serialize-repository-cgit-configuration x)
>   (define (rest? field)
>     (not (eq? (configuration-field-name field) 'url)))
>   (let ((url (repository-cgit-configuration-url x))
>         (rest (filter rest? repository-cgit-configuration-fields)))
>     (serialize-repo-string 'url url)
>     (serialize-configuration x rest)))

Output doesn't change.

--8<---------------cut here---------------start------------->8---
scheme@(gnu services cgit)> (serialize-configuration
                             (repository-cgit-configuration
                              (url "http://cgit.magnolia.local")
                              (source-filter "la"))
                             repository-cgit-configuration-fields)
repo.enable-commit-graph=0
repo.enable-log-filecount=0
repo.enable-log-linecount=0
repo.enable-remote-branches=0
repo.enable-subject-links=0
repo.enable-html-serving=0
repo.hide=0
repo.ignore=0
repo.source-filter=la
repo.url=http://cgit.magnolia.local
scheme@(gnu services cgit)> 
It's been nice interacting with you!
Press C-c C-z to bring me back.
GNU Guile 2.2.2
Copyright (C) 1995-2017 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> ,m (gnu services cgit)
;;; note: source file /home/natsu/src/guix-wip-cgit/gnu/services/cgit.scm
;;;       newer than compiled /home/natsu/src/guix-wip-cgit/gnu/services/cgit.go
;;; note: source file /home/natsu/src/guix-wip-cgit/gnu/services/cgit.scm
;;;       newer than compiled /home/natsu/.cache/guile/ccache/2.2-LE-8-3.A/home/natsu/src/guix-wip-cgit/gnu/services/cgit.scm.go
scheme@(gnu services cgit)> (serialize-configuration
                              (repository-cgit-configuration
                              (url "http://cgit.magnolia.local")
                              (source-filter "la"))
                             repository-cgit-configuration-fields)
repo.enable-commit-graph=0
repo.enable-log-filecount=0
repo.enable-log-linecount=0
repo.enable-remote-branches=0
repo.enable-subject-links=0
repo.enable-html-serving=0
repo.hide=0
repo.ignore=0
repo.source-filter=la
repo.url=http://cgit.magnolia.local
--8<---------------cut here---------------end--------------->8---

> The same mechanism could be used for 'snapshots' and 'source-filter',
> according to the Archlinux link you provided.

However, simple reordering fields in (define-configuration …) works.
I reordered in attached patch.  Is it good enough?

--8<---------------cut here---------------start------------->8---
scheme@(gnu services cgit)> (serialize-configuration
                             (repository-cgit-configuration
                              (url "http://cgit.magnolia.local")
                              (source-filter "la"))
                             repository-cgit-configuration-fields)
repo.url=http://cgit.magnolia.local
repo.enable-commit-graph=0
repo.enable-log-filecount=0
repo.enable-log-linecount=0
repo.enable-remote-branches=0
repo.enable-subject-links=0
repo.enable-html-serving=0
repo.hide=0
repo.ignore=0
repo.source-filter=la
--8<---------------cut here---------------end--------------->8---

>> +(define (serialize-module-link-path field-name val)
>> +  (if (null? val)
>> +      ""
>> +      (format #t "repo.~a.~a=~a\n"
>> +              (uglify-field-name field-name)
>> +              (car val) (cadr val))))
>
> I think 'match' is better than 'car' and 'cadr' because it names things.

Applied.

>> +(define (serialize-mimetype-alist field-name val)
>> +  (format #t "# Mimetypes\n~a"
>> +          (apply string-append
>> +                 (fold (lambda (x xs)
>> +                         (cons* (symbol->string (car x)) "=" (cadr x) "\n" xs))
>> +                       '() val))))
>
>
> Maybe you could use 'match' instead of 'car' and 'cadr'?  And I think
> 'x' and 'xs' are not very clear.  Also, isn't 'map' more natural than
> 'fold'?  I'd use something like this:
>
> (define (serialize-mimetype-alist-clem field-name val)
>   (format #t "# Mimetypes\n~a"
>           (string-join
>            (map (match-lambda
>                   ((extension mimetype)
>                    (format #f "~a=~a" (symbol->string extension) mimetype)))
>                 val) "\n")))
>
> Another advantage is that the order won't be inverted.

Applied.  Also I added forgoten "mimetype.".

>> +  (defbranch
>> +    (repo-string "")
>       ^--- Extra space here (because of 'def' being interpreted by your
>            text editor I reckon).

Applied.

>> +    "The name of the default branch for this repository. If no such branch
>                                Two spaces here :-) --------^

Applied.

>> +  (email-filter
>> +   (repo-string "")
>> +   "Override the default @code{email-filter.}")
>                                         }. ---^

Applied.

>> +  (enable-remote-branches?
>> +   (repo-boolean #f)
>> +   "Flag which, when set to @code{#t}, will make Cgit display remote
>> +branches in the summary and refs views.")
>
> I think the official project uses 'cgit' instead of 'Cgit' (there are
> other occurrences where you use 'Cgit').

Ludovic asked to capitalize cgit in
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28283#14

>> +(define-configuration cgit-configuration
>> +  (package
>> +    (package cgit)
>      ^--- There is one extra space here (because package is interpreted
>           by your text editor I reckon).

Applied.

>> +  (footer
>> +   (string "")
>> +   "The content of the file specified with this option will be included
>> +verbatim at the bottom of all pages (i.e. it replaces the standard
>> +\"generated by...\" message.")
>
> I think you forgot the closing parenthesis inside the comment.

Applied.

>> +  (max-stats
>> +   (string "")
>> +   "Maximum statistics period.  Valid values are @samp{week},@samp{month},
>                                               Space here :-) ---^
>> +@samp{quarter} and @samp{year.}")
>                          }. ----^

Done

>> +  (scan-hidden-path
>> +   (boolean #f)
>> +   "If set to @samp{#t} and repository-directory is enabled,
>> +repository-directory will recurse into directories whose name starts with a
>> +period.  Otherwise, repository-directory will stay away from such directories,
>> +considered as \"hidden\". Note that this does not apply to the \".git\"
>             Space here -----^

Applied.

>> +  (repository-directory
>> +   (repository-directory "/srv/git")
>> +   "Name of the directory to scan for repositories.")
>
> I believe it would be clearer if it was named the same way cgit names
> it: scan-path.

Ludovic asked to rename it in
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28283#14

I don't know should we stay close to cgit naming conventions or not.
Thoughts?

>> +  (project-list
>> +   (list '())
>> +   "A list of subdirectories inside of @code{repository-directory}, relative
>> +to it, that should loaded as Git repositories.")
>
> I forgot one thing: 'project-list' is a file, not a list of strings.  I
> agree it's weird that cgit's documentation doesn't say it's a file.  I
> see two solutions:

Sorry, it's not clear for me.  As I understand from CGITRC(5) it's a
list like:

    project-list=/share/cgit/cgit.png /share/cgit/cgit.jpg

relative to /srv/git (in our case).

> 1. Change the type to 'string', so that people can set a file name.
>
> 2. Use a list type that would transparently transform its values into a
>    file in the store, with the generated cgitrc file pointing to it.
>
> The second solution is better because the user won't need to create the
> file.

I choose 1st for now, because 2nd I don't understand what need to be
produced at the end.  Could you give me an example?

> Also, could you add a way to use an opaque configuration file?  It would
> be helpful for users who don't have time to update their configuration,
> or in case there are new cgit configurations that are not yet
> implemented by the Scheme service.

Sure.

Is the following order is OK?

    (serialize-configuration
     (cgit-configuration
      (extra-options (list "soo=do"))
      (repositories (list
                     (repository-cgit-configuration
                      (module-link-path '("/super/cow" "moo"))
                      (extra-options (list "goo=foo"))))))
     cgit-configuration-fields)

    …
    repo.extra-options=goo=foo
    extra-options=soo=do
    # END OF FILE

Also I need to mention that this patch probably will broke system
reconfigure and require update /etc/config.scm.

>From d48b3bf9915e4d161eec98a3d52df8644a0b2bfa Mon Sep 17 00:00:00 2001
From: Oleg Pykhalov <[email-masked]>
Date: Tue, 12 Dec 2017 02:13:55 +0300
Subject: [PATCH] services: cgit: Add more configuration fields.

* gnu/services/version-control.scm (cgit-service-type): Move to separate file.
* gnu/services/cgit.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add this.
* gnu/tests/version-control.scm (gnu): Add this.
* doc/guix.texi (Cgit Service): Document this.
---
 doc/guix.texi                    | 942 +++++++++++++++++++++++++++++++++++++--
 gnu/local.mk                     |   1 +
 gnu/services/cgit.scm            | 658 +++++++++++++++++++++++++++
 gnu/services/version-control.scm | 118 -----
 gnu/tests/version-control.scm    |   1 +
 5 files changed, 1568 insertions(+), 152 deletions(-)
 create mode 100644 gnu/services/cgit.scm

diff --git a/doc/guix.texi b/doc/guix.texi
index 94d4d8f92..19ba6b5a6 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -17897,57 +17897,931 @@ By default, Cgit can be accessed on port 80 (@code{http://localhost:80}).
 @example
 (service nginx-service-type)
 (service fcgiwrap-service-type)
-(service cgit-service-type)
+(service cgit-service-type
+         (cgit-configuration
+          (branch-sort "age")
+          (enable-commit-graph? #t)
+          (enable-follow-links? #t)
+          (enable-index-links? #t)
+          (enable-log-filecount? #t)
+          (enable-log-linecount? #t)
+          (enable-remote-branches? #t)
+          (enable-subject-links? #t)
+          (remove-suffix? #t)
+          (enable-index-owner? #f)
+          (snapshots (list "tar.gz"))))
 @end example
 
-@deftp {Data Type} cgit-configuration
-Data type representing the configuration of Cgit.
-This type has the following parameters:
+@c The following documentation was initially generated by
+@c (generate-cgit-documentation) in (gnu services cgit).  Manually
+@c maintained documentation is better, so we shouldn't hesitate to edit
+@c below as needed.  However if the change you want to make to this
+@c documentation can be done in an automated way, it's probably easier
+@c to change (generate-documentation) than to make it below and have to
+@c deal with the churn as Cgit updates.
 
-@table @asis
-@item @code{config-file} (default: @code{(cgit-configuration-file)})
-The configuration file to use for Cgit.  This can be set to a
-@dfn{cgit-configuration-file} record value, or any gexp
-(@pxref{G-Expressions}).
+Available @code{cgit-configuration} fields are:
 
-For example, to instead use a local file, the @code{local-file} function
-can be used:
+@deftypevr {@code{cgit-configuration} parameter} package package
+The CGIT package.
 
-@example
-(service cgit-service-type
-         (cgit-configuration
-           (config-file (local-file "./my-cgitrc.conf"))))
-@end example
+@end deftypevr
 
-@item @code{package} (default: @code{cgit})
-The Cgit package to use.
+@deftypevr {@code{cgit-configuration} parameter} nginx-server-configuration-list nginx
+NGINX configuration.
 
-@end table
-@end deftp
+@end deftypevr
 
-@deftp {Data Type} cgit-configuration-file
-Data type representing the configuration options for Cgit.
-This type has the following parameters:
+@deftypevr {@code{cgit-configuration} parameter} string about-filter
+Specifies a command which will be invoked to format the content of about
+pages (both top-level and for each repository).
 
-@table @asis
-@item @code{css} (default: @code{"/share/cgit/cgit.css"})
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string agefile
+Specifies a path, relative to each repository path, which can be used to
+specify the date and time of the youngest commit in the repository.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string auth-filter
+Specifies a command that will be invoked for authenticating repository
+access.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string branch-sort
+Flag which, when set to @samp{age}, enables date ordering in the branch
+ref list, and when set @samp{name} enables ordering by branch name.
+
+Defaults to @samp{"name"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string cache-root
+Path used to store the Cgit cache entries.
+
+Defaults to @samp{"/var/cache/cgit"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-static-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of repository pages accessed with a fixed SHA1.
+
+Defaults to @samp{-1}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-dynamic-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of repository pages accessed without a fixed SHA1.
+
+Defaults to @samp{5}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-repo-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of the repository summary page.
+
+Defaults to @samp{5}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-root-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of the repository index page.
+
+Defaults to @samp{5}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-scanrc-ttl
+Number which specifies the time-to-live, in minutes, for the result of
+scanning a path for Git repositories.
+
+Defaults to @samp{15}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-about-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of the repository about page.
+
+Defaults to @samp{15}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-snapshot-ttl
+Number which specifies the time-to-live, in minutes, for the cached
+version of snapshots.
+
+Defaults to @samp{5}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer cache-size
+The maximum number of entries in the cgit cache.  When set to @samp{0},
+caching is disabled.
+
+Defaults to @samp{0}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean case-sensitive-sort?
+Sort items in the repo list case sensitively.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} list clone-prefix
+List of common prefixes which, when combined with a repository URL,
+generates valid clone URLs for the repository.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} list clone-url
+List of @code{clone-url} templates.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string commit-filter
+Command which will be invoked to format commit messages.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string commit-sort
+Flag which, when set to @samp{date}, enables strict date ordering in the
+commit log, and when set to @samp{topo} enables strict topological
+ordering.
+
+Defaults to @samp{"git log"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string css
 URL which specifies the css document to include in all Cgit pages.
 
-@item @code{logo} (default: @code{"/share/cgit/cgit.png"})
+Defaults to @samp{"/share/cgit/cgit.css"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string email-filter
+Specifies a command which will be invoked to format names and email
+address of committers, authors, and taggers, as represented in various
+places throughout the Cgit interface.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean embedded?
+Flag which, when set to @samp{#t}, will make Cgit generate a HTML
+fragment suitable for embedding in other HTML pages.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-commit-graph?
+Flag which, when set to @samp{#t}, will make Cgit print an ASCII-art
+commit history graph to the left of the commit messages in the
+repository log page.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-filter-overrides?
+Flag which, when set to @samp{#t}, allows all filter settings to be
+overridden in repository-specific cgitrc files.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-follow-links?
+Flag which, when set to @samp{#t}, allows users to follow a file in the
+log view.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-http-clone?
+If set to @samp{#t}, Cgit will act as an dumb HTTP endpoint for Git
+clones.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-index-links?
+Flag which, when set to @samp{#t}, will make Cgit generate extra links
+"summary", "commit", "tree" for each repo in the repository index.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-index-owner?
+Flag which, when set to @samp{#t}, will make Cgit display the owner of
+each repo in the repository index.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-log-filecount?
+Flag which, when set to @samp{#t}, will make Cgit print the number of
+modified files for each commit on the repository log page.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-log-linecount?
+Flag which, when set to @samp{#t}, will make Cgit print the number of
+added and removed lines for each commit on the repository log page.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-remote-branches?
+Flag which, when set to @code{#t}, will make Cgit display remote
+branches in the summary and refs views.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-subject-links?
+Flag which, when set to @code{1}, will make Cgit use the subject of the
+parent commit as link text when generating links to parent commits in
+commit view.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-html-serving?
+Flag which, when set to @samp{#t}, will make Cgit use the subject of the
+parent commit as link text when generating links to parent commits in
+commit view.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-tree-linenumbers?
+Flag which, when set to @samp{#t}, will make Cgit generate linenumber
+links for plaintext blobs printed in the tree view.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean enable-git-config?
+Flag which, when set to @samp{#f}, will allow Cgit to use Git config to
+set any repo specific settings.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string favicon
+URL used as link to a shortcut icon for Cgit.
+
+Defaults to @samp{"/favicon.ico"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string footer
+The content of the file specified with this option will be included
+verbatim at the bottom of all pages (i.e.  it replaces the standard
+"generated by..." message).
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string head-include
+The content of the file specified with this option will be included
+verbatim in the HTML HEAD section on all pages.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string header
+The content of the file specified with this option will be included
+verbatim at the top of all pages.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string include
+Name of a configfile to include before the rest of the current config-
+file is parsed.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string index-header
+The content of the file specified with this option will be included
+verbatim above the repository index.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string index-info
+The content of the file specified with this option will be included
+verbatim below the heading on the repository index page.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean local-time?
+Flag which, if set to @samp{#t}, makes Cgit print commit and tag times
+in the servers timezone.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string logo
 URL which specifies the source of an image which will be used as a logo
 on all Cgit pages.
 
-@item @code{virtual-root} (default: @code{"/"})
-URL which, if specified, will be used as root for all Cgit links.
+Defaults to @samp{"/share/cgit/cgit.png"}.
 
-@item @code{repository-directory} (default: @code{"/srv/git"})
-Name of the directory to scan for repositories.
+@end deftypevr
 
-@item @code{robots} (default: @code{(list "noindex" "nofollow")})
-Text used as content for the ``robots'' meta-tag.
+@deftypevr {@code{cgit-configuration} parameter} string logo-link
+URL loaded when clicking on the Cgit logo image.
 
-@end table
-@end deftp
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string owner-filter
+Command which will be invoked to format the Owner column of the main
+page.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-atom-items
+Number of items to display in atom feeds view.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-commit-count
+Number of entries to list per page in "log" view.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-message-length
+Number of commit message characters to display in "log" view.
+
+Defaults to @samp{80}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-repo-count
+Specifies the number of entries to list per page on the repository index
+page.
+
+Defaults to @samp{50}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-repodesc-length
+Specifies the maximum number of repo description characters to display
+on the repository index page.
+
+Defaults to @samp{80}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer max-blob-size
+Specifies the maximum size of a blob to display HTML for in KBytes.
+
+Defaults to @samp{0}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string max-stats
+Maximum statistics period.  Valid values are @samp{week},@samp{month},
+@samp{quarter} and @samp{year}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} mimetype-alist mimetype
+Mimetype for the specified filename extension.
+
+Defaults to @samp{((gif "image/gif") (html "text/html") (jpg
+"image/jpeg") (jpeg "image/jpeg") (pdf "application/pdf") (png
+"image/png") (svg "image/svg+xml"))}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string mimetype-file
+Specifies the file to use for automatic mimetype lookup.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string module-link
+Text which will be used as the formatstring for a hyperlink when a
+submodule is printed in a directory listing.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean nocache?
+If set to the value @samp{#t} caching will be disabled.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean noplainemail?
+If set to @samp{#t} showing full author email addresses will be
+disabled.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean noheader?
+Flag which, when set to @samp{#t}, will make Cgit omit the standard
+header on all pages.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string project-list
+A list of subdirectories inside of @code{repository-directory}, relative
+to it, that should loaded as Git repositories.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string readme
+Text which will be used as default value for @code{cgit-repo-readme}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean remove-suffix?
+If set to @code{#t} and @code{repository-directory} is enabled, if any
+repositories are found with a suffix of @code{.git}, this suffix will be
+removed for the URL and name.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer renamelimit
+Maximum number of files to consider when detecting renames.
+
+Defaults to @samp{-1}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string repository-sort
+The way in which repositories in each section are sorted.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} robots-list robots
+Text used as content for the @code{robots} meta-tag.
+
+Defaults to @samp{("noindex" "nofollow")}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string root-desc
+Text printed below the heading on the repository index page.
+
+Defaults to @samp{"a fast webinterface for the git dscm"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string root-readme
+The content of the file specified with this option will be included
+verbatim below thef "about" link on the repository index page.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string root-title
+Text printed as heading on the repository index page.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean scan-hidden-path
+If set to @samp{#t} and repository-directory is enabled,
+repository-directory will recurse into directories whose name starts
+with a period.  Otherwise, repository-directory will stay away from such
+directories, considered as "hidden".  Note that this does not apply to
+the ".git" directory in non-bare repos.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} list snapshots
+Text which specifies the default set of snapshot formats that cgit
+generates links for.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} repository-directory repository-directory
+Name of the directory to scan for repositories.
+
+Defaults to @samp{"/srv/git"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string section
+The name of the current repository section - all repositories defined
+after this option will inherit the current section name.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string section-sort
+Flag which, when set to @samp{1}, will sort the sections on the
+repository listing by name.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer section-from-path
+A number which, if defined prior to repository-directory, specifies how
+many path elements from each repo path to use as a default section name.
+
+Defaults to @samp{0}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} boolean side-by-side-diffs?
+If set to @samp{#t} shows side-by-side diffs instead of unidiffs per
+default.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string source-filter
+Specifies a command which will be invoked to format plaintext blobs in
+the tree view.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer summary-branches
+Specifies the number of branches to display in the repository "summary"
+view.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer summary-log
+Specifies the number of log entries to display in the repository
+"summary" view.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} integer summary-tags
+Specifies the number of tags to display in the repository "summary"
+view.
+
+Defaults to @samp{10}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string strict-export
+Filename which, if specified, needs to be present within the repository
+for Cgit to allow access to that repository.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} string virtual-root
+URL which, if specified, will be used as root for all Cgit links.
+
+Defaults to @samp{"/"}.
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} repository-cgit-configuration-list repositories
+A list of @dfn{cgit-repo} records to use with config.
+
+Defaults to @samp{()}.
+
+Available @code{repository-cgit-configuration} fields are:
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-list snapshots
+A mask of snapshot formats for this repo that cgit generates links for,
+restricted by the global @code{snapshots} setting.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string source-filter
+Override the default @code{source-filter}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string url
+The relative URL used to access the repository.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string about-filter
+Override the default @code{about-filter}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string branch-sort
+Flag which, when set to @samp{age}, enables date ordering in the branch
+ref list, and when set to @samp{name} enables ordering by branch name.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-list clone-url
+A list of URLs which can be used to clone repo.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string commit-filter
+Override the default @code{commit-filter}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string commit-sort
+Flag which, when set to @samp{date}, enables strict date ordering in the
+commit log, and when set to @samp{topo} enables strict topological
+ordering.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string defbranch
+The name of the default branch for this repository.  If no such branch
+exists in the repository, the first branch name (when sorted) is used as
+default instead.  By default branch pointed to by HEAD, or "master" if
+there is no suitable HEAD.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string desc
+The value to show as repository description.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string homepage
+The value to show as repository homepage.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string email-filter
+Override the default @code{email-filter}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-commit-graph?
+A flag which can be used to disable the global setting
+@code{enable-commit-graph?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-log-filecount?
+A flag which can be used to disable the global setting
+@code{enable-log-filecount?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-log-linecount?
+A flag which can be used to disable the global setting
+@code{enable-log-linecount?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-remote-branches?
+Flag which, when set to @code{#t}, will make Cgit display remote
+branches in the summary and refs views.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-subject-links?
+A flag which can be used to override the global setting
+@code{enable-subject-links?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean enable-html-serving?
+A flag which can be used to override the global setting
+@code{enable-html-serving?}.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean hide?
+Flag which, when set to @code{#t}, hides the repository from the
+repository index.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-boolean ignore?
+Flag which, when set to @samp{#t}, ignores the repository.
+
+Defaults to @samp{#f}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string logo
+URL which specifies the source of an image which will be used as a logo
+on this repo’s pages.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string logo-link
+URL loaded when clicking on the Cgit logo image.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string owner-filter
+Override the default @code{owner-filter}.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string module-link
+Text which will be used as the formatstring for a hyperlink when a
+submodule is printed in a directory listing.  The arguments for the
+formatstring are the path and SHA1 of the submodule commit.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} module-link-path module-link-path
+Text which will be used as the formatstring for a hyperlink when a
+submodule with the specified subdirectory path is printed in a directory
+listing.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string max-stats
+Override the default maximum statistics period.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string name
+The value to show as repository name.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string owner
+A value used to identify the owner of the repository.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string path
+An absolute path to the repository directory.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string readme
+A path (relative to repo) which specifies a file to include verbatim as
+the "About" page for this repo.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-string section
+The name of the current repository section - all repositories defined
+after this option will inherit the current section name.
+
+Defaults to @samp{""}.
+
+@end deftypevr
+
+@deftypevr {@code{repository-cgit-configuration} parameter} repo-list extra-options
+Extra options will be appended to cgitrc file.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+@end deftypevr
+
+@deftypevr {@code{cgit-configuration} parameter} list extra-options
+Extra options will be appended to cgitrc file.
+
+Defaults to @samp{()}.
+
+@end deftypevr
 
 @node Setuid Programs
 @subsection Setuid Programs
diff --git a/gnu/local.mk b/gnu/local.mk
index b1cf3c3de..9c2f91b91 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -445,6 +445,7 @@ GNU_SYSTEM_MODULES =				\
   %D%/services/avahi.scm			\
   %D%/services/base.scm				\
   %D%/services/certbot.scm			\
+  %D%/services/cgit.scm			\
   %D%/services/configuration.scm		\
   %D%/services/cuirass.scm			\
   %D%/services/cups.scm				\
diff --git a/gnu/services/cgit.scm b/gnu/services/cgit.scm
new file mode 100644
index 000000000..c45124b7a
--- /dev/null
+++ b/gnu/services/cgit.scm
@@ -0,0 +1,658 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2017 Oleg Pykhalov <[email-masked]>
+;;;
+;;; 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 cgit)
+  #:use-module (gnu packages admin)
+  #:use-module (gnu packages version-control)
+  #:use-module (gnu services base)
+  #:use-module (gnu services configuration)
+  #:use-module (gnu services shepherd)
+  #:use-module (gnu services web)
+  #:use-module (gnu services)
+  #:use-module (gnu system shadow)
+  #:use-module (guix gexp)
+  #:use-module (guix packages)
+  #:use-module (guix records)
+  #:use-module (guix store)
+  #:use-module (ice-9 match)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
+  #:export (repository-cgit-configuration
+            cgit-configuration
+            %cgit-configuration-nginx
+            cgit-configuration-nginx-config
+            cgit-service-type))
+
+(define %cgit-configuration-nginx
+  (nginx-server-configuration
+   (root cgit)
+   (locations
+    (list
+     (nginx-location-configuration
+      (uri "@cgit")
+      (body '("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;"
+              "fastcgi_param PATH_INFO $uri;"
+              "fastcgi_param QUERY_STRING $args;"
+              "fastcgi_param HTTP_HOST $server_name;"
+              "fastcgi_pass 127.0.0.1:9000;")))))
+   (try-files (list "$uri" "@cgit"))
+   (listen '("80"))
+   (ssl-certificate #f)
+   (ssl-certificate-key #f)))
+
+
+;;;
+;;; Serialize <cgit-configuration>
+;;;
+
+(define (uglify-field-name field-name)
+  (let ((str (symbol->string field-name)))
+    (string-join (string-split (string-delete #\? str) #\-) "-")))
+
+(define (serialize-field field-name val)
+  (format #t "~a=~a\n" (uglify-field-name field-name) val))
+
+(define (serialize-string field-name val)
+  (if (string=? val "") "" (serialize-field field-name val)))
+
+(define (serialize-boolean field-name val)
+  (serialize-field field-name (if val 1 0)))
+
+(define (serialize-list field-name val)
+  (if (null? val) "" (serialize-field field-name (string-join val))))
+
+(define robots-list? list?)
+
+(define (serialize-robots-list field-name val)
+  (if (null? val) "" (serialize-field field-name (string-join val ", "))))
+
+(define (integer? val)
+  (exact-integer? val))
+
+(define (serialize-integer field-name val)
+  (serialize-field field-name val))
+
+(define (serialize-repository-cgit-configuration x)
+  (serialize-configuration x repository-cgit-configuration-fields))
+
+(define (repository-cgit-configuration-list? val)
+  (list? val))
+
+(define (serialize-repository-cgit-configuration-list field-name val)
+  (for-each serialize-repository-cgit-configuration val))
+
+(define (nginx-server-configuration-list? val)
+  (and (list? val) (and-map nginx-server-configuration? val)))
+
+(define (serialize-nginx-server-configuration-list field-name val)
+  #f)
+
+
+;;;
+;;; Serialize <repository-cgit-configuration>
+;;;
+
+(define (serialize-repo-field field-name val)
+  (format #t "repo.~a=~a\n" (uglify-field-name field-name) val))
+
+(define (serialize-repo-list field-name val)
+  (if (null? val) "" (serialize-repo-field field-name (string-join val))))
+
+(define repo-boolean? boolean?)
+
+(define (serialize-repo-boolean field-name val)
+  (serialize-repo-field field-name (if val 1 0)))
+
+(define (serialize-repo-integer field-name val)
+  (serialize-repo-field field-name val))
+
+(define repo-list? list?)
+
+(define repo-string? string?)
+
+(define (serialize-repo-string field-name val)
+  (if (string=? val "") "" (serialize-repo-field field-name val)))
+
+(define module-link-path? list?)
+
+(define (serialize-module-link-path field-name val)
+  (if (null? val) ""
+      (match val
+        ((path text)
+         (format #t "repo.~a.~a=~a\n"
+                 (string-drop-right (uglify-field-name 'module-link-path)
+                                    (string-length "-path"))
+                 path text)))))
+
+(define repository-directory? string?)
+
+(define (serialize-repository-directory _ val)
+  (if (string=? val "") "" (format #t "scan-path=~a\n" val)))
+
+(define mimetype-alist? list?)
+
+(define (serialize-mimetype-alist field-name val)
+  (format #t "# Mimetypes\n~a"
+          (string-join
+           (map (match-lambda
+                  ((extension mimetype)
+                   (format #f "mimetype.~a=~a"
+                           (symbol->string extension) mimetype)))
+                val) "\n")))
+
+(define-configuration repository-cgit-configuration
+  (snapshots ; ¹
+   (repo-list '())
+   "A mask of snapshot formats for this repo that cgit generates links for,
+restricted by the global @code{snapshots} setting.")
+  (source-filter; ¹
+   (repo-string "")
+   "Override the default @code{source-filter}.")
+  (url ; ¹
+   (repo-string "")
+   "The relative URL used to access the repository.")
+  (about-filter
+   (repo-string "")
+   "Override the default @code{about-filter}.")
+  (branch-sort
+   (repo-string "")
+   "Flag which, when set to @samp{age}, enables date ordering in the branch
+ref list, and when set to @samp{name} enables ordering by branch name.")
+  (clone-url
+   (repo-list '())
+   "A list of URLs which can be used to clone repo.")
+  (commit-filter
+   (repo-string "")
+   "Override the default @code{commit-filter}.")
+  (commit-sort
+   (repo-string "")
+   "Flag which, when set to @samp{date}, enables strict date ordering in the
+commit log, and when set to @samp{topo} enables strict topological ordering.")
+  (defbranch
+   (repo-string "")
+   "The name of the default branch for this repository.  If no such branch
+exists in the repository, the first branch name (when sorted) is used as
+default instead.  By default branch pointed to by HEAD, or \"master\" if there
+is no suitable HEAD.")
+  (desc
+   (repo-string "")
+   "The value to show as repository description.")
+  (homepage
+   (repo-string "")
+   "The value to show as repository homepage.")
+  (email-filter
+   (repo-string "")
+   "Override the default @code{email-filter}.")
+  (enable-commit-graph?
+   (repo-boolean #f)
+   "A flag which can be used to disable the global setting
+@code{enable-commit-graph?}.")
+  (enable-log-filecount?
+   (repo-boolean #f)
+   "A flag which can be used to disable the global setting
+@code{enable-log-filecount?}.")
+  (enable-log-linecount?
+   (repo-boolean #f)
+   "A flag which can be used to disable the global setting
+@code{enable-log-linecount?}.")
+  (enable-remote-branches?
+   (repo-boolean #f)
+   "Flag which, when set to @code{#t}, will make Cgit display remote
+branches in the summary and refs views.")
+  (enable-subject-links?
+   (repo-boolean #f)
+   "A flag which can be used to override the global setting
+@code{enable-subject-links?}.")
+  (enable-html-serving?
+   (repo-boolean #f)
+   "A flag which can be used to override the global setting
+@code{enable-html-serving?}.")
+  (hide?
+   (repo-boolean #f)
+   "Flag which, when set to @code{#t}, hides the repository from the
+repository index.")
+  (ignore?
+   (repo-boolean #f)
+   "Flag which, when set to @samp{#t}, ignores the repository.")
+  (logo
+   (repo-string "")
+   "URL which specifies the source of an image which will be used as a
+logo on this repo’s pages.")
+  (logo-link
+   (repo-string "")
+   "URL loaded when clicking on the Cgit logo image.")
+  (owner-filter
+   (repo-string "")
+   "Override the default @code{owner-filter}.")
+  (module-link
+   (repo-string "")
+   "Text which will be used as the formatstring for a hyperlink when a
+submodule is printed in a directory listing.  The arguments for the
+formatstring are the path and SHA1 of the submodule commit.")
+  (module-link-path
+   (module-link-path '())
+   "Text which will be used as the formatstring for a hyperlink when a
+submodule with the specified subdirectory path is printed in a directory
+listing.")
+  (max-stats
+   (repo-string "")
+   "Override the default maximum statistics period.")
+  (name
+   (repo-string "")
+   "The value to show as repository name.")
+  (owner
+   (repo-string "")
+   "A value used to identify the owner of the repository.")
+  (path
+   (repo-string "")
+   "An absolute path to the repository directory.")
+  (readme
+   (repo-string "")
+   "A path (relative to repo) which specifies a file to include verbatim
+as the \"About\" page for this repo.")
+  (section
+   (repo-string "")
+   "The name of the current repository section - all repositories defined
+after this option will inherit the current section name.")
+  (extra-options
+   (repo-list '())
+   "Extra options will be appended to cgitrc file."))
+
+;; Generate a <cgit-configuration> record, which may include a list of
+;; <repository-cgit-configuration>, <nginx-server-configuration>, <package>.
+(define-configuration cgit-configuration
+  (package
+   (package cgit)
+   "The CGIT package.")
+  (nginx
+   (nginx-server-configuration-list (list %cgit-configuration-nginx))
+   "NGINX configuration.")
+  (about-filter
+   (string "")
+   "Specifies a command which will be invoked to format the content of about
+pages (both top-level and for each repository).")
+  (agefile
+   (string "")
+   "Specifies a path, relative to each repository path, which can be used to
+specify the date and time of the youngest commit in the repository.")
+  (auth-filter
+   (string "")
+   "Specifies a command that will be invoked for authenticating repository
+access.")
+  (branch-sort
+   (string "name")
+   "Flag which, when set to @samp{age}, enables date ordering in the branch
+ref list, and when set @samp{name} enables ordering by branch name.")
+  (cache-root
+   (string "/var/cache/cgit")
+   "Path used to store the Cgit cache entries.")
+  (cache-static-ttl
+   (integer -1)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of repository pages accessed with a fixed SHA1.")
+  (cache-dynamic-ttl
+   (integer 5)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of repository pages accessed without a fixed SHA1.")
+  (cache-repo-ttl
+   (integer 5)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of the repository summary page.")
+  (cache-root-ttl
+   (integer 5)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of the repository index page.")
+  (cache-scanrc-ttl
+   (integer 15)
+   "Number which specifies the time-to-live, in minutes, for the result of
+scanning a path for Git repositories.")
+  (cache-about-ttl
+   (integer 15)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of the repository about page.")
+  (cache-snapshot-ttl
+   (integer 5)
+   "Number which specifies the time-to-live, in minutes, for the cached
+version of snapshots.")
+  (cache-size
+   (integer 0)
+   "The maximum number of entries in the cgit cache. When set to
+@samp{0}, caching is disabled.")
+  (case-sensitive-sort?
+   (boolean #t)
+   "Sort items in the repo list case sensitively.")
+  (clone-prefix
+   (list '())
+   "List of common prefixes which, when combined with a repository URL,
+generates valid clone URLs for the repository.")
+  (clone-url
+   (list '())
+   "List of @code{clone-url} templates.")
+  (commit-filter
+   (string "")
+   "Command which will be invoked to format commit messages.")
+  (commit-sort
+   (string "git log")
+   "Flag which, when set to @samp{date}, enables strict date ordering in the
+commit log, and when set to @samp{topo} enables strict topological
+ordering.")
+  (css
+   (string "/share/cgit/cgit.css")
+   "URL which specifies the css document to include in all Cgit pages.")
+  (email-filter
+   (string "")
+   "Specifies a command which will be invoked to format names and email
+address of committers, authors, and taggers, as represented in various
+places throughout the Cgit interface.")
+  (embedded?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit generate a HTML
+fragment suitable for embedding in other HTML pages.")
+  (enable-commit-graph?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit print an ASCII-art
+commit history graph to the left of the commit messages in the
+repository log page.")
+  (enable-filter-overrides?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, allows all filter settings to be
+overridden in repository-specific cgitrc files.")
+  (enable-follow-links?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, allows users to follow a file in the
+log view.")
+  (enable-http-clone?
+   (boolean #t)
+   "If set to @samp{#t}, Cgit will act as an dumb HTTP endpoint for Git
+clones.")
+  (enable-index-links?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit generate extra links
+\"summary\", \"commit\", \"tree\" for each repo in the repository index.")
+  (enable-index-owner?
+   (boolean #t)
+   "Flag which, when set to @samp{#t}, will make Cgit display the owner of
+each repo in the repository index.")
+  (enable-log-filecount?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit print the number of
+modified files for each commit on the repository log page.")
+  (enable-log-linecount?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit print the number of
+added and removed lines for each commit on the repository log page.")
+  (enable-remote-branches?
+   (boolean #f)
+   "Flag which, when set to @code{#t}, will make Cgit display remote
+branches in the summary and refs views.")
+  (enable-subject-links?
+   (boolean #f)
+   "Flag which, when set to @code{1}, will make Cgit use the subject of
+the parent commit as link text when generating links to parent commits
+in commit view.")
+  (enable-html-serving?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit use the subject of the
+parent commit as link text when generating links to parent commits in
+commit view.")
+  (enable-tree-linenumbers?
+   (boolean #t)
+   "Flag which, when set to @samp{#t}, will make Cgit generate linenumber
+links for plaintext blobs printed in the tree view.")
+  (enable-git-config?
+   (boolean #f)
+   "Flag which, when set to @samp{#f}, will allow Cgit to use Git config to
+set any repo specific settings.")
+  (favicon
+   (string "/favicon.ico")
+   "URL used as link to a shortcut icon for Cgit.")
+  (footer
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim at the bottom of all pages (i.e. it replaces the standard
+\"generated by...\" message).")
+  (head-include
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim in the HTML HEAD section on all pages.")
+  (header
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim at the top of all pages.")
+  (include
+   (string "")
+   "Name of a configfile to include before the rest of the current config-
+file is parsed.")
+  (index-header
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim above the repository index.")
+  (index-info
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim below the heading on the repository index page.")
+  (local-time?
+   (boolean #f)
+   "Flag which, if set to @samp{#t}, makes Cgit print commit and tag times
+in the servers timezone.")
+  (logo
+   (string "/share/cgit/cgit.png")
+   "URL which specifies the source of an image which will be used as a logo
+on all Cgit pages.")
+  (logo-link
+   (string "")
+   "URL loaded when clicking on the Cgit logo image.")
+  (owner-filter
+   (string "")
+   "Command which will be invoked to format the Owner column of the main
+page.")
+  (max-atom-items
+   (integer 10)
+   "Number of items to display in atom feeds view.")
+  (max-commit-count
+   (integer 50)
+   "Number of entries to list per page in \"log\" view.")
+  (max-message-length
+   (integer 80)
+   "Number of commit message characters to display in \"log\" view.")
+  (max-repo-count
+   (integer 50)
+   "Specifies the number of entries to list per page on the repository index
+page.")
+  (max-repodesc-length
+   (integer 80)
+   "Specifies the maximum number of repo description characters to display
+on the repository index page.")
+  (max-blob-size
+   (integer 0)
+   "Specifies the maximum size of a blob to display HTML for in KBytes.")
+  (max-stats
+   (string "")
+   "Maximum statistics period.  Valid values are @samp{week},@samp{month},
+@samp{quarter} and @samp{year}.")
+  (mimetype
+   (mimetype-alist '((gif "image/gif")
+                     (html "text/html")
+                     (jpg "image/jpeg")
+                     (jpeg "image/jpeg")
+                     (pdf "application/pdf")
+                     (png "image/png")
+                     (svg "image/svg+xml")))
+   "Mimetype for the specified filename extension.")
+  (mimetype-file
+   (string "")
+   "Specifies the file to use for automatic mimetype lookup.")
+  (module-link
+   (string "")
+   "Text which will be used as the formatstring for a hyperlink when a
+submodule is printed in a directory listing.")
+  (nocache?
+   (boolean #f)
+   "If set to the value @samp{#t} caching will be disabled.")
+  (noplainemail?
+   (boolean #f)
+   "If set to @samp{#t} showing full author email addresses will be
+disabled.")
+  (noheader?
+   (boolean #f)
+   "Flag which, when set to @samp{#t}, will make Cgit omit the standard
+header on all pages.")
+  (project-list
+   (string "")
+   "A list of subdirectories inside of @code{repository-directory}, relative
+to it, that should loaded as Git repositories.")
+  (readme
+   (string "")
+   "Text which will be used as default value for @code{cgit-repo-readme}.")
+  (remove-suffix?
+   (boolean #f)
+   "If set to @code{#t} and @code{repository-directory} is enabled, if any
+repositories are found with a suffix of @code{.git}, this suffix will be
+removed for the URL and name.")
+  (renamelimit
+   (integer -1)
+   "Maximum number of files to consider when detecting renames.")
+  (repository-sort
+   (string "")
+   "The way in which repositories in each section are sorted.")
+  (robots
+   (robots-list (list "noindex" "nofollow"))
+   "Text used as content for the @code{robots} meta-tag.")
+  (root-desc
+   (string "a fast webinterface for the git dscm")
+   "Text printed below the heading on the repository index page.")
+  (root-readme
+   (string "")
+   "The content of the file specified with this option will be included
+verbatim below thef \"about\" link on the repository index page.")
+  (root-title
+   (string "")
+   "Text printed as heading on the repository index page.")
+  (scan-hidden-path
+   (boolean #f)
+   "If set to @samp{#t} and repository-directory is enabled,
+repository-directory will recurse into directories whose name starts with a
+period.  Otherwise, repository-directory will stay away from such directories,
+considered as \"hidden\".  Note that this does not apply to the \".git\"
+directory in non-bare repos.")
+  (snapshots ; ¹
+   (list '())
+   "Text which specifies the default set of snapshot formats that cgit
+generates links for.")
+  (repository-directory
+   (repository-directory "/srv/git")
+   "Name of the directory to scan for repositories.")
+  (section
+   (string "")
+   "The name of the current repository section - all repositories defined
+after this option will inherit the current section name.")
+  (section-sort
+   (string "")
+   "Flag which, when set to @samp{1}, will sort the sections on the repository
+listing by name.")
+  (section-from-path
+   (integer 0)
+   "A number which, if defined prior to repository-directory, specifies how
+many path elements from each repo path to use as a default section name.")
+  (side-by-side-diffs?
+   (boolean #f)
+   "If set to @samp{#t} shows side-by-side diffs instead of unidiffs per
+default.")
+  (source-filter
+   (string "")
+   "Specifies a command which will be invoked to format plaintext blobs in the
+tree view.")
+  (summary-branches
+   (integer 10)
+   "Specifies the number of branches to display in the repository \"summary\"
+view.")
+  (summary-log
+   (integer 10)
+   "Specifies the number of log entries to display in the repository
+\"summary\" view.")
+  (summary-tags
+   (integer 10)
+   "Specifies the number of tags to display in the repository \"summary\"
+view.")
+  (strict-export
+   (string "")
+   "Filename which, if specified, needs to be present within the repository
+for Cgit to allow access to that repository.")
+  (virtual-root
+   (string "/")
+   "URL which, if specified, will be used as root for all Cgit links.")
+  (repositories
+   (repository-cgit-configuration-list '())
+   "A list of @dfn{cgit-repo} records to use with config.")
+  (extra-options
+   (list '())
+   "Extra options will be appended to cgitrc file."))
+
+(define (configuration->text config)
+  (with-output-to-string
+    (lambda _
+      (serialize-configuration config cgit-configuration-fields))))
+
+(define (cgit-configuration-file config)
+  "Return the Cgit configuration file corresponding to CONFIG."
+  (plain-file "cgitrc" config))
+
+(define (cgit-configuration-file-text config)
+  (cgit-configuration-file (configuration->text config)))
+
+(define (cgit-activation config)
+  (match config
+    (($ <cgit-configuration> cache-root)
+     #~(begin
+         (use-modules (guix build utils))
+         (mkdir-p #$cache-root)
+         ;; Cgit compiled with default configuration path.
+         (copy-file #$(cgit-configuration-file-text config) "/etc/cgitrc")))))
+
+(define (cgit-configuration-nginx-config config)
+  (cgit-configuration-nginx config))
+
+(define cgit-service-type
+  (service-type
+   (name 'cgit)
+   (extensions
+    (list (service-extension activation-service-type
+                             cgit-activation)
+          (service-extension nginx-service-type
+                             cgit-configuration-nginx-config)))
+   (default-value (cgit-configuration))
+   (description
+    "Run the Cgit web interface, which allows users to browse Git
+repositories.")))
+
+(define (generate-cgit-documentation)
+  (generate-documentation
+   `((cgit-configuration
+      ,cgit-configuration-fields
+      (repositories repository-cgit-configuration))
+     (repository-cgit-configuration
+      ,repository-cgit-configuration-fields))
+   'cgit-configuration))
+
+
+;;;
+;;; Footnotes
+;;;
+
+;; ¹ Should be specified before in specific order,
+;;   see <https://wiki.archlinux.org/index.php/Cgit#snapshots_does_not_show_properly>.
diff --git a/gnu/services/version-control.scm b/gnu/services/version-control.scm
index 6bf656949..dc3bd056c 100644
--- a/gnu/services/version-control.scm
+++ b/gnu/services/version-control.scm
@@ -1,7 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2016 ng0 <[email-masked]>
 ;;; Copyright © 2016 Sou Bunnbu <[email-masked]>
-;;; Copyright © 2017 Oleg Pykhalov <[email-masked]>
 ;;; Copyright © 2017 Clément Lassieur <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -38,26 +37,6 @@
             git-daemon-configuration
             git-daemon-configuration?
 
-            <cgit-configuration-file>
-            cgit-configuration-file
-            cgit-configuration-file?
-            cgit-configuration-file-css
-            cgit-configuration-file-logo
-            cgit-configuration-file-robots
-            cgit-configuration-file-virtual-root
-            cgit-configuration-file-repository-directory
-
-            <cgit-configuration>
-            cgit-configuration
-            cgit-configuration?
-            cgit-configuration-config-file
-            cgit-configuration-package
-
-            %cgit-configuration-nginx
-            cgit-configuration-nginx-config
-
-            cgit-service-type
-
             git-http-configuration
             git-http-configuration?
             git-http-nginx-location-configuration))
@@ -173,103 +152,6 @@ access to exported repositories under @file{/srv/git}."
   (service git-daemon-service-type config))
 
 
-;;;
-;;; Cgit
-;;;
-
-(define-record-type* <cgit-configuration-file>
-  cgit-configuration-file
-  make-cgit-configuration-file
-  cgit-configuration-file?
-  (css                  cgit-configuration-file-css                  ; string
-                        (default "/share/cgit/cgit.css"))
-  (logo                 cgit-configuration-file-logo                 ; string
-                        (default "/share/cgit/cgit.png"))
-  (robots               cgit-configuration-file-robots               ; list
-                        (default '("noindex" "nofollow")))
-  (virtual-root         cgit-configuration-file-virtual-root         ; string
-                        (default "/"))
-  (repository-directory cgit-configuration-file-repository-directory ; string
-                        (default "/srv/git")))
-
-(define (cgit-configuration-robots-string robots)
-  (string-join robots ", "))
-
-(define-gexp-compiler (cgit-configuration-file-compiler
-                       (file <cgit-configuration-file>) system target)
-  (match file
-    (($ <cgit-configuration-file> css logo
-                                  robots virtual-root repository-directory)
-     (apply text-file* "cgitrc"
-            (letrec-syntax ((option (syntax-rules ()
-                                      ((_ key value)
-                                       (if value
-                                           `(,key "=" ,value "\n")
-                                           '()))))
-                            (key/value (syntax-rules ()
-                                         ((_ (key value) rest ...)
-                                          (append (option key value)
-                                                  (key/value rest ...)))
-                                         ((_)
-                                          '()))))
-              (key/value ("css" css)
-                         ("logo" logo)
-                         ("robots" (cgit-configuration-robots-string robots))
-                         ("virtual-root" virtual-root)
-                         ("scan-path" repository-directory)))))))
-
-(define %cgit-configuration-nginx
-  (list
-   (nginx-server-configuration
-    (root cgit)
-    (locations
-     (list
-      (nginx-location-configuration
-       (uri "@cgit")
-       (body '("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;"
-               "fastcgi_param PATH_INFO $uri;"
-               "fastcgi_param QUERY_STRING $args;"
-               "fastcgi_param HTTP_HOST $server_name;"
-               "fastcgi_pass 127.0.0.1:9000;")))))
-    (try-files (list "$uri" "@cgit"))
-    (listen '("80"))
-    (ssl-certificate #f)
-    (ssl-certificate-key #f))))
-
-(define-record-type* <cgit-configuration>
-  cgit-configuration make-cgit-configuration
-  cgit-configuration?
-  (config-file cgit-configuration-config-file
-               (default (cgit-configuration-file)))
-  (package cgit-configuration-package
-           (default cgit))
-  (nginx cgit-configuration-nginx
-         (default %cgit-configuration-nginx)))
-
-(define (cgit-activation config)
-  ;; Cgit compiled with default configuration path
-  #~(begin
-      (use-modules (guix build utils))
-      (mkdir-p "/var/cache/cgit")
-      (copy-file #$(cgit-configuration-config-file config) "/etc/cgitrc")))
-
-(define (cgit-configuration-nginx-config config)
-  (cgit-configuration-nginx config))
-
-(define cgit-service-type
-  (service-type
-   (name 'cgit)
-   (extensions
-    (list (service-extension activation-service-type
-                             cgit-activation)
-          (service-extension nginx-service-type
-                             cgit-configuration-nginx-config)))
-   (default-value (cgit-configuration))
-   (description
-    "Run the Cgit web interface, which allows users to browse Git
-repositories.")))
-
-
 ;;;
 ;;; HTTP access.  Add the result of calling
 ;;; git-http-nginx-location-configuration to an nginx-server-configuration's
diff --git a/gnu/tests/version-control.scm b/gnu/tests/version-control.scm
index 7367861b0..53e247a05 100644
--- a/gnu/tests/version-control.scm
+++ b/gnu/tests/version-control.scm
@@ -26,6 +26,7 @@
   #:use-module (gnu system vm)
   #:use-module (gnu services)
   #:use-module (gnu services version-control)
+  #:use-module (gnu services cgit)
   #:use-module (gnu services web)
   #:use-module (gnu services networking)
   #:use-module (gnu packages version-control)
-- 
2.15.1

Succeeded

    make check-system TESTS="cgit"

Thanks,
Oleg.