1. Peter Bex
  2. henrietta-cache


Peter Bex  committed ae10d0c

Implement zipfile-extraction

  • Participants
  • Parent commits b0c1749
  • Branches default

Comments (0)

Files changed (1)

File henrietta-cache.scm

View file
-;(module henrietta-cache ()
-(import chicken scheme)
 (use utils posix http-client matchable)
 (define (usage code)
   -c   -cache-dir LOCATION      put the egg cache in this directory
   -e   -egg-list  LOCATION      file containing the master list of available eggs
-  QUERYSTRING and REMOTEADDR default to the value of the `QUERY_STRING' 
+  QUERYSTRING and REMOTEADDR default to the value of the `QUERY_STRING'
 and `REMOTE_ADDR' environment variables, respectively.
              (when limit (set! limit (- limit (string-length data))))
              (loop (read-string (min (or limit bufsize) bufsize) in))))))
+(define (call-with-output-pipe* cmd proc)
+  (let ([p (open-output-pipe cmd)])
+    (proc p)
+    (unless (zero? (close-output-pipe p))
+      (error "Got an error while executing command " cmd))))
+(define (pipe-from-http uri cmd)
+  (call-with-input-request
+   uri #f (lambda (i) (call-with-output-pipe*
+                        cmd
+                        (lambda (o) (copy-port i o))))))
+(define dispatchers
+  `((targz . ,(lambda (uri cache-dir)
+                (pipe-from-http
+                 uri
+                 (sprintf "(cd ~A; gzcat | pax -r -s ',^[^/]*/,,')"
+                          (qs cache-dir)))))
+    (tarbz2 . ,(lambda (uri cache-dir)
+                 (pipe-from-http
+                  uri
+                  (sprintf "(cd ~A; bzcat | pax -r -s ',^[^/]*/,,')"
+                           (qs cache-dir)))))
+    (zip . ,(lambda (uri cache-dir)
+              (let ((tmpdir (create-temporary-directory))
+                    (tmp-zipfile (create-temporary-file)))
+                (call-with-input-request
+                 uri #f (lambda (i) (call-with-output-file
+                                        tmp-zipfile
+                                      (lambda (o) (copy-port i o)))))
+                (let* ((cmd (sprintf "unzip -d ~A -o -qq ~A" (qs tmpdir) (qs tmp-zipfile)))
+                       (status (system cmd)))
+                  (delete-file tmp-zipfile)
+                  (unless (zero? status)
+                    (system (sprintf "rm -rf ~A" (qs tmpdir)))
+                    (error "Got an error executing command" cmd)))
+                ;; Some people unzip to the current directory, some include the
+                ;; directory
+                (let* ((contents (directory tmpdir))
+                       (contents-dir (if (= 1 (length contents))
+                                         (make-pathname tmpdir (car contents))
+                                         tmpdir)))
+                  (rename-file contents-dir cache-dir)
+                  (system (sprintf "rm -rf ~A" (qs tmpdir)))))))))
 (define (download-all-release-files egg-name uris/releases uris)
   (let ((egg-cache-dir (make-pathname *cache-directory* (->string egg-name))))
-    (unless (directory? egg-cache-dir)
-      (create-directory egg-cache-dir #t))
     (for-each (lambda (uri/releases)
                 (and-let* ((uri-alias (car uri/releases))
                            (uri-info (alist-ref uri-alias uris))
                            (uri-template (cadr uri-info)))
                    (lambda (egg-release)
-                     (let ((cached-file (make-pathname egg-cache-dir
-                                                       egg-release
-                                                       (->string type))))
-                       (unless (file-exists? cached-file)
+                     (let ((cache-dir (make-pathname egg-cache-dir egg-release)))
+                       (unless (file-exists? cache-dir)
                          (let* ((patterns `((egg-name . ,egg-name)
                                             (egg-release . ,egg-release)
                                             (chicken-release . ,*chicken-release*)))
                                 (uri (replace-uri-patterns uri-template patterns)))
                            (printf "\tDownloading release ~A from ~A\n"
                                    egg-release uri)
-                           ;; Here we should dispatch on type to determine what to do!
-                           (call-with-input-request
-                            uri #f (lambda (i)
-                                     (call-with-output-file
-                                         cached-file
-                                       (lambda (o) (copy-port i o)))))))))
+                           (handle-exceptions exn
+                             (begin
+                               (system (sprintf "rm -rf ~A" cache-dir))
+                               (printf "Error downloading or extracting egg '~A' release ~A: "
+                                       egg-name egg-release)
+                               (print-error-message exn))
+                             (create-directory cache-dir #t)
+                             ((alist-ref type dispatchers eq? void) uri cache-dir))))))
                    (cdr uri/releases))))
     (if (null? args)
         (let ((arg (car args)))
-          (cond ((or (string=? arg "-help") 
+          (cond ((or (string=? arg "-help")
                      (string=? arg "-h")
                      (string=? arg "--help"))
                  (usage 0))
                 (else (loop (cdr args))))))))
 (main (command-line-arguments))