dbf0b1727d5ea5d307222fb4bc447636f1bde9da
[scratchy.git] / examples / browse-git.scm
1 ;; Script to browse locally-hosted URLs
2 ;;
3 ;; To use, replace the strings git-base-url and git-base-dir
4 ;; with the values appropriate to your system.  Your git
5 ;; repository REPO should then be reachable at the selector
6 ;; browse-git.scm|REPO.
7 ;;
8 ;; You may optionally include a file named project-description
9 ;; in each repository, which will be displayed at the top
10 ;; of the page when the repository tree is served.
11
12 (lambda (repo . args)
13   (let ((branch (if (< (length args) 1) "master" (list-ref args 0)))
14         (path (if (< (length args) 2) "." (list-ref args 1)))
15         (type-str (if (< (length args) 3) "tree" (list-ref args 2))))
16
17     (import (chicken string)
18             (chicken process)
19             (chicken io)
20             (chicken pathname)
21             (chicken file)
22             srfi-13)
23
24     (define git-base-url "git://MY.GIT.SERVER/")
25     (define git-base-dir "/path/to/git/repositories/")
26
27
28     (define (git . args)
29       (let ((repo-pathname (make-pathname git-base-dir repo)))
30         (if (not (string-prefix? git-base-dir (normalize-pathname repo-pathname)))
31             (error "Invalid git repository."))
32         (with-current-working-directory
33          repo-pathname
34          (lambda ()
35            (let-values (((in-port out-port id) (process "git" args)))
36              (let ((result (read-lines in-port)))
37                (close-input-port in-port)
38                (close-output-port out-port)
39                result))))))
40
41     (define (serve-tree)
42       (let ((entries (git "ls-tree" branch path))
43             (references (git "show-ref" "--heads")))
44         (append
45          (list (conc "Git repository " git-base-url repo)
46                "")
47          (let ((descr-file (make-pathname git-base-dir
48                                           (make-pathname repo "project-description"))))
49            (if (file-exists? descr-file)
50                (list "----= Description =----"
51                      (with-input-from-file descr-file read-string)
52                      "")
53                '()))
54          (list "-----= Branches =-----")
55          (map (lambda (ref)
56                 (let ((refname (caddr (string-split ref "/"))))
57                   (list
58                    1
59                    (conc (if (equal? branch refname) "*" "")
60                          refname)
61                    (conc "browse-git.scm|" repo "|" refname "|" path "|tree"))))
62               references)
63          (list ""
64                (conc "-----= Files [" path "] =-----"))
65          (map (lambda (entry)
66                 (let* ((l (string-split entry "\t"))
67                        (type (string->symbol (cadr (string-split (car l) " "))))
68                        (file-path (cadr l))
69                        (file (conc (pathname-file file-path)
70                                    (if (pathname-extension file-path)
71                                        (conc "." (pathname-extension file-path))
72                                        ""))))
73                   (list (if (eq? type 'tree) 1 0)
74                         file
75                         (conc "browse-git.scm|" repo "|" branch "|"
76                               file-path
77                               (if (eq? type 'tree) "/" "")
78                               "|" type))))
79               entries))))
80
81     (define (serve-blob)
82       (for-each
83        (lambda (line)
84          (print line "\r"))
85        (git "cat-file" "blob" (conc branch ":" path)))
86       (print ".\r"))
87
88     (let ((type (string->symbol type-str)))
89       (case type
90         ((tree) (serve-tree))
91         ((blob) (serve-blob))
92         (else
93          (error "Unsupported git object."))))))