diff --git a/.local/bin/guix-containerize b/.local/bin/guix-containerize new file mode 100755 index 00000000..4319e0a2 --- /dev/null +++ b/.local/bin/guix-containerize @@ -0,0 +1,122 @@ +#!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)