152 lines
7.1 KiB
Text
152 lines
7.1 KiB
Text
|
|
(define-library (zilch lang go vfs)
|
||
|
|
(import
|
||
|
|
(scheme base) (scheme write) (scheme read) (scheme file) (scheme process-context) (scheme lazy) (scheme case-lambda)
|
||
|
|
(chicken file)
|
||
|
|
(zilch magic) (zilch file) (zilch zexpr)
|
||
|
|
(zilch nix drv) (zilch nix path) (zilch nixpkgs)
|
||
|
|
(json)
|
||
|
|
(chicken base) (chicken format) (chicken foreign)
|
||
|
|
(scheme char)
|
||
|
|
(srfi 4) (srfi 128) (srfi 133) (srfi 146) (srfi 152) (srfi 207)
|
||
|
|
(zilch lang go) (zilch lang go core) (zilch lang go stdlib) (zilch lang go sum) (zilch lang go fetch)
|
||
|
|
(chicken foreign))
|
||
|
|
|
||
|
|
(export vfs-from-dirhash vfs-from-directory filter-vfs filter-vfs-for-package-reading vfs-to-store)
|
||
|
|
|
||
|
|
(begin
|
||
|
|
(define (read-full-file port)
|
||
|
|
(define buf (make-bytevector 2048 0))
|
||
|
|
(call-with-port (open-output-bytevector)
|
||
|
|
(lambda (outport)
|
||
|
|
(do ((read-bytes 0 (read-bytevector! buf port))) ((eof-object? read-bytes) (get-output-bytevector outport))
|
||
|
|
(unless (eof-object? read-bytes) (write-bytevector buf outport 0 read-bytes))))))
|
||
|
|
|
||
|
|
(foreign-declare "#include \"dirhash_source.h\"")
|
||
|
|
|
||
|
|
(define dirhash-generator
|
||
|
|
(go-package-link
|
||
|
|
(go-package-compile "main"
|
||
|
|
(map go-stdlib-ref '("archive/zip" "crypto/sha256" "fmt" "io" "os" "sort"))
|
||
|
|
(list (cons "main.go" (zfile (foreign-value "dirhash_source" nonnull-c-string)))))))
|
||
|
|
|
||
|
|
(foreign-declare "#include \"unzip_one_source.h\"")
|
||
|
|
(define unpack-zip
|
||
|
|
(go-package-link
|
||
|
|
(go-package-compile "main"
|
||
|
|
(map go-stdlib-ref '("archive/zip" "io" "os"))
|
||
|
|
(list (cons "main.go" (zfile (foreign-value "unzip_one_source" nonnull-c-string)))))))
|
||
|
|
|
||
|
|
(define (rewrite-name name)
|
||
|
|
(define out "")
|
||
|
|
(string-for-each (lambda (ch)
|
||
|
|
(if (char-upper-case? ch) (set! out (string-append out (string #\! (char-downcase ch)))) (set! out (string-append out (string ch))))) name)
|
||
|
|
out)
|
||
|
|
|
||
|
|
(define (vfs-to-store vfs)
|
||
|
|
(define dirmap (mapping (make-default-comparator)))
|
||
|
|
(vector-for-each
|
||
|
|
(lambda (pair)
|
||
|
|
(define key (car pair))
|
||
|
|
(define separator (if (string=? key "/") 0 (string-index-right key (lambda (ch) (char=? ch #\/)) 0 (- (string-length key) 1))))
|
||
|
|
(unless (string=? key "/")
|
||
|
|
(let
|
||
|
|
((dirname (string-copy key 0 (+ 1 separator)))
|
||
|
|
(fname (string-copy key (+ 1 separator) (- (string-length key) 1))))
|
||
|
|
(set! dirmap (mapping-set! dirmap dirname (cons (cons fname key) (mapping-ref/default dirmap dirname '())))))))
|
||
|
|
vfs)
|
||
|
|
(define (translate-dir name)
|
||
|
|
(define files (vector-any (lambda (f) (and (string=? (car f) name) (cdr f))) vfs))
|
||
|
|
(define dirs (mapping-ref/default dirmap name '()))
|
||
|
|
(zdir (append
|
||
|
|
(map (lambda (kv) (cons (car kv) (zsymlink (cdr kv)))) (vector->list files))
|
||
|
|
(map (lambda (k) (cons (car k) (translate-dir (cdr k)))) dirs))))
|
||
|
|
(translate-dir "/"))
|
||
|
|
|
||
|
|
|
||
|
|
(define (fetch-dirhash-for-sum sum-line)
|
||
|
|
(when (go-sum-path sum-line) (error "go.sum line is invalid for fetch-dirhash-for-sum" sum-line))
|
||
|
|
(define url (string-append "https://proxy.golang.org/" (rewrite-name (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
|
||
|
|
(define known (fetch-with-known-url "module.zip" url))
|
||
|
|
(store-path-for-fod "module" "x86_64-linux" #~(#$dirhash-generator) #~(("src" . #$known)) "sha256" (go-sum-hash sum-line) #f))
|
||
|
|
|
||
|
|
(define (vfs-from-dirhash sum-line)
|
||
|
|
(define dirhash-file (fetch-dirhash-for-sum sum-line))
|
||
|
|
(define url (string-append "https://proxy.golang.org/" (rewrite-name (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
|
||
|
|
(define zip (fetch-with-known-url "module.zip" url))
|
||
|
|
(define lines '())
|
||
|
|
(define prefix-length (string-length (string-append (go-sum-module sum-line) "@" (go-sum-version sum-line) "/")))
|
||
|
|
(call-with-port (store-path-open dirhash-file)
|
||
|
|
(lambda (port)
|
||
|
|
(do ((line "" (read-line port)) (hash #f) (file #f))
|
||
|
|
((eof-object? line) #f)
|
||
|
|
(unless (string=? "" line)
|
||
|
|
(set! hash (hex-string->bytevector (string-copy line 0 64)))
|
||
|
|
(set! file (string-copy line 66))
|
||
|
|
(set! lines (cons (cons file hash) lines))))))
|
||
|
|
(define dirs '())
|
||
|
|
(for-each
|
||
|
|
(lambda (pair)
|
||
|
|
(define fpath (string-copy (car pair) prefix-length))
|
||
|
|
(define slashindex (string-index-right fpath (lambda (c) (char=? c #\/))))
|
||
|
|
(define dirname "/")
|
||
|
|
(define filename fpath)
|
||
|
|
(when slashindex
|
||
|
|
(set! dirname (string-append "/" (string-copy fpath 0 slashindex) "/"))
|
||
|
|
(set! filename (string-copy fpath (+ slashindex 1))))
|
||
|
|
|
||
|
|
(define dir (assoc dirname dirs))
|
||
|
|
(define file (store-path-for-fod "file" "x86_64-linux" #~(#$unpack-zip #$zip ,(car pair)) '() "sha256" (cdr pair) #f))
|
||
|
|
(unless dir
|
||
|
|
(set! dirs (cons (list dirname) dirs))
|
||
|
|
(set! dir (car dirs)))
|
||
|
|
|
||
|
|
; Skip files we know for sure won't be used.
|
||
|
|
(unless (or (string-contains dirname "/_") (string-contains dirname "/.") (string-contains dirname "/testdata/") (char=? #\. (string-ref filename 0)) (char=? #\_ (string-ref filename 0)))
|
||
|
|
(set-cdr! dir (cons (cons filename file) (cdr dir)))))
|
||
|
|
lines)
|
||
|
|
(list->vector (map (lambda (pair) (cons (car pair) (list->vector (cdr pair)))) dirs)))
|
||
|
|
|
||
|
|
(define (vfs-from-directory osdir)
|
||
|
|
(define iter-dir #f)
|
||
|
|
(define output '())
|
||
|
|
(set! iter-dir
|
||
|
|
(lambda (dirpath)
|
||
|
|
(define reldir (string-append osdir "/" dirpath))
|
||
|
|
(define files '())
|
||
|
|
(define contents (directory (string-append osdir dirpath)))
|
||
|
|
(for-each
|
||
|
|
(lambda (name)
|
||
|
|
(unless (string=? (string-copy name 0 1) ".")
|
||
|
|
(if (directory-exists? (string-append reldir "/" name))
|
||
|
|
(iter-dir (string-append dirpath "/" name))
|
||
|
|
(set! files (cons (cons name (zfile #~,(call-with-input-file (string-append reldir "/" name) read-full-file))) files)))))
|
||
|
|
contents)
|
||
|
|
(set! output (cons (cons (string-append dirpath "/") (list->vector files)) output))))
|
||
|
|
(iter-dir "")
|
||
|
|
(list->vector output))
|
||
|
|
|
||
|
|
(define (filter-vfs vfs filter)
|
||
|
|
(vector-map
|
||
|
|
(lambda (dir)
|
||
|
|
(cons (car dir)
|
||
|
|
(vector-map
|
||
|
|
(lambda (pair)
|
||
|
|
(if (filter (car dir) (car pair))
|
||
|
|
(cons (car pair) (cdr pair))
|
||
|
|
(cons (car pair) "/dev/null")))
|
||
|
|
(cdr dir))))
|
||
|
|
vfs))
|
||
|
|
|
||
|
|
; List extracted from go src/go/build/build.go.
|
||
|
|
(define good-extensions '("go" "c" "cc" "cpp" "cxx" "m" "h" "hh" "hpp" "hxx" "f" "F" "for" "f90" "s" "S" "sx" "swig" "swigcxx" "syso"))
|
||
|
|
(define (extract-extension name i)
|
||
|
|
(cond ((char=? (string-ref name i) #\.) (string-copy name (+ i 1)))
|
||
|
|
((= i 0) #f)
|
||
|
|
(else (extract-extension name (- i 1)))))
|
||
|
|
|
||
|
|
(define (filter-vfs-for-package-reading vfs)
|
||
|
|
(filter-vfs vfs
|
||
|
|
(lambda (dir fname)
|
||
|
|
(define extension (extract-extension fname (- (string-length fname) 1)))
|
||
|
|
(member extension good-extensions))))))
|