source: project/chicken/branches/hygienic/henrietta.scm @ 11978

Last change on this file since 11978 was 11978, checked in by felix winkelmann, 12 years ago

henrietta fixes

File size: 6.1 KB
Line 
1;;;; henrietta.scm - Server program (CGI) for serving eggs from a repository over HTTP
2;
3; Copyright (c) 2008, The Chicken Team
4; All rights reserved.
5;
6; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
7; conditions are met:
8;
9;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
10;     disclaimer.
11;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12;     disclaimer in the documentation and/or other materials provided with the distribution.
13;   Neither the name of the author nor the names of its contributors may be used to endorse or promote
14;     products derived from this software without specific prior written permission.
15;
16; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
17; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24; POSSIBILITY OF SUCH DAMAGE.
25
26
27(require-library setup-download regex extras utils ports srfi-1 posix)
28
29
30(module main ()
31
32  (import scheme chicken regex extras utils ports srfi-1 posix)
33  (import setup-utils setup-download)
34
35  (define *default-transport* 'svn)
36  (define *default-location* (current-directory))
37  (define *username* #f)
38  (define *password* #f)
39  (define *tests* #f)
40
41  (define (headers)
42    (print "Connection: close\r\nContent-type: text/plain\r\n\r\n"))
43
44  (define (fail msg . args)
45    (pp `(error ,msg ,@args))
46    (cleanup)
47    (exit 0))
48
49  (define (cleanup)
50    (and-let* ((tmpdir (temporary-directory)))
51      (fprintf (current-error-port) "removing temporary directory `~a'~%" tmpdir)
52      (remove-directory tmpdir)))
53
54  (define (test-file? path)
55    (string-match "(\\./)?tests(/.*)?" path))
56
57  (define (retrieve name version)
58    (let ((dir (handle-exceptions ex 
59                   (fail ((condition-property-accessor 'exn 'message) ex)
60                         ((condition-property-accessor 'exn 'arguments) ex))
61                 (retrieve-extension 
62                  name *default-transport* *default-location*
63                  version: version 
64                  quiet: #t 
65                  destination: #f
66                  tests: *tests*
67                  username: *username* 
68                  password: *password*))))
69      (unless dir 
70        (fail "no such extension or version" name version))
71      (let walk ((dir dir) (prefix "."))
72        (let ((files (directory dir)))
73          (for-each
74           (lambda (f)
75             (when (or *tests* (not (test-file? f)))
76               (let ((ff (string-append dir "/" f))
77                     (pf (string-append prefix "/" f)))
78                 (cond ((directory? ff)
79                        (print "\n#|--------------------|# \"" pf "/\" 0")
80                        (walk ff pf))
81                       (else
82                        (print "\n#|--------------------|# \"" pf "\" " (file-size ff))
83                        (display (read-all ff)))))))
84           files)))
85      (print "\n#!eof") ) )
86
87  (define (service)
88    (let ((qs (getenv "QUERY_STRING"))
89          (ra (getenv "REMOTE_ADDR")))
90      (fprintf (current-error-port) "~%========== serving request from ~a: ~s~%"
91               (or ra "<unknown>") qs)
92      (unless qs
93        (error "no QUERY_STRING set"))
94      (let ((m (string-match "[^?]+\\?(.+)" qs))
95            (egg #f)
96            (version #f))
97        (let loop ((qs (if m (cadr m) qs)))
98          (let* ((m (string-search-positions "^&?(\\w+)=([^&]+)" qs))
99                 (ms (and m (apply substring qs (cadr m))))
100                 (rest (and m (substring qs (cadar m)))))
101            (cond ((not m)
102                   (headers)            ; from here on use `fail'
103                   (cond (egg
104                          (retrieve egg version)
105                          (cleanup) )
106                         (else (fail "no extension name specified") ) ))
107                  ((string=? ms "version")
108                   (set! version (apply substring qs (caddr m)))
109                   (loop rest))
110                  ((string=? ms "name")
111                   (set! egg (apply substring qs (caddr m)))
112                   (loop rest))
113                  ((string=? ms "tests")
114                   (set! *tests* #t)
115                   (loop rest))
116                  (else
117                   (warning "unrecognized query option" ms)
118                   (loop rest))))))))
119 
120
121  (define (usage code)
122    (print #<#EOF
123usage: henrietta [OPTION ...]
124
125  -h   -help                    show this message
126  -l   -location LOCATION       install from given location (default: current directory)
127  -t   -transport TRANSPORT     use given transport instead of default (#{*default-transport*})
128       -username USER           set username for transports that require this
129       -password PASS           set password for transports that require this
130EOF
131);|
132    (exit code))
133
134  (define *short-options* '(#\h #\l #\t))
135
136  (define (main args)
137    (let loop ((args args))
138      (if (null? args)
139          (service)
140          (let ((arg (car args)))
141            (cond ((or (string=? arg "-help") 
142                       (string=? arg "-h")
143                       (string=? arg "--help"))
144                   (usage 0))
145                  ((or (string=? arg "-l") (string=? arg "-location"))
146                   (unless (pair? (cdr args)) (usage 1))
147                   (set! *default-location* (cadr args))
148                   (loop (cddr args)))
149                  ((or (string=? arg "-t") (string=? arg "-transport"))
150                   (unless (pair? (cdr args)) (usage 1))
151                   (set! *default-transport* (string->symbol (cadr args)))
152                   (loop (cddr args)))
153                  ((string=? "-username" arg)
154                   (unless (pair? (cdr args)) (usage 1))
155                   (set! *username* (cadr args))
156                   (loop (cddr args)))
157                  ((string=? "-password" arg)
158                   (unless (pair? (cdr args)) (usage 1))
159                   (set! *password* (cadr args))
160                   (loop (cddr args)))
161                  ((and (positive? (string-length arg))
162                        (char=? #\- (string-ref arg 0)))
163                   (if (> (string-length arg) 2)
164                       (let ((sos (string->list (substring arg 1))))
165                         (if (null? (lset-intersection eq? *short-options* sos))
166                             (loop (append (map (cut string #\- <>) sos) (cdr args)))
167                             (usage 1)))
168                       (usage 1)))
169                  (else (loop (cdr args))))))))
170
171  (main (command-line-arguments))
172 
173)
Note: See TracBrowser for help on using the repository browser.