Support projects in subdirectories.
gitile/handler.scm
| 25 | 25 | #:use-module (ice-9 match) | |
| 26 | 26 | #:use-module (rnrs bytevectors) | |
| 27 | 27 | #:use-module (srfi srfi-9) | |
| 28 | + | #:use-module (srfi srfi-11) | |
| 28 | 29 | #:use-module (sxml simple) | |
| 29 | 30 | #:use-module (web request) | |
| 30 | 31 | #:use-module (web response) | |
… | |||
| 114 | 115 | page)) | |
| 115 | 116 | ||
| 116 | 117 | (define (gitile-handler config) | |
| 118 | + | (define (repo-404 content project-name ref) | |
| 119 | + | (show (style content project-name ref (config-footer config)) | |
| 120 | + | #:code 404)) | |
| 121 | + | ||
| 122 | + | (define (repo-500 content) | |
| 123 | + | (show content #:code 500)) | |
| 124 | + | ||
| 117 | 125 | (define (call-with-repo project-name callback) | |
| 118 | - | (define (repo-404 content project-name ref) | |
| 119 | - | (show (style content project-name ref (config-footer config)) | |
| 120 | - | #:code 404)) | |
| 121 | - | (define (repo-500 content) | |
| 122 | - | (show content #:code 500)) | |
| 123 | 126 | (define (get-repo name) | |
| 124 | 127 | (let ((repo (string-append (config-repositories config) | |
| 125 | 128 | "/" name ".git")) | |
… | |||
| 151 | 154 | "-")))) | |
| 152 | 155 | ||
| 153 | 156 | (define (name->project project) | |
| 157 | + | (pk 'name->project project) | |
| 154 | 158 | (make-project project (call-with-repo project get-name) | |
| 155 | 159 | (call-with-repo project get-description))) | |
| 156 | 160 | ||
| 157 | 161 | (define (projects) | |
| 158 | - | (let ((dir (opendir (config-repositories config)))) | |
| 159 | - | (let loop ((res '()) (repo (readdir dir))) | |
| 160 | - | (if (eof-object? repo) | |
| 161 | - | res | |
| 162 | - | (if (and | |
| 163 | - | (> (string-length repo) 4) | |
| 164 | - | (file-exists? (string-append (config-repositories config) | |
| 165 | - | "/" repo "/git-daemon-export-ok"))) | |
| 166 | - | (loop | |
| 167 | - | (cons | |
| 168 | - | (name->project | |
| 169 | - | (if (equal? (substring repo (- (string-length repo) 4)) ".git") | |
| 170 | - | (substring repo 0 (- (string-length repo) 4)) | |
| 171 | - | repo)) | |
| 172 | - | res) | |
| 173 | - | (readdir dir)) | |
| 174 | - | (loop res (readdir dir))))))) | |
| 162 | + | (define (projects-aux dir) | |
| 163 | + | (pk 'opening 'projects 'in dir) | |
| 164 | + | (let ((opened-dir (opendir dir))) | |
| 165 | + | (let loop ((res '()) (repo (readdir opened-dir))) | |
| 166 | + | (cond | |
| 167 | + | ((eof-object? repo) | |
| 168 | + | (closedir opened-dir) | |
| 169 | + | res) | |
| 170 | + | ((file-exists? (string-append dir "/" repo "/git-daemon-export-ok")) | |
| 171 | + | (pk 'found dir '/ repo) | |
| 172 | + | (loop | |
| 173 | + | (cons | |
| 174 | + | (name->project | |
| 175 | + | (substring | |
| 176 | + | (string-append | |
| 177 | + | dir "/" | |
| 178 | + | (if (string-suffix? ".git" repo) | |
| 179 | + | (substring repo 0 (- (string-length repo) 4)) | |
| 180 | + | repo)) | |
| 181 | + | (+ (string-length (config-repositories config)) 1))) | |
| 182 | + | res) | |
| 183 | + | (readdir opened-dir))) | |
| 184 | + | ((file-exists? (string-append dir "/" repo "/.git")) | |
| 185 | + | (loop res (readdir opened-dir))) | |
| 186 | + | ((and (stat (string-append dir "/" repo) #f) | |
| 187 | + | (equal? (stat:type (stat (string-append dir "/" repo) #f)) 'directory) | |
| 188 | + | (not (equal? repo ".git")) | |
| 189 | + | (not (equal? repo ".")) | |
| 190 | + | (not (equal? repo ".."))) | |
| 191 | + | (loop (append (projects-aux (string-append dir "/" repo)) res) | |
| 192 | + | (readdir opened-dir))) | |
| 193 | + | (else (loop res (readdir opened-dir))))))) | |
| 194 | + | (projects-aux (config-repositories config))) | |
| 195 | + | ||
| 196 | + | (define (find-project-component request) | |
| 197 | + | (let ((request (string-join | |
| 198 | + | (split-and-decode-uri-path (uri-path (request-uri request))) | |
| 199 | + | "/"))) | |
| 200 | + | (let loop ((projects (projects))) | |
| 201 | + | (match projects | |
| 202 | + | (() (values "" (split-and-decode-uri-path request))) | |
| 203 | + | ((project projects ...) | |
| 204 | + | (let ((slug (project-slug project))) | |
| 205 | + | (if (or (string-prefix? (string-append slug "/") request) | |
| 206 | + | (equal? slug request)) | |
| 207 | + | (values (project-slug project) | |
| 208 | + | (split-and-decode-uri-path | |
| 209 | + | (substring request (string-length slug)))) | |
| 210 | + | (loop projects)))))))) | |
| 175 | 211 | ||
| 176 | 212 | (match config | |
| 177 | 213 | (($ <config> port host database repositories base-git-url index-title intro | |
… | |||
| 179 | 215 | (lambda (request body) | |
| 180 | 216 | (pk 'request request) | |
| 181 | 217 | (pk 'body (if body (utf8->string body) body)) | |
| 182 | - | (match (request-path-components request) | |
| 183 | - | (() | |
| 184 | - | (show (index-page (projects) base-git-url index-title intro footer))) | |
| 185 | - | ((project-name) | |
| 186 | - | (call-with-repo project-name | |
| 187 | - | (lambda (repo) | |
| 188 | - | (show (style (project-index base-git-url project-name repo) | |
| 189 | - | project-name "-" footer))))) | |
| 190 | - | ((project-name "tree" ref path ...) | |
| 191 | - | (call-with-repo project-name | |
| 192 | - | (lambda (repo) | |
| 193 | - | (show (style (project-files project-name repo #:ref ref #:path path) | |
| 194 | - | project-name ref footer))))) | |
| 195 | - | ((project-name "raw" ref path ...) | |
| 196 | - | (call-with-repo project-name | |
| 197 | - | (lambda (repo) | |
| 198 | - | (show-raw (project-file-raw repo path #:ref ref))))) | |
| 199 | - | ((project-name "commits") | |
| 200 | - | (call-with-repo project-name | |
| 201 | - | (lambda (repo) | |
| 202 | - | (show (style (project-commits project-name repo #f) | |
| 203 | - | project-name "-" footer))))) | |
| 204 | - | ((project-name "commits" ref) | |
| 205 | - | (call-with-repo project-name | |
| 206 | - | (lambda (repo) | |
| 207 | - | (show (style (project-commits project-name repo ref) | |
| 208 | - | project-name ref footer))))) | |
| 209 | - | ((project-name "commit" ref) | |
| 210 | - | (call-with-repo project-name | |
| 211 | - | (lambda (repo) | |
| 212 | - | (show (style (project-commit project-name repo ref) | |
| 213 | - | project-name ref footer))))) | |
| 214 | - | ((project-name "tags") | |
| 215 | - | (call-with-repo project-name | |
| 216 | - | (lambda (repo) | |
| 217 | - | (show (style (project-tags project-name repo) | |
| 218 | - | project-name "-" footer))))) | |
| 219 | - | (_ (not-found request footer))))))) | |
| 218 | + | (let-values (((project-name path) (find-project-component request))) | |
| 219 | + | (match (cons project-name path) | |
| 220 | + | (("" . ()) | |
| 221 | + | (pk 'index) | |
| 222 | + | (show (index-page (projects) base-git-url index-title intro footer))) | |
| 223 | + | (("" . args) | |
| 224 | + | (pk '404 args) | |
| 225 | + | (repo-404 "Project not found" "" | |
| 226 | + | "-")) | |
| 227 | + | ((project-name) | |
| 228 | + | (call-with-repo project-name | |
| 229 | + | (lambda (repo) | |
| 230 | + | (show (style (project-index base-git-url project-name repo) | |
| 231 | + | project-name "-" footer))))) | |
| 232 | + | ((project-name "tree" ref path ...) | |
| 233 | + | (call-with-repo project-name | |
| 234 | + | (lambda (repo) | |
| 235 | + | (show (style (project-files project-name repo #:ref ref #:path path) | |
| 236 | + | project-name ref footer))))) | |
| 237 | + | ((project-name "raw" ref path ...) | |
| 238 | + | (call-with-repo project-name | |
| 239 | + | (lambda (repo) | |
| 240 | + | (show-raw (project-file-raw repo path #:ref ref))))) | |
| 241 | + | ((project-name "commits") | |
| 242 | + | (call-with-repo project-name | |
| 243 | + | (lambda (repo) | |
| 244 | + | (show (style (project-commits project-name repo #f) | |
| 245 | + | project-name "-" footer))))) | |
| 246 | + | ((project-name "commits" ref) | |
| 247 | + | (call-with-repo project-name | |
| 248 | + | (lambda (repo) | |
| 249 | + | (show (style (project-commits project-name repo ref) | |
| 250 | + | project-name ref footer))))) | |
| 251 | + | ((project-name "commit" ref) | |
| 252 | + | (call-with-repo project-name | |
| 253 | + | (lambda (repo) | |
| 254 | + | (show (style (project-commit project-name repo ref) | |
| 255 | + | project-name ref footer))))) | |
| 256 | + | ((project-name "tags") | |
| 257 | + | (call-with-repo project-name | |
| 258 | + | (lambda (repo) | |
| 259 | + | (show (style (project-tags project-name repo) | |
| 260 | + | project-name "-" footer))))) | |
| 261 | + | (_ (not-found request footer)))))))) | |