(zilch lang go): introduce proper vfs record

This should hopefully make the code a bit clearer, and is preparation
for Rust support.
This commit is contained in:
puck 2024-11-01 00:12:04 +00:00
parent 0c575ca0e4
commit fc8aea8fb4
5 changed files with 228 additions and 162 deletions

View file

@ -8,6 +8,7 @@
r7rs r7rs
json json
srfi-152 srfi-152
srfi-113
srfi-207 srfi-207
(callPackage ../../core {}) (callPackage ../../core {})

View file

@ -55,7 +55,7 @@
(set-cdr! loc (cons (cons (go-sum-version line) (delay (vfs-from-dirhash line))) (cdr loc)))))) (set-cdr! loc (cons (cons (go-sum-version line) (delay (vfs-from-dirhash line))) (cdr loc))))))
go-sum)) go-sum))
(define (add-modules-from-sum nvfs dir) (define (add-modules-from-sum nvfs dir)
(define sumfile (vector-get-kv-value "go.sum" (vector-get-kv-value dir nvfs))) (define sumfile (vfs-file-ref nvfs dir "go.sum"))
(when sumfile (when sumfile
(parse-sumfile (call-with-port (store-path-open sumfile) parse-go-sum-file)))) (parse-sumfile (call-with-port (store-path-open sumfile) parse-go-sum-file))))
@ -63,7 +63,7 @@
(fprintf (current-error-port) "Collecting required modules\n") (fprintf (current-error-port) "Collecting required modules\n")
(define (find-requires-from-mod vfs dir) (define (find-requires-from-mod vfs dir)
(define modfile (vector-get-kv-value "go.mod" (vector-get-kv-value dir vfs))) (define modfile (vfs-file-ref vfs dir "go.mod"))
(define pathname #f) (define pathname #f)
(when modfile (when modfile
(let* (let*
@ -88,8 +88,8 @@
pathname) pathname)
(define root-path-name #f) (define root-path-name #f)
(define (handle-vfs nvfs) (define (handle-vfs nvfs)
(add-modules-from-sum nvfs "/") (add-modules-from-sum nvfs "")
(find-requires-from-mod nvfs "/")) (find-requires-from-mod nvfs ""))
(for-each (for-each
(lambda (vfs) (lambda (vfs)
@ -145,27 +145,28 @@
(define go-files (cdr (assoc "goFiles" pairs))) (define go-files (cdr (assoc "goFiles" pairs)))
(define s-files (if (and (assoc "sFiles" pairs) (list? (cdr (assoc "sFiles" pairs)))) (cdr (assoc "sFiles" pairs)) '())) (define s-files (if (and (assoc "sFiles" pairs) (list? (cdr (assoc "sFiles" pairs)))) (cdr (assoc "sFiles" pairs)) '()))
(define imports (cdr (assoc "imports" pairs))) (define imports (cdr (assoc "imports" pairs)))
; format: ((pattern . (fname file dir))) ; format: ((pattern . (file-name dir file)))
(define embed-vectors (cdr (assoc "embeds" pairs))) (define embed-vectors (cdr (assoc "embeds" pairs)))
(define embeds (if (vector? embed-vectors) (vector->list embed-vectors) '())) (define embeds (if (vector? embed-vectors) (vector->list embed-vectors) '()))
(define embed-filenames '()) (define embed-filenames '())
; Creates a list of (pattern-text . (filename-1 filename-2 ...)).
(define embed-patterns (map (lambda (pattern) (cons (car pattern) (if (list? (cdr pattern)) (map car (cdr pattern)) '()))) embeds)) (define embed-patterns (map (lambda (pattern) (cons (car pattern) (if (list? (cdr pattern)) (map car (cdr pattern)) '()))) embeds))
(for-each (for-each
(lambda (pattern) (lambda (pattern)
(when (list? pattern) (when (list? pattern)
(for-each (for-each
(lambda (fname) (lambda (entry)
(define new-fname (cadr fname)) (define target-file-name (list-ref entry 2))
(if (string=? "//" new-fname) (set! new-fname "/")) (define target-directory (list-ref entry 1))
(define dir (vector-get-kv-value new-fname vfs)) (define file-obj (vfs-file-ref vfs target-directory target-file-name))
(define file-obj (vector-get-kv-value (car (cddr fname)) dir)) (unless (assoc (car entry) embed-filenames) (set! embed-filenames (cons (cons (car entry) file-obj) embed-filenames))))
(unless (assoc (car fname) embed-filenames) (set! embed-filenames (cons (cons (car fname) file-obj) embed-filenames))))
(cdr pattern)))) (cdr pattern))))
embeds) embeds)
(define vfsdir (vector-get-kv-value last-part vfs))
(let (let
((collected-files (map (lambda (name) (cons name (vector-get-kv-value name vfsdir))) go-files)) ((collected-files (map (lambda (name) (cons name (vfs-file-ref vfs last-part name))) go-files))
(collected-assembly-files (map (lambda (name) (cons name (vector-get-kv-value name vfsdir))) s-files)) (collected-assembly-files (map (lambda (name) (cons name (vfs-file-ref vfs last-part name))) s-files))
(collected-assembly-includes (if (= (length s-files) 0) '() #~,(string-append #$(force headers) last-part))) (collected-assembly-includes (if (= (length s-files) 0) '() #~,(string-append #$(force headers) last-part)))
(collected-imports (map (lambda (name) (if (is-builtin name) (go-stdlib-ref name) (find-package name))) (collected-imports (map (lambda (name) (if (is-builtin name) (go-stdlib-ref name) (find-package name)))
(filter (lambda (name) (not (member name '("builtin" "unsafe")))) imports)))) (filter (lambda (name) (not (member name '("builtin" "unsafe")))) imports))))
@ -174,30 +175,27 @@
(define packages (mapping (make-default-comparator))) (define packages (mapping (make-default-comparator)))
(define (process-packages-for-module root-path vfs) (define (process-packages-for-module root-path vfs)
(define (dir-has-valid-contents contents) (define (list-any filter entries)
(vector-any (cond
(lambda (entry) ((eq? entries '()) #f)
(or ((filter (car entries)) #t)
(eq? (car entry) "go.mod") (else (list-any filter (cdr entries)))))
(string-suffix? ".go" (car entry))))
contents))
(define module-packages (define module-packages
(find-packages-inside-vfs (find-packages-inside-vfs
(vector-map (vfs-dir-filter-all
(lambda (pair) (lambda (dirname)
(cons (list-any
(car pair) (lambda (entry)
(if (dir-has-valid-contents (cdr pair)) (or (eq? (car entry) "go.mod")
(cdr pair) (string-suffix? ".go" (car entry))))
(vector-map (lambda (pair) (cons (car pair) "/dev/null")) (cdr pair))))) (vfs-dir-files vfs dirname)))
vfs))) vfs)))
(define headers (delay (vfs-to-store (filter-vfs vfs (lambda (dir fname) (string-suffix? ".h" fname)))))) (define headers (delay (vfs-to-store (vfs-dir-filter vfs (lambda (dir fname contents) (string-suffix? ".h" fname))))))
(vector-for-each (vector-for-each
(lambda (pair) (lambda (pair)
(define full-path (string-append root-path (car pair))) (define full-path (string-append root-path (if (string=? (car pair) "") "" "/") (car pair)))
(set! full-path (string-copy full-path 0 (- (string-length full-path) 1)))
(define pairs (vector->list (cdr pair))) (define pairs (vector->list (cdr pair)))
(set! packages (mapping-set! packages full-path (delay (process-package vfs (car pair) full-path pairs headers))))) (set! packages (mapping-set! packages full-path (delay (process-package vfs (car pair) full-path pairs headers)))))
module-packages)) module-packages))

View file

@ -25,7 +25,7 @@
#~,(call-with-port #~,(call-with-port
(open-output-bytevector) (open-output-bytevector)
(lambda (bv) (lambda (bv)
(json-write (vector (cons "GOARCH" (%goarch)) (cons "GOOS" "linux") (cons "files" #$(filter-vfs-for-package-reading vfs))) bv) (json-write (vector (cons "GOARCH" (%goarch)) (cons "GOOS" "linux") (cons "files" #$(vfs-to-json (vfs-filter-for-go-package vfs)))) bv)
(get-output-bytevector bv)))) (get-output-bytevector bv))))
(define input-file (zfile input)) (define input-file (zfile input))
(define store-path (cdar (store-path-for-ca-drv* "find-packages" "x86_64-linux" #~(#$go-import-parser #$input-file) '() '("out")))) (define store-path (cdar (store-path-for-ca-drv* "find-packages" "x86_64-linux" #~(#$go-import-parser #$input-file) '() '("out"))))

View file

@ -14,13 +14,60 @@
(json) (json)
(chicken base) (chicken format) (chicken foreign) (chicken base) (chicken format) (chicken foreign)
(scheme char) (scheme char)
(srfi 4) (srfi 128) (srfi 133) (srfi 146) (srfi 152) (srfi 207) (srfi 4) (srfi 113) (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) (zilch lang go) (zilch lang go core) (zilch lang go stdlib) (zilch lang go sum) (zilch lang go fetch)
(chicken foreign)) (chicken foreign))
(export vfs-from-dirhash vfs-from-directory filter-vfs filter-vfs-for-package-reading vfs-to-store) (export vfs? vfs-dir-files vfs-file-ref vfs-dir-filter vfs-dir-filter-all vfs-from-dirhash vfs-from-directory vfs-filter-for-go-package vfs-to-store vfs-to-json)
(begin (begin
;; `contents` is a mapping whose keys are a pair (dir . filename) to file contents (e.g. zfile, or store path).
;; The file contents may be the symbol 'directory to indicate there's a directory.
;;
;; The root directory is specified by `dir` being an empty string. There are no trailing or leading slashes.
(define-record-type <vfs>
(make-vfs contents)
vfs?
(contents vfs-contents))
(define (vfs-dir-files vfs dir)
(mapping-map->list
(lambda (k v) (cons (cdr k) v))
(mapping-filter
(lambda (key val)
(and (not (eq? val 'directory)) (string=? (car key) dir)))
(vfs-contents vfs))))
(define (vfs-file-ref vfs dirname filename)
(mapping-ref/default (vfs-contents vfs) (cons dirname filename) #f))
;; Calls the filter with the dir, filename, and contents, for each file.
;; If filter returns #f, the file in the vfs will be replaced by /dev/null.
(define (vfs-dir-filter vfs filter)
(make-vfs
(mapping-map/monotone
(lambda (key val)
(if (or (eq? val 'directory) (filter (car key) (cdr key) val)) (values key val) (values key "/dev/null")))
(make-default-comparator)
(vfs-contents vfs))))
;; Calls the filter for each directory. If the filter returns #f, the directory's files are replaced with `/dev/null`.
(define (vfs-dir-filter-all filter vfs)
(define to-filter-out (set (make-default-comparator)))
(mapping-for-each
(lambda (key val)
(when (and (eq? val 'directory) (not (filter (string-append (car key) "/" (cdr key)))))
(set! to-filter-out (set-adjoin! to-filter-out (string-append (car key) "/" (cdr key))))))
(vfs-contents vfs))
(define (is-filtered dirname)
(set-any? (lambda (v) (string=? v dirname)) to-filter-out))
(make-vfs
(mapping-map/monotone
(lambda (key val)
(if (or (eq? val 'directory) (not (is-filtered (car key)))) (values key val) (values key "/dev/null")))
(make-default-comparator)
(vfs-contents vfs))))
(define (read-full-file port) (define (read-full-file port)
(define buf (make-bytevector 2048 0)) (define buf (make-bytevector 2048 0))
(call-with-port (open-output-bytevector) (call-with-port (open-output-bytevector)
@ -43,7 +90,7 @@
(map go-stdlib-ref '("archive/zip" "io" "os")) (map go-stdlib-ref '("archive/zip" "io" "os"))
(list (cons "main.go" (zfile (foreign-value "unzip_one_source" nonnull-c-string))))))) (list (cons "main.go" (zfile (foreign-value "unzip_one_source" nonnull-c-string)))))))
(define (rewrite-name name) (define (rewrite-go-package-name-for-url name)
(define out "") (define out "")
(string-for-each (lambda (ch) (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) (if (char-upper-case? ch) (set! out (string-append out (string #\! (char-downcase ch)))) (set! out (string-append out (string ch))))) name)
@ -53,30 +100,31 @@
;; returning a zdir describing the root directory. ;; returning a zdir describing the root directory.
(define (vfs-to-store vfs) (define (vfs-to-store vfs)
(define dirmap (mapping (make-default-comparator))) (define dirmap (mapping (make-default-comparator)))
(vector-for-each (mapping-for-each
(lambda (pair) (lambda (k contents)
(define key (car pair)) (define dir (car k))
(define separator (if (string=? key "/") 0 (string-index-right key (lambda (ch) (char=? ch #\/)) 0 (- (string-length key) 1)))) (define fname (cdr k))
(unless (string=? key "/") (unless (eq? contents 'directory)
(let (set! dirmap (mapping-update!/default dirmap dir (lambda (v) (cons (cons fname (zsymlink contents)) v)) '()))))
((dirname (string-copy key 0 (+ 1 separator))) (vfs-contents vfs))
(fname (string-copy key (+ 1 separator) (- (string-length key) 1)))) (mapping-for-each
(set! dirmap (mapping-set! dirmap dirname (cons (cons fname key) (mapping-ref/default dirmap dirname '()))))))) (lambda (k contents)
vfs) (define dir (car k))
(define (translate-dir name) (define fname (cdr k))
(define files (vector-any (lambda (f) (and (string=? (car f) name) (cdr f))) vfs)) (when (eq? contents 'directory)
(define dirs (mapping-ref/default dirmap name '())) (let*
(zdir (append ((name (string-append dir "/" fname))
(map (lambda (kv) (cons (car kv) (zsymlink (cdr kv)))) (vector->list files)) (dir (mapping-ref dirmap name)))
(map (lambda (k) (cons (car k) (translate-dir (cdr k)))) dirs)))) (set! dirmap (mapping-update!/default dirmap dir (lambda (v) (cons (cons fname (zdir dir)) v)) '())))))
(translate-dir "/")) (vfs-contents vfs))
(zdir (mapping-ref/default dirmap "" '())))
;; Reads a dirhash from a `go.sum` line. This prefetches the module from ;; Reads a dirhash from a `go.sum` line. This prefetches the module from
;; the go module proxy, and then generates the dirhash without unpacking ;; the go module proxy, and then generates the dirhash without unpacking
;; said module file. ;; said module file.
(define (fetch-dirhash-for-sum sum-line) (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)) (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 url (string-append "https://proxy.golang.org/" (rewrite-go-package-name-for-url (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
(define known (fetch-with-known-url "module.zip" url)) (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)) (store-path-for-fod "module" "x86_64-linux" #~(#$dirhash-generator) #~(("src" . #$known)) "sha256" (go-sum-hash sum-line) #f))
@ -84,7 +132,7 @@
;; line. ;; line.
(define (vfs-from-dirhash sum-line) (define (vfs-from-dirhash sum-line)
(define dirhash-file (fetch-dirhash-for-sum 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 url (string-append "https://proxy.golang.org/" (rewrite-go-package-name-for-url (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
(define zip (fetch-with-known-url "module.zip" url)) (define zip (fetch-with-known-url "module.zip" url))
(define lines '()) (define lines '())
(define prefix-length (string-length (string-append (go-sum-module sum-line) "@" (go-sum-version sum-line) "/"))) (define prefix-length (string-length (string-append (go-sum-module sum-line) "@" (go-sum-version sum-line) "/")))
@ -96,62 +144,53 @@
(set! hash (hex-string->bytevector (string-copy line 0 64))) (set! hash (hex-string->bytevector (string-copy line 0 64)))
(set! file (string-copy line 66)) (set! file (string-copy line 66))
(set! lines (cons (cons file hash) lines)))))) (set! lines (cons (cons file hash) lines))))))
(define dirs '()) (define output (mapping (make-default-comparator)))
(for-each (for-each
; (path . hash)
(lambda (pair) (lambda (pair)
(define fpath (string-copy (car pair) prefix-length)) (define file-path (string-copy (car pair) prefix-length))
(define slashindex (string-index-right fpath (lambda (c) (char=? c #\/)))) (define hash (cdr pair))
(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 last-slash (string-index-right file-path (lambda (c) (char=? c #\/))))
(define file (store-path-for-fod "file" "x86_64-linux" #~(#$unpack-zip #$zip ,(car pair)) '() "sha256" (cdr pair) #f)) (define dirname "")
(unless dir (define filename file-path)
(set! dirs (cons (list dirname) dirs)) (when last-slash
(set! dir (car dirs))) (set! dirname (string-copy file-path 0 last-slash))
(set! filename (string-copy file-path (+ last-slash 1))))
; Record directory name in the parent directory.
(unless last-slash
(let ((second-to-last-slash (string-index-right dirname (lambda (c) (char=? c #\/)))))
(if second-to-last-slash
(set! output (mapping-set! output (cons (string-copy dirname 0 second-to-last-slash) (string-copy dirname (+ second-to-last-slash 1))) 'directory))
(unless (string=? dirname "") (set! output (mapping-set! output (cons "" dirname) 'directory))))))
(define file (store-path-for-fod "file" "x86_64-linux" #~(#$unpack-zip #$zip ,(car pair)) '() "sha256" hash #f))
; Skip files we know for sure won't be used. ; Skip files we know for sure won't be used.
; TODO(puck): this should be moved to vfs-filter-for-go-package?
(unless (or (string-contains dirname "/_") (string-contains dirname "/.") (string-contains dirname "/testdata/") (char=? #\. (string-ref filename 0)) (char=? #\_ (string-ref filename 0))) (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))))) (set! output (mapping-set! output (cons dirname filename) file))))
lines) lines)
(list->vector (map (lambda (pair) (cons (car pair) (list->vector (cdr pair)))) dirs))) (make-vfs output))
;; Generates a full VFS structure from an on-disk directory. ;; Generates a full VFS structure from an on-disk directory.
(define (vfs-from-directory osdir) (define (vfs-from-directory osdir)
(define iter-dir #f) (define out (mapping (make-default-comparator)))
(define output '()) (define (iter-dir dirpath)
(set! iter-dir
(lambda (dirpath)
(define reldir (string-append osdir "/" dirpath)) (define reldir (string-append osdir "/" dirpath))
(define files '()) (define contents (directory reldir))
(define contents (directory (string-append osdir dirpath)))
(for-each (for-each
(lambda (name) (lambda (name)
(unless (string=? (string-copy name 0 1) ".") (unless (string=? (string-copy name 0 1) ".")
(if (directory-exists? (string-append reldir "/" name)) (if (directory-exists? (string-append reldir "/" name))
(iter-dir (string-append dirpath "/" name)) (begin
(set! files (cons (cons name (zfile #~,(call-with-input-file (string-append reldir "/" name) read-full-file))) files))))) (iter-dir (if (string=? dirpath "") name (string-append dirpath "/" name)))
contents) (set! out (mapping-set! out (cons dirpath name) 'directory)))
(set! output (cons (cons (string-append dirpath "/") (list->vector files)) output)))) (set! out (mapping-set! out (cons dirpath name) (zfile #~,(call-with-input-file (string-append reldir "/" name) read-full-file)))))))
contents))
(iter-dir "") (iter-dir "")
(list->vector output)) (make-vfs out))
;; Calls `filter` for each file in the virtual filesystem, replacing its
;; contents with an empty file if `filter` returns false.
(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. ;; 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 good-extensions '("go" "c" "cc" "cpp" "cxx" "m" "h" "hh" "hpp" "hxx" "f" "F" "for" "f90" "s" "S" "sx" "swig" "swigcxx" "syso"))
@ -162,8 +201,13 @@
;; Returns a VFS, filtered down to only contain the contents of files that ;; Returns a VFS, filtered down to only contain the contents of files that
;; will be read during the processing of Go packages. ;; will be read during the processing of Go packages.
(define (filter-vfs-for-package-reading vfs) (define (vfs-filter-for-go-package vfs)
(filter-vfs vfs (vfs-dir-filter vfs
(lambda (dir fname) (lambda (dir fname contents)
(define extension (extract-extension fname (- (string-length fname) 1))) (define extension (extract-extension fname (- (string-length fname) 1)))
(member extension good-extensions)))))) (member extension good-extensions))))
(define (vfs-to-json vfs)
(mapping-map->list
(lambda (k v) (list (car k) (cdr k) (if (eq? v 'directory) "" v)))
(vfs-contents vfs)))))

View file

@ -52,8 +52,8 @@ func (s *DirStat) Sys() any {
} }
type Input struct { type Input struct {
// directory -> filename -> path // list of [directory, filename, target path] (target path is empty, if directory marker)
Files map[string]map[string]string `json:"files"` Files [][3]string `json:"files"`
GOARCH string `json:"GOARCH"` GOARCH string `json:"GOARCH"`
GOOS string `json:"GOOS"` GOOS string `json:"GOOS"`
} }
@ -66,6 +66,11 @@ type Output struct {
Embeds map[string][][]string `json:"embeds"` Embeds map[string][][]string `json:"embeds"`
} }
type FileOrDir struct {
Directory []string
File string
}
func main() { func main() {
inputFile, err := os.Open(os.Args[1]) inputFile, err := os.Open(os.Args[1])
if err != nil { if err != nil {
@ -77,6 +82,37 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
files := make(map[string]*FileOrDir)
for _, file := range input.Files {
directory := file[0]
filename := file[1]
contents := file[2]
dirslash := directory
if directory != "" {
dirslash = directory + "/"
}
if contents == "" {
_, ok := files[dirslash+filename]
if !ok {
files[dirslash+filename] = &FileOrDir{}
}
} else {
files[dirslash+filename] = &FileOrDir{File: contents}
}
parent, ok := files[directory]
if !ok {
parent = &FileOrDir{}
files[directory] = parent
}
parent.Directory = append(parent.Directory, dirslash+filename)
}
ctx := build.Context{ ctx := build.Context{
GOARCH: input.GOARCH, GOARCH: input.GOARCH,
GOOS: input.GOOS, GOOS: input.GOOS,
@ -89,40 +125,26 @@ func main() {
return nil, fs.ErrNotExist return nil, fs.ErrNotExist
} }
dir = path.Clean(dir[5:]) dir = path.Clean(dir[5:])[1:]
if dir == "." {
dir = "/"
}
if !strings.HasSuffix(dir, "/") { contents, ok := files[dir]
dir += "/"
}
dircontents, ok := input.Files[dir]
if !ok { if !ok {
return nil, fs.ErrNotExist return nil, fs.ErrNotExist
} }
infos := make([]fs.FileInfo, len(dircontents)) infos := make([]fs.FileInfo, len(contents.Directory))
i := 0 for i, filename := range contents.Directory {
for name, file := range dircontents { file := files[filename]
stat, err := os.Stat(file) if file.File != "" {
stat, err := os.Stat(file.File)
if err != nil { if err != nil {
return nil, err return nil, err
} }
infos[i] = &WrappedStat{FileInfo: stat, newName: name} infos[i] = &WrappedStat{FileInfo: stat, newName: path.Base(filename)}
i = i + 1 } else {
} infos[i] = &DirStat{path.Base(filename)}
for key := range input.Files {
if path.Dir(key) == dir {
base := path.Base(key)
if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" {
continue
}
infos = append(infos, &DirStat{base})
} }
} }
@ -136,16 +158,13 @@ func main() {
return nil, fs.ErrNotExist return nil, fs.ErrNotExist
} }
pth = path.Clean(pth[5:]) pth = path.Clean(pth[5:])[1:]
dirname, fname := path.Split(pth) fmt.Printf("-> OpenFile(%q)\n", pth)
if dirname == "." { fil := files[pth]
dirname = "/"
}
dir := input.Files[dirname]
data, err := os.Open(dir[fname]) data, err := os.Open(fil.File)
if err != nil { if err != nil {
return data, fmt.Errorf("OpenFile(%q; %q[%q]; %q): %w", opth, dirname, fname, dir[fname], err) return data, fmt.Errorf("OpenFile(%q; %q): %w", opth, pth, err)
} }
return data, err return data, err
}, },
@ -156,18 +175,11 @@ func main() {
return false return false
} }
dir = path.Clean(dir[5:]) dir = path.Clean(dir[5:])[1:]
if dir == "." {
dir = "/"
}
if !strings.HasSuffix(dir, "/") { contents, ok := files[dir]
dir += "/" fmt.Printf("IsDir -> %q, %v, %v\n", dir, contents, ok)
} return ok && contents.File == ""
_, ok := input.Files[dir]
fmt.Printf("IsDir -> %q, %v\n", dir, ok)
return ok
}, },
HasSubdir: func(root, dir string) (rel string, ok bool) { HasSubdir: func(root, dir string) (rel string, ok bool) {
@ -179,17 +191,21 @@ func main() {
} }
var filenames []string var filenames []string
for dirname, files := range input.Files { for _, filedata := range input.Files {
for filename := range files { if filedata[2] != "" {
filenames = append(filenames, filepath.Join(dirname, filename)) filenames = append(filenames, filepath.Join(filedata[0], filedata[1]))
} }
} }
files := make(map[string]Output) outfiles := make(map[string]Output)
for dir, filelist := range files {
if filelist.File != "" {
continue
}
for dir, filelist := range input.Files {
isGo := false isGo := false
for file := range filelist { for _, file := range filelist.Directory {
if strings.HasSuffix(file, ".go") { if strings.HasSuffix(file, ".go") {
isGo = true isGo = true
break break
@ -203,13 +219,16 @@ func main() {
} }
base := path.Base(dir) base := path.Base(dir)
if base == "." {
base = ""
}
if !isGo || strings.HasPrefix(base, "_") || strings.HasPrefix(base, ".") || base == "testdata" { if !isGo || strings.HasPrefix(base, "_") || strings.HasPrefix(base, ".") || base == "testdata" {
fmt.Printf(" skipping (not go)\n") fmt.Printf(" skipping (not go)\n")
continue continue
} }
pkg, err := ctx.Import(".", path.Clean("/code"+dir), 0) pkg, err := ctx.Import(".", path.Clean("/code/"+dir), 0)
if err != nil { if err != nil {
if _, ok := err.(*build.NoGoError); ok { if _, ok := err.(*build.NoGoError); ok {
continue continue
@ -267,13 +286,17 @@ func main() {
sort.Strings(matchedFiles) sort.Strings(matchedFiles)
var split [][]string var split [][]string
for _, match := range matchedFiles { for _, match := range matchedFiles {
split = append(split, []string{match[len(dir):], filepath.Dir(match) + "/", filepath.Base(match)}) dirname := filepath.Dir(match)
if dirname == "." {
dirname = ""
}
split = append(split, []string{match[len(dir)+1:], dirname, filepath.Base(match)})
} }
out.Embeds[pattern] = split out.Embeds[pattern] = split
} }
files[dir] = out outfiles[dir] = out
} }
out, err := os.OpenFile(os.Getenv("out"), os.O_CREATE|os.O_RDWR, 0666) out, err := os.OpenFile(os.Getenv("out"), os.O_CREATE|os.O_RDWR, 0666)
@ -281,7 +304,7 @@ func main() {
panic(err) panic(err)
} }
if err := json.NewEncoder(out).Encode(files); err != nil { if err := json.NewEncoder(out).Encode(outfiles); err != nil {
panic(err) panic(err)
} }