diff options
Diffstat (limited to 'guix')
| -rw-r--r-- | guix/build-system/gnu.scm | 2 | ||||
| -rw-r--r-- | guix/build/syscalls.scm | 15 | ||||
| -rw-r--r-- | guix/gnu-maintenance.scm | 14 | ||||
| -rw-r--r-- | guix/http-client.scm | 56 | ||||
| -rw-r--r-- | guix/scripts/graph.scm | 8 | ||||
| -rw-r--r-- | guix/scripts/system.scm | 119 | ||||
| -rw-r--r-- | guix/utils.scm | 7 |
7 files changed, 190 insertions, 31 deletions
diff --git a/guix/build-system/gnu.scm b/guix/build-system/gnu.scm index 3be83468eb..c83c50b76e 100644 --- a/guix/build-system/gnu.scm +++ b/guix/build-system/gnu.scm @@ -204,7 +204,7 @@ runs `make distcheck' and whose result is one or more source tarballs." (let ((ref (lambda (module var) (module-ref (resolve-interface module) var)))) `(,@(package-native-inputs p) - ("autoconf" ,(ref '(gnu packages autotools) 'autoconf)) + ("autoconf" ,((ref '(gnu packages autotools) 'autoconf-wrapper))) ("automake" ,(ref '(gnu packages autotools) 'automake)) ("libtool" ,(ref '(gnu packages autotools) 'libtool)) ("gettext" ,(ref '(gnu packages gettext) 'gnu-gettext)) diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm index 2c2fbde0a3..a3b68c4537 100644 --- a/guix/build/syscalls.scm +++ b/guix/build/syscalls.scm @@ -315,10 +315,16 @@ string TMPL and return its file name. TMPL must end with 'XXXXXX'." (define CLONE_NEWNET #x40000000) ;; The libc interface to sys_clone is not useful for Scheme programs, so the -;; low-level system call is wrapped instead. +;; low-level system call is wrapped instead. The 'syscall' function is +;; declared in <unistd.h> as a variadic function; in practice, it expects 6 +;; pointer-sized arguments, as shown in, e.g., x86_64/syscall.S. (define clone (let* ((ptr (dynamic-func "syscall" (dynamic-link))) - (proc (pointer->procedure int ptr (list int int '*))) + (proc (pointer->procedure long ptr + (list long ;sysno + unsigned-long ;flags + '* '* '* + '*))) ;; TODO: Don't do this. (syscall-id (match (utsname:machine (uname)) ("i686" 120) @@ -329,7 +335,10 @@ string TMPL and return its file name. TMPL must end with 'XXXXXX'." "Create a new child process by duplicating the current parent process. Unlike the fork system call, clone accepts FLAGS that specify which resources are shared between the parent and child processes." - (let ((ret (proc syscall-id flags %null-pointer)) + (let ((ret (proc syscall-id flags + %null-pointer ;child stack + %null-pointer %null-pointer ;ptid & ctid + %null-pointer)) ;unused (err (errno))) (if (= ret -1) (throw 'system-error "clone" "~d: ~A" diff --git a/guix/gnu-maintenance.scm b/guix/gnu-maintenance.scm index ac83df40a3..e09df4b3ef 100644 --- a/guix/gnu-maintenance.scm +++ b/guix/gnu-maintenance.scm @@ -116,8 +116,10 @@ (doc-urls gnu-package-doc-urls) ; list of strings (download-url gnu-package-download-url)) -(define (official-gnu-packages) - "Return a list of records, which are GNU packages." +(define* (official-gnu-packages + #:optional (fetch http-fetch/cached)) + "Return a list of records, which are GNU packages. Use FETCH, +to fetch the list of GNU packages over HTTP." (define (read-records port) ;; Return a list of alists. Each alist contains fields of a GNU ;; package. @@ -129,8 +131,7 @@ (cons alist result))))) (define official-description - (let ((db (read-records (http-fetch %package-description-url - #:text? #t)))) + (let ((db (read-records (fetch %package-description-url #:text? #t)))) (lambda (name) ;; Return the description found upstream for package NAME, or #f. (and=> (find (lambda (alist) @@ -160,7 +161,10 @@ "doc-url" "download-url") '("doc-url" "language")))) - (read-records (http-fetch %package-list-url #:text? #t)))) + (let* ((port (fetch %package-list-url #:text? #t)) + (lst (read-records port))) + (close-port port) + lst))) (define (find-packages regexp) "Find GNU packages which satisfy REGEXP." diff --git a/guix/http-client.scm b/guix/http-client.scm index 9861ec80cb..8d1cc9b8f3 100644 --- a/guix/http-client.scm +++ b/guix/http-client.scm @@ -23,6 +23,8 @@ #:use-module ((web client) #:hide (open-socket-for-uri)) #:use-module (web response) #:use-module (srfi srfi-11) + #:use-module (srfi srfi-19) + #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:use-module (ice-9 match) @@ -30,6 +32,8 @@ #:use-module (rnrs bytevectors) #:use-module (guix ui) #:use-module (guix utils) + #:use-module ((guix build utils) + #:select (mkdir-p dump-port)) #:use-module ((guix build download) #:select (open-socket-for-uri resolve-uri-reference)) #:re-export (open-socket-for-uri) @@ -39,7 +43,10 @@ http-get-error-code http-get-error-reason - http-fetch)) + http-fetch + + %http-cache-ttl + http-fetch/cached)) ;;; Commentary: ;;; @@ -229,4 +236,51 @@ Raise an '&http-get-error' condition if downloading fails." (&message (message "download failed")))))))))) + +;;; +;;; Caching. +;;; + +(define (%http-cache-ttl) + ;; Time-to-live in seconds of the HTTP cache of in ~/.cache/guix. + (make-parameter + (* 3600 (or (and=> (getenv "GUIX_HTTP_CACHE_TTL") + string->number*) + 36)))) + +(define* (http-fetch/cached uri #:key (ttl (%http-cache-ttl)) text?) + "Like 'http-fetch', return an input port, but cache its contents in +~/.cache/guix. The cache remains valid for TTL seconds." + (let* ((directory (string-append (cache-directory) "/http/" + (uri-host uri))) + (file (string-append directory "/" + (basename (uri-path uri))))) + (define (update-cache) + ;; Update the cache and return an input port. + (let ((port (http-fetch uri #:text? text?))) + (mkdir-p directory) + (call-with-output-file file + (cut dump-port port <>)) + (close-port port) + (open-input-file file))) + + (define (old? port) + ;; Return true if PORT has passed TTL. + (let* ((s (stat port)) + (now (current-time time-utc))) + (< (+ (stat:mtime s) ttl) (time-second now)))) + + (catch 'system-error + (lambda () + (let ((port (open-input-file file))) + (if (old? port) + (begin + (close-port port) + (update-cache)) + port))) + (lambda args + (if (= ENOENT (system-error-errno args)) + (update-cache) + (apply throw args)))))) + ;;; http-client.scm ends here diff --git a/guix/scripts/graph.scm b/guix/scripts/graph.scm index 725ae42030..734a47719a 100644 --- a/guix/scripts/graph.scm +++ b/guix/scripts/graph.scm @@ -322,10 +322,12 @@ substitutes." (define* (export-graph sinks port #:key + reverse-edges? (node-type %package-node-type) (backend %graphviz-backend)) "Write to PORT the representation of the DAG with the given SINKS, using the -given BACKEND. Use NODE-TYPE to traverse the DAG." +given BACKEND. Use NODE-TYPE to traverse the DAG. When REVERSE-EDGES? is +true, draw reverse arrows." (match backend (($ <graph-backend> emit-prologue emit-epilogue emit-node emit-edge) (emit-prologue (node-type-name node-type) port) @@ -349,7 +351,9 @@ given BACKEND. Use NODE-TYPE to traverse the DAG." dependencies))) (emit-node id (node-label head) port) (for-each (lambda (dependency dependency-id) - (emit-edge id dependency-id port)) + (if reverse-edges? + (emit-edge dependency-id id port) + (emit-edge id dependency-id port))) dependencies ids) (loop (append dependencies tail) (set-insert id visited))))))))))))) diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index 71b92dacc7..b5da57a9ce 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm @@ -28,12 +28,15 @@ #:use-module (guix profiles) #:use-module (guix scripts) #:use-module (guix scripts build) + #:use-module (guix scripts graph) #:use-module (guix build utils) #:use-module (gnu build install) #:use-module (gnu system) #:use-module (gnu system file-systems) #:use-module (gnu system vm) #:use-module (gnu system grub) + #:use-module (gnu services) + #:use-module (gnu services dmd) #:use-module (gnu packages grub) #:use-module (srfi srfi-1) #:use-module (srfi srfi-19) @@ -280,6 +283,50 @@ it atomically, and then run OS's activation script." ;;; +;;; Graphs. +;;; + +(define (service-node-label service) + "Return a label to represent SERVICE." + (let ((type (service-kind service)) + (value (service-parameters service))) + (string-append (symbol->string (service-type-name type)) + (cond ((or (number? value) (symbol? value)) + (string-append " " (object->string value))) + ((string? value) + (string-append " " value)) + ((file-system? value) + (string-append " " (file-system-mount-point value))) + (else + ""))))) + +(define (service-node-type services) + "Return a node type for SERVICES. Since <service> instances are not +self-contained (they express dependencies on service types, not on services), +we have to create the 'edges' procedure dynamically as a function of the full +list of services." + (node-type + (name "service") + (description "the DAG of services") + (identifier (lift1 object-address %store-monad)) + (label service-node-label) + (edges (lift1 (service-back-edges services) %store-monad)))) + +(define (dmd-service-node-label service) + "Return a label for a node representing a <dmd-service>." + (string-join (map symbol->string (dmd-service-provision service)))) + +(define (dmd-service-node-type services) + "Return a node type for SERVICES, a list of <dmd-service>." + (node-type + (name "dmd-service") + (description "the dependency graph of dmd services") + (identifier (lift1 dmd-service-node-label %store-monad)) + (label dmd-service-node-label) + (edges (lift1 (dmd-service-back-edges services) %store-monad)))) + + +;;; ;;; Action. ;;; @@ -366,6 +413,29 @@ building anything." ;; All we had to do was to build SYS. (return (derivation->output-path sys)))))))) +(define (export-extension-graph os port) + "Export the service extension graph of OS to PORT." + (let* ((services (operating-system-services os)) + (boot (find (lambda (service) + (eq? (service-kind service) boot-service-type)) + services))) + (export-graph (list boot) (current-output-port) + #:node-type (service-node-type services) + #:reverse-edges? #t))) + +(define (export-dmd-graph os port) + "Export the graph of dmd services of OS to PORT." + (let* ((services (operating-system-services os)) + (pid1 (fold-services services + #:target-type dmd-root-service-type)) + (dmds (service-parameters pid1)) ;the list of <dmd-service> + (sinks (filter (lambda (service) + (null? (dmd-service-requirement service))) + dmds))) + (export-graph sinks (current-output-port) + #:node-type (dmd-service-node-type dmds) + #:reverse-edges? #t))) + ;;; ;;; Options. @@ -388,7 +458,11 @@ Build the operating system declared in FILE according to ACTION.\n")) (display (_ "\ disk-image build a disk image, suitable for a USB stick\n")) (display (_ "\ - init initialize a root file system to run GNU.\n")) + init initialize a root file system to run GNU\n")) + (display (_ "\ + extension-graph emit the service extension graph in Dot format\n")) + (display (_ "\ + dmd-graph emit the graph of dmd services in Dot format\n")) (show-build-options-help) (display (_ " @@ -496,16 +570,17 @@ Build the operating system declared in FILE according to ACTION.\n")) (alist-cons 'argument arg result) (let ((action (string->symbol arg))) (case action - ((build vm vm-image disk-image reconfigure init) + ((build vm vm-image disk-image reconfigure init + extension-graph dmd-graph) (alist-cons 'action action result)) (else (leave (_ "~a: unknown action~%") action)))))) (define (match-pair car) ;; Return a procedure that matches a pair with CAR. (match-lambda - ((head . tail) - (and (eq? car head) tail)) - (_ #f))) + ((head . tail) + (and (eq? car head) tail)) + (_ #f))) (define (option-arguments opts) ;; Extract the plain arguments from OPTS. @@ -561,20 +636,26 @@ Build the operating system declared in FILE according to ACTION.\n")) (run-with-store store (mbegin %store-monad (set-guile-for-build (default-guile)) - (perform-action action os - #:dry-run? dry? - #:derivations-only? (assoc-ref opts - 'derivations-only?) - #:use-substitutes? (assoc-ref opts 'substitutes?) - #:image-size (assoc-ref opts 'image-size) - #:full-boot? (assoc-ref opts 'full-boot?) - #:mappings (filter-map (match-lambda - (('file-system-mapping . m) - m) - (_ #f)) - opts) - #:grub? grub? - #:target target #:device device)) + (case action + ((extension-graph) + (export-extension-graph os (current-output-port))) + ((dmd-graph) + (export-dmd-graph os (current-output-port))) + (else + (perform-action action os + #:dry-run? dry? + #:derivations-only? (assoc-ref opts + 'derivations-only?) + #:use-substitutes? (assoc-ref opts 'substitutes?) + #:image-size (assoc-ref opts 'image-size) + #:full-boot? (assoc-ref opts 'full-boot?) + #:mappings (filter-map (match-lambda + (('file-system-mapping . m) + m) + (_ #f)) + opts) + #:grub? grub? + #:target target #:device device)))) #:system system)))) ;;; system.scm ends here diff --git a/guix/utils.scm b/guix/utils.scm index 0802a1b67a..190b787185 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -81,6 +81,7 @@ fold-tree fold-tree-leaves split + cache-directory filtered-port compressed-port @@ -703,6 +704,12 @@ elements after E." ((head . tail) (loop tail (cons head acc)))))) +(define (cache-directory) + "Return the cache directory for Guix, by default ~/.cache/guix." + (or (getenv "XDG_CONFIG_HOME") + (and=> (getenv "HOME") + (cut string-append <> "/.cache/guix")))) + ;;; ;;; Source location. |
