utils: Add 'call-with-decompressed-port' and 'call-with-compressed-output-port'.

* guix/utils.scm (call-with-decompressed-port,
  call-with-compressed-output-port): New procedures.
* tests/utils.scm ("compressed-output-port + decompressed-port"):
  Rewrite to use them.
master
Ludovic Courtès 2014-03-24 22:15:29 +01:00
parent 80dea563a3
commit 01ac19dca4
3 changed files with 48 additions and 18 deletions

View File

@ -22,6 +22,8 @@
(eval . (put 'with-error-handling 'scheme-indent-function 0)) (eval . (put 'with-error-handling 'scheme-indent-function 0))
(eval . (put 'with-mutex 'scheme-indent-function 1)) (eval . (put 'with-mutex 'scheme-indent-function 1))
(eval . (put 'with-atomic-file-output 'scheme-indent-function 1)) (eval . (put 'with-atomic-file-output 'scheme-indent-function 1))
(eval . (put 'call-with-compressed-output-port 'scheme-indent-function 2))
(eval . (put 'call-with-decompressed-port 'scheme-indent-function 2))
(eval . (put 'syntax-parameterize 'scheme-indent-function 1)) (eval . (put 'syntax-parameterize 'scheme-indent-function 1))
(eval . (put 'with-monad 'scheme-indent-function 1)) (eval . (put 'with-monad 'scheme-indent-function 1))

View File

@ -21,6 +21,7 @@
#:use-module (guix config) #:use-module (guix config)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-9) #:use-module (srfi srfi-9)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (srfi srfi-39) #:use-module (srfi srfi-39)
#:use-module (srfi srfi-60) #:use-module (srfi srfi-60)
@ -74,7 +75,9 @@
filtered-port filtered-port
compressed-port compressed-port
decompressed-port decompressed-port
compressed-output-port)) call-with-decompressed-port
compressed-output-port
call-with-compressed-output-port))
;;; ;;;
@ -224,6 +227,22 @@ a symbol such as 'xz."
('gzip (filtered-port `(,%gzip "-c") input)) ('gzip (filtered-port `(,%gzip "-c") input))
(else (error "unsupported compression scheme" compression)))) (else (error "unsupported compression scheme" compression))))
(define (call-with-decompressed-port compression port proc)
"Call PROC with a wrapper around PORT, a file port, that decompresses data
read from PORT according to COMPRESSION, a symbol such as 'xz. PORT is closed
as soon as PROC's dynamic extent is entered."
(let-values (((decompressed pids)
(decompressed-port compression port)))
(dynamic-wind
(const #f)
(lambda ()
(close-port port)
(proc decompressed))
(lambda ()
(close-port decompressed)
(unless (every (compose zero? cdr waitpid) pids)
(error "decompressed-port failure" pids))))))
(define (filtered-output-port command output) (define (filtered-output-port command output)
"Return an output port. Data written to that port is filtered through "Return an output port. Data written to that port is filtered through
COMMAND and written to OUTPUT, an output file port. In addition, return a COMMAND and written to OUTPUT, an output file port. In addition, return a
@ -265,6 +284,22 @@ of PIDs to wait for."
('gzip (filtered-output-port `(,%gzip "-c") output)) ('gzip (filtered-output-port `(,%gzip "-c") output))
(else (error "unsupported compression scheme" compression)))) (else (error "unsupported compression scheme" compression))))
(define (call-with-compressed-output-port compression port proc)
"Call PROC with a wrapper around PORT, a file port, that compresses data
that goes to PORT according to COMPRESSION, a symbol such as 'xz. PORT is
closed as soon as PROC's dynamic extent is entered."
(let-values (((compressed pids)
(compressed-output-port compression port)))
(dynamic-wind
(const #f)
(lambda ()
(close-port port)
(proc compressed))
(lambda ()
(close-port compressed)
(unless (every (compose zero? cdr waitpid) pids)
(error "compressed-output-port failure" pids))))))
;;; ;;;
;;; Nixpkgs. ;;; Nixpkgs.

View File

@ -162,23 +162,16 @@
(equal? (get-bytevector-all decompressed) data))))) (equal? (get-bytevector-all decompressed) data)))))
(false-if-exception (delete-file temp-file)) (false-if-exception (delete-file temp-file))
(test-equal "compressed-output-port + decompressed-port" (test-assert "compressed-output-port + decompressed-port"
'((0) "Hello, compressed port!") (let* ((file (search-path %load-path "guix/derivations.scm"))
(let ((text "Hello, compressed port!") (data (call-with-input-file file get-bytevector-all)))
(output (open-file temp-file "w0b"))) (call-with-compressed-output-port 'xz (open-file temp-file "w0b")
(let-values (((compressed pids) (lambda (compressed)
(compressed-output-port 'xz output))) (put-bytevector compressed data)))
(display text compressed)
(close-port compressed) (bytevector=? data
(close-port output) (call-with-decompressed-port 'xz (open-file temp-file "r0b")
(and (every (compose zero? cdr waitpid) pids) get-bytevector-all))))
(let*-values (((input)
(open-file temp-file "r0b"))
((decompressed pids)
(decompressed-port 'xz input)))
(let ((str (get-string-all decompressed)))
(list (map (compose cdr waitpid) pids)
str)))))))
(false-if-exception (delete-file temp-file)) (false-if-exception (delete-file temp-file))
(test-equal "fcntl-flock wait" (test-equal "fcntl-flock wait"