Refactor: Move dfs to its own function so that we can use let*.

This commit is contained in:
zainab-ali 2023-01-11 18:31:08 +00:00
parent 898440d4f5
commit b9f2df85ef

View File

@ -2,6 +2,7 @@
(require json) (require json)
(require racket/file) (require racket/file)
(require racket/function)
(require racket/match) (require racket/match)
(require racket/list) (require racket/list)
(require racket/set) (require racket/set)
@ -16,134 +17,135 @@
;; that we traverse foo-lib, and that subsequently generating the ;; that we traverse foo-lib, and that subsequently generating the
;; foo-lib dream-lock requires repeating the same traversal of foo-lib. How can this be avoided? ;; foo-lib dream-lock requires repeating the same traversal of foo-lib. How can this be avoided?
;; TODO: no effort is made to handle cycles right now
(define (dfs graph u dependency-subgraph)
(if (hash-has-key? dependency-subgraph u)
dependency-subgraph
(let ([destinations (hash-ref graph u)])
(foldl (curry dfs graph)
(hash-set dependency-subgraph u destinations)
destinations))))
(define (generate-dream-lock pkgs-all-path) (define (generate-dream-lock pkgs-all-path)
(letrec ([src-path (getenv "RACKET_SOURCE")] (let* ([src-path (getenv "RACKET_SOURCE")]
[rel-path (getenv "RACKET_RELPATH")] [rel-path (getenv "RACKET_RELPATH")]
[package-path (simplify-path (cleanse-path (build-path src-path (if (string=? rel-path "") [package-path (simplify-path (cleanse-path (build-path src-path (if (string=? rel-path "")
'same 'same
rel-path))))] rel-path))))]
[parent-path (simplify-path (cleanse-path (build-path package-path 'up)))] [parent-path (simplify-path (cleanse-path (build-path package-path 'up)))]
[package-name (if (string=? rel-path "") [package-name (if (string=? rel-path "")
(getenv "RACKET_PKG_MAYBE_NAME") (getenv "RACKET_PKG_MAYBE_NAME")
(path->string (path->string
(match/values (split-path package-path) (match/values (split-path package-path)
((_base subdir _must-be-dir?) subdir))))] ((_base subdir _must-be-dir?) subdir))))]
[pkgs-all (with-input-from-file pkgs-all-path read)] [pkgs-all (with-input-from-file pkgs-all-path read)]
[pkg-in-stdlib? (lambda (pkg-name) [pkg-in-stdlib? (lambda (pkg-name)
(or ;; Some people add racket itself as a dependency for some reason (or ;; Some people add racket itself as a dependency for some reason
(string=? pkg-name "racket") (string=? pkg-name "racket")
(ormap (lambda (tag) (ormap (lambda (tag)
;; XXX: would prefer to use memq, but tag is mutable for some reason ;; XXX: would prefer to use memq, but tag is mutable for some reason
(member tag '("main-distribution" "main-tests"))) (member tag '("main-distribution" "main-tests")))
(hash-ref (hash-ref pkgs-all pkg-name) 'tags))))] (hash-ref (hash-ref pkgs-all pkg-name) 'tags))))]
[dep-alist-from-catalog (hash-map pkgs-all [dep-alist-from-catalog (hash-map pkgs-all
(match-lambda** (match-lambda**
[(name (hash-table ('dependencies dependencies))) [(name (hash-table ('dependencies dependencies)))
(let ([external-deps (filter-not pkg-in-stdlib? dependencies)]) (let ([external-deps (filter-not pkg-in-stdlib? dependencies)])
(cons name external-deps))]))] (cons name external-deps))]))]
[compute-overridden-dep-lists [compute-overridden-dep-lists
(lambda (name dir) (lambda (name dir)
(let ([info-procedure (get-info/full dir)]) (let ([info-procedure (get-info/full dir)])
(and info-procedure (and info-procedure
(cons name (cons name
(remove-duplicates (remove-duplicates
(filter-not pkg-in-stdlib? (filter-not pkg-in-stdlib?
(map (match-lambda (map (match-lambda
[(or (cons pkg-name _) pkg-name) [(or (cons pkg-name _) pkg-name)
pkg-name]) pkg-name])
(append (with-handlers ([exn:fail? (lambda (_) '())]) (append (with-handlers ([exn:fail? (lambda (_) '())])
(info-procedure 'deps)) (info-procedure 'deps))
(with-handlers ([exn:fail? (lambda (_) '())]) (with-handlers ([exn:fail? (lambda (_) '())])
(info-procedure 'build-deps))))))))))] (info-procedure 'build-deps))))))))))]
[dep-list-overrides [dep-list-overrides
;; XXX: this probably doesn't capture every case since ;; XXX: this probably doesn't capture every case since
;; Racket doesn't seem to enforce much structure in a ;; Racket doesn't seem to enforce much structure in a
;; multi-package repo, but it accounts for the only cases ;; multi-package repo, but it accounts for the only cases
;; that a sane person would choose ;; that a sane person would choose
(if (string=? rel-path "") (if (string=? rel-path "")
(list (compute-overridden-dep-lists package-name package-path)) (list (compute-overridden-dep-lists package-name package-path))
(let* ([sibling-paths (filter directory-exists? (let* ([sibling-paths (filter directory-exists?
(directory-list parent-path #:build? #t))] (directory-list parent-path #:build? #t))]
[names-of-sibling-paths (map (lambda (p) [names-of-sibling-paths (map (lambda (p)
;; XXX: maybe not very DRY ;; XXX: maybe not very DRY
(path->string (path->string
(match/values (split-path p) (match/values (split-path p)
((_base dir-fragment _must-be-dir?) dir-fragment)))) ((_base dir-fragment _must-be-dir?) dir-fragment))))
sibling-paths)]) sibling-paths)])
(filter-map compute-overridden-dep-lists (filter-map compute-overridden-dep-lists
names-of-sibling-paths names-of-sibling-paths
sibling-paths)))] sibling-paths)))]
[names-of-overridden-packages (apply set (map car dep-list-overrides))] [names-of-overridden-packages (apply set (map car dep-list-overrides))]
[graph (make-immutable-hash (append dep-alist-from-catalog [graph (make-immutable-hash (append dep-alist-from-catalog
dep-list-overrides))] dep-list-overrides))]
;; TODO: no effort is made to handle cycles right now [dependency-subgraph (dfs graph package-name (make-immutable-hash))]
[dfs (lambda (u dependency-subgraph) [generic (make-immutable-hash
(if (hash-has-key? dependency-subgraph u) `((subsystem . "racket")
dependency-subgraph (location . ,rel-path)
(let ([destinations (hash-ref graph u)]) (sourcesAggregatedHash . ,(json-null))
(foldl dfs (defaultPackage . ,package-name)
(hash-set dependency-subgraph u destinations) (packages . ,(make-immutable-hash `((,(string->symbol package-name) . "0.0.0"))))))]
destinations))))] [sources-from-catalog
[dependency-subgraph (dfs package-name (make-immutable-hash))] (hash-map pkgs-all
[generic (make-immutable-hash (match-lambda**
`((subsystem . "racket") [(name (hash-table
(location . ,rel-path) ('versions
(sourcesAggregatedHash . ,(json-null)) (hash-table
(defaultPackage . ,package-name) ('default
(packages . ,(make-immutable-hash `((,(string->symbol package-name) . "0.0.0"))))))]
[sources-from-catalog
(hash-map pkgs-all
(match-lambda**
[(name (hash-table
('versions
(hash-table (hash-table
('default ('source_url url)))))
(hash-table ('checksum rev)))
('source_url url))))) (let* ([source-with-removed-http-or-git-double-slash (regexp-replace #rx"^(?:git|http)://" url "https://")]
('checksum rev))) [left-trimmed-source (string-trim source-with-removed-http-or-git-double-slash "git+" #:right? #f)]
(let* ([source-with-removed-http-or-git-double-slash (regexp-replace #rx"^(?:git|http)://" url "https://")] [maybe-match-path (regexp-match #rx"\\?path=([^#]+)" left-trimmed-source)]
[left-trimmed-source (string-trim source-with-removed-http-or-git-double-slash "git+" #:right? #f)] [trimmed-source (regexp-replace #rx"(?:/tree/.+)?(?:\\?path=.+)?$" left-trimmed-source "")])
[maybe-match-path (regexp-match #rx"\\?path=([^#]+)" left-trimmed-source)] (cons (string->symbol name)
[trimmed-source (regexp-replace #rx"(?:/tree/.+)?(?:\\?path=.+)?$" left-trimmed-source "")]) (make-immutable-hash
(cons (string->symbol name) `((0.0.0 . ,(make-immutable-hash
(make-immutable-hash (append (match maybe-match-path
`((0.0.0 . ,(make-immutable-hash [(list _match dir)
(append (match maybe-match-path `((dir . ,(regexp-replace* #rx"%2F" dir "/")))]
[(list _match dir) [_ '()])
`((dir . ,(regexp-replace* #rx"%2F" dir "/")))] `((url . ,trimmed-source)
[_ '()]) (rev . ,rev)
`((url . ,trimmed-source) (type . "git")
(rev . ,rev) ;; TODO: sha256?
(type . "git") ))))))))]))]
;; TODO: sha256? [sources-from-repo (if (string=? rel-path "")
))))))))]))] (list (cons (string->symbol package-name)
[sources-from-repo (if (string=? rel-path "") (make-immutable-hash
(list (cons (string->symbol package-name) `((0.0.0 . ,(make-immutable-hash
(make-immutable-hash `((type . "path")
`((0.0.0 . ,(make-immutable-hash (path . ,src-path))))))))
`((type . "path") (set-map names-of-overridden-packages
(path . ,src-path)))))))) (lambda (name)
(set-map names-of-overridden-packages (cons (string->symbol name)
(lambda (name) (make-immutable-hash
(cons (string->symbol name) `((0.0.0 . ,(make-immutable-hash
(make-immutable-hash `((type . "path")
`((0.0.0 . ,(make-immutable-hash (path . ,(path->string (build-path parent-path (string-append-immutable name "/")))))))))))))]
`((type . "path") [sources-hash-table (make-immutable-hash (append sources-from-catalog
(path . ,(path->string (build-path parent-path (string-append-immutable name "/")))))))))))))] sources-from-repo))]
[sources-hash-table (make-immutable-hash (append sources-from-catalog [sources (make-immutable-hash (hash-map dependency-subgraph
sources-from-repo))] (lambda (name _v)
[sources (make-immutable-hash (hash-map dependency-subgraph (cons (string->symbol name) (hash-ref sources-hash-table (string->symbol name))))))]
(lambda (name _v) [dream-lock (make-immutable-hash
(cons (string->symbol name) (hash-ref sources-hash-table (string->symbol name))))))] `((_generic . ,generic)
[dream-lock (make-immutable-hash (sources . ,sources)
`((_generic . ,generic) (_subsystem . ,(make-immutable-hash))
(sources . ,sources) (dependencies . ,(make-immutable-hash
(_subsystem . ,(make-immutable-hash)) (hash-map dependency-subgraph
(dependencies . ,(make-immutable-hash (lambda (name dep-list)
(hash-map dependency-subgraph (cons (string->symbol name)
(lambda (name dep-list) (make-immutable-hash `((0.0.0 . ,(map (lambda (dep-name) (list dep-name "0.0.0")) dep-list)))))))))))])
(cons (string->symbol name)
(make-immutable-hash `((0.0.0 . ,(map (lambda (dep-name) (list dep-name "0.0.0")) dep-list)))))))))))])
(make-parent-directory* (getenv "RACKET_OUTPUT_FILE")) (make-parent-directory* (getenv "RACKET_OUTPUT_FILE"))
(with-output-to-file (getenv "RACKET_OUTPUT_FILE") (with-output-to-file (getenv "RACKET_OUTPUT_FILE")
(lambda () (write-json dream-lock)) (lambda () (write-json dream-lock))