gitile/gitile/handler.scm

handler.scm

1
;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu>
2
;;;; 
3
;;;; This library is free software; you can redistribute it and/or
4
;;;; modify it under the terms of the GNU Lesser General Public
5
;;;; License as published by the Free Software Foundation; either
6
;;;; version 3 of the License, or (at your option) any later version.
7
;;;; 
8
;;;; This library is distributed in the hope that it will be useful,
9
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
;;;; Lesser General Public License for more details.
12
;;;; 
13
;;;; You should have received a copy of the GNU Lesser General Public
14
;;;; License along with this library; if not, write to the Free Software
15
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
;;;; 
17
18
(define-module (gitile handler)
19
  #:use-module (fibers web server)
20
  #:use-module (git)
21
  #:use-module (gitile config)
22
  #:use-module (gitile pages)
23
  #:use-module (ice-9 match)
24
  #:use-module (rnrs bytevectors)
25
  #:use-module (sxml simple)
26
  #:use-module (web request)
27
  #:use-module (web response)
28
  #:use-module (web uri)
29
  #:export (gitile-handler))
30
31
(define (request-path-components request)
32
  (split-and-decode-uri-path (uri-path (request-uri request))))
33
34
(define (not-found request)
35
  (format #t "Not found: ~a~%" (uri->string (request-uri request)))
36
  (show (style `((p "Resource not found: "
37
                    ,(uri->string (request-uri request))))
38
               "" "")))
39
40
(define (style page project ref)
41
  `(html
42
     (head
43
       (meta (@ (charset "UTF-8")))
44
       (meta (@ (name "viewport") (content "width=device-width, initial-scale=1")))
45
       (link (@ (rel "stylesheet") (href "/css/gitile.css")))
46
       (link (@ (rel "icon") (href "/images/icon.png") (sizes "32x32")))
47
       (script (@ (src "/js/gitile.js")) "")
48
       (title ,project))
49
     (body
50
       (header
51
         (nav
52
           (ul
53
             (li (@ (class "first")) (a (@ (href "/")) "Projects"))
54
             (li (a (@ (href "/" ,project)) "Repository"))
55
             (li (a (@ (href "/" ,project "/tree/" ,ref)) "Files"))
56
             (li (a (@ (href "/" ,project "/commits")) "Commits"))
57
             (li (a (@ (href "/" ,project "/tags")) "Tags")))))
58
       (div (@ (id "content"))
59
            ,@page)
60
       (footer (p (a (@ (href "https://lepiller.eu")) "Who am I?"))))))
61
62
(define* (show page #:key (code 200))
63
  (values (build-response #:code code #:headers '((content-type . (text/html))))
64
          (with-output-to-string (lambda _ (sxml->xml page)))))
65
66
(define (show-raw page)
67
  (values '((content-type . (text/plain)))
68
          page))
69
70
(define (gitile-handler config)
71
  (define (call-with-repo project-name callback)
72
    (define (repo-404 content project-name ref)
73
      (show (style content project-name ref)
74
            #:code 404))
75
    (define (repo-500 content)
76
      (show content #:code 500))
77
    (define (get-repo name)
78
      (let ((repo (string-append (config-repositories config)
79
                                 "/" name ".git")))
80
        (pk 'repo repo)
81
        (pk 'exists (file-exists? (string-append repo "/git-daemon-export-ok")))
82
        (if (file-exists? (string-append repo "/git-daemon-export-ok"))
83
            (repository-open repo)
84
            #f)))
85
  
86
    (let ((repo (get-repo project-name)))
87
      (if repo
88
          (catch #t
89
            (lambda _
90
              (callback repo))
91
            (lambda* (key . args)
92
              (match key
93
                ('not-found
94
                 (pk 'except key args)
95
                 (repo-404 (assoc-ref args 'content)
96
                           project-name
97
                           (or (assoc-ref args 'ref) "-")))
98
                (_
99
                  (pk 'uncaught-exception key args)
100
                  (repo-500 `((p "Internal error")))))))
101
          (repo-404 `((p "Repository not found: " ,project-name)) project-name
102
                    "-"))))
103
  (match config
104
    (($ <config> port host database repositories)
105
     (lambda (request body)
106
       (pk 'request request)
107
       (pk 'body (if body (utf8->string body) body))
108
       (match (request-path-components request)
109
         ((project-name)
110
          (call-with-repo project-name
111
            (lambda (repo)
112
              (show (style (project-index project-name repo)
113
                           project-name "-")))))
114
         ((project-name "tree" ref path ...)
115
          (call-with-repo project-name
116
            (lambda (repo)
117
              (show (style (project-files project-name repo #:ref ref #:path path)
118
                           project-name ref)))))
119
         ((project-name "raw" ref path ...)
120
          (call-with-repo project-name
121
            (lambda (repo)
122
              (show-raw (project-file-raw repo path #:ref ref)))))
123
         ((project-name "commits")
124
          (call-with-repo project-name
125
            (lambda (repo)
126
              (show (style (project-commits project-name repo #f)
127
                    project-name "-")))))
128
         ((project-name "commits" ref)
129
          (call-with-repo project-name
130
            (lambda (repo)
131
              (show (style (project-commits project-name repo ref)
132
                    project-name ref)))))
133
         ((project-name "commit" ref)
134
          (call-with-repo project-name
135
            (lambda (repo)
136
              (show (style (project-commit project-name repo ref)
137
                           project-name ref)))))
138
         ((project-name "tags")
139
          (call-with-repo project-name
140
            (lambda (repo)
141
              (show (style (project-tags project-name repo)
142
                    project-name "-")))))
143
     (_ (not-found request)))))))
144