(define-module (ruther environment) #:use-module (guix profiles) #:use-module (guix gexp) #:use-module (guix packages) #:use-module (guix build-system trivial) #:use-module (gnu packages bash) #:export (make-environment)) ;; Makes a package that uses the given environment, and wraps the binaries in it. ;; TODO: replace the paths (only in text files!!! not in binaries...) in all extra-paths files, ;; so instead of symlinking some of the files might have to be just copied and substituted. ;; this also means it might come in handy to create all directories instead and symlink only the files. (define* (make-environment manifest #:key (name "environment") (binary-paths '("bin")) (extra-paths '("share/info" "share/man" "share/doc" "share/applications")) (rename-function #~identity) (filter-function #~(const #t))) "Takes a manifest, makes a package that will have all the binaries the profile has, wrapped to use etc/profile " (let ((profile (profile (content manifest)))) (package (name name) (version "0") (source #f) (build-system trivial-build-system) (inputs (list bash)) (arguments (list #:modules '((guix build utils)) #:builder #~(begin (use-modules (guix build utils) (ice-9 format) (ice-9 ftw)) (mkdir-p #$output) ;; Iterate all binary-paths under profile and make scripts in output (let ((profile-path #$profile)) (define (make-wrapper-script source-file input-file output-file) (call-with-output-file output-file (lambda (port) (format port "!#~a/bin/bash~%" #$(this-package-input "bash")) (format port "source ~a~%" source-file) (format port "exec ~a \"$@\"~%" input-file))) (chmod output-file #o555)) (define (not-directory? base-path) (lambda (path) (let ((s (stat (string-append base-path "/" path)))) (not (eq? (stat:type s) 'directory))))) (for-each (lambda (binary-path) (mkdir-p (string-append #$output "/" binary-path)) ;; list the files, make scripts in #$output/ that call them, with source #$profile/etc/profile prepended (for-each (lambda (file-name) (when (#$filter-function file-name) (make-wrapper-script (string-append profile-path "/etc/profile") (string-append profile-path "/" binary-path "/" file-name) (string-append #$output "/" binary-path "/" (#$rename-function file-name))))) (scandir (string-append profile-path "/" binary-path) (not-directory? (string-append profile-path "/" binary-path))))) '#$binary-paths) ;; Iterate all extra-paths and symlink them to output. (for-each (lambda (extra-path) (when (string-contains extra-path "/") (mkdir-p (string-append #$output "/" (dirname extra-path)))) (symlink (string-append #$profile "/" extra-path) (string-append #$output "/" extra-path))) '#$extra-paths))))) (synopsis #f) (description #f) (home-page #f) (license #f))))