Hello,
Here is another version of 'psyntax.library-manager.ss':
http://proteus.freeshell.org/_psyntax.library-manager-library-repositories.ss
This one takes a different approach. It introduces a
'library-repositories' parameter.
In the previous hack, each "library location" was assumed to be a set of
paths into the local filesystem. The 'library-repositories' is a bit
more abstract than that. I.e.:
(library-repositories
(list (standard-library-repository "/usr/local/share/ikarus")
(my-library-repository "/root/scheme-libraries")
(http-library-repository "http://crop-circles.info/scheme")
(dns-library-repository "scheme.crop-circles.info")
(sqlite-library-repository "/root/db/scheme-libraries")))
In particular, it's a list of procedures. Each procedure does:
library-name => resource
The resource is something that the library-loader should know how to
handle. For example, if the resource is simply a fully qualified path,
it does the usual thing. However, the resource might be something
complex like:
"sqlite:/var/scheme.db:a/b/c"
The 'standard-library-repository' acts like the current Ikarus default.
Let's try a real example.
Here's a library on a web server:
http://proteus.freeshell.org/test-remote/breatharian/breatharian.scm
Make sure there's nothing up my sleeve:
(import (breatharian))
Unhandled exception
Let's add a library repository for that remote location:
(library-repositories
(cons (http-library-repository "proteus.freeshell.org/test-remote")
(library-repositories)))
And try again:
(import (breatharian))
--21:47:02--
http://proteus.freeshell.org/test-remote/breatharian/breatharian.scm
=> `breatharian.scm'
Resolving proteus.freeshell.org... 192.94.73.7
Connecting to proteus.freeshell.org|192.94.73.7|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 95 [text/plain]
100%[====================================>] 95 --.--K/s
21:47:03 (7.91 MB/s) - `breatharian.scm' saved [95/95]
Bam!
(breatharian)
10
It works.
So what does 'http-library-repository' look like?
----------------------------------------------------------------------
(define (http-library-repository remote)
(let ( (cache (string-append "/tmp/" remote)) )
(if (not (file-exists? cache))
;; (make-directory cache)
(system
(string-append "mkdir -p " cache)))
(lambda (library-name)
(let ( (local-file
(string-append cache
"/"
(my-library-name->string library-name)
".scm"))
(remote-file
(string-append "http://" remote "/"
(my-library-name->string library-name)
".scm")) )
(if (file-exists? local-file)
local-file
(begin
(if (not (file-exists? (dirname local-file)))
(mkdir (dirname local-file)))
(current-directory (dirname local-file))
(let ((status (system
(string-append "wget " remote-file))))
(if (= status 0)
local-file
#f))))))))
----------------------------------------------------------------------
It uses these other procedures:
(define (mkdir path)
(system
(string-append "mkdir -p " path)))
(define (dirname path)
(let loop ( (i (- (string-length path) 1)) )
(if (char=? (string-ref path i) #\/)
(substring path 0 i)
(loop (- i 1)))))
(define (my-library-name->string name)
(let loop ((name name))
(let ((component (symbol->string (car name))))
(cond ((null? (cdr name))
(string-append component "/" component))
(else
(string-append component "/" (loop (cdr name))))))))
In this case, the 'http-library-repository' hands the library-loader a
resource it knows how to deal with; i.e. a path into the local
filesystem. In particular, a path into the library source cache that it
builds up under "/tmp".
Ed