#!guile \ --no-auto-compile -s !# ;; This is an example Guix containerization wrapper. (use-modules (srfi srfi-1) (ice-9 receive)) (define program-command "unrar") (define program-package "unrar") (define empty-dir "/tmp/empty") (define user "foo") (define (usage) (display (format #f "Usage: ~a COMMAND [OPTIONS] ARCHIVE [FILES...] [@LISTFILES...] [OUTPUT-DIR/] Run program in a container. Within the container, the archive is read-only and the OUTPUT-DIR is shared read-write. OUTPUT-DIR must end with a '/'. If unspecified, current directory is used. See below for the original program options: " (first (command-line)))) (let ((command-line `("guix" "environment" "--pure" ,(string-append "--user=" user) "--container" "--ad-hoc" program-package "--" program-command "h"))) (run-command-line command-line))) (define (parse-args) (let ((args (command-line)) (command "") (switches '()) (archive "") (files '()) (output-directory (getcwd))) ;; Skip caller. (set! args (cdr args)) ;; Check for help. (when (and (not (null? args)) (or (string=? (first args) "-h") (string=? (first args) "--help"))) (usage) (exit #t)) ;; Command. (unless (null? args) (set! command (first args)) (set! args (cdr args))) ;; Switches. (while (and (not (null? args)) (string=? (string-take (first args) 1) "-")) (set! switches (append (list (first args)) files)) (set! args (cdr args))) (set! switches (reverse! switches)) ;; Archive. (unless (null? args) (set! archive (first args)) (set! args (cdr args))) ;; Files and filelists. (while (and (not (null? args)) (not (string=? (string-take-right (first args) 1) "/"))) (set! files (append (list (first args)) files)) (set! args (cdr args))) (set! files (reverse! files)) ;; Output dir. (unless (null? args) (set! output-directory (first args)) (set! args (cdr args))) ;; Handy error checking while we are at it. (unless (null? args) (warn "Possible extraneous arguments:" args)) (values command switches archive files output-directory))) (define (expose file) (string-append "--expose=" file "=" (basename file))) (define (run-command-line command-line) ;; TODO: Use guix' mkdir-p? (unless (file-exists? empty-dir) (mkdir empty-dir)) (apply system* command-line) (rmdir empty-dir)) (define (main) (receive (command switches archive files output-directory) (parse-args) (when (or (string=? command "") (string=? archive "")) (display "Both COMMAND and ARCHIVE arguments are required") (newline) (usage) (exit #f)) (let ((command-line `("guix" "environment" "--pure" ,(string-append "--user=" user) "--container" ,(expose archive) ,@(map expose files) ,(string-append "--share=" output-directory "=" (basename output-directory)) "--ad-hoc" program-package "--" program-command ,command ,@switches ,(basename archive) ,@(map basename files) ;; TODO: This is not the right ,(string-append (basename output-directory) "/") ))) (display (format #f "Running command: ~a" command-line)) (newline) (newline) (run-command-line command-line)))) (main)