diff options
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | README.md | 67 | ||||
-rw-r--r-- | deepenv.scm | 26 |
3 files changed, 100 insertions, 11 deletions
@@ -1,13 +1,25 @@ +CSC ?= csc +PREFIX ?= /usr/local + deepenv: deepenv.scm - csc -o deepenv deepenv.scm + $(CSC) -o deepenv deepenv.scm dispenv: dispenv.scm - csc -o dispenv dispenv.scm + $(CSC) -o dispenv dispenv.scm .PHONY: static static: deepenv.scm - csc -static -o deepenv.static deepenv.scm + $(CSC) -static -o deepenv.static deepenv.scm .PHONY: clean clean: rm -f dispenv deepenv dispenv.link deepenv.link deepenv.static + +.PHONY: install +install: + mkdir -p $(PREFIX)/bin + install deepenv $(PREFIX)/bin/deepenv + +.PHONY: uninstall +uninstall: + rm $(PREFIX)/bin/deepenv @@ -1,4 +1,69 @@ DEEPENV ======= -Deepenv is a tool to run programs with their environment variables populated from all detected parent .env files merged together. +Deepenv is a tool to run programs with their environment variables +populated from all detected parent .env files merged together. + +## Installing + +Deepenv is written in Chicken scheme. In order to install it, you will +need to first install Chicken, and compile deepenv. + +On Linux, use your package manager to install Chicken like so: + +``` +sudo apt install chicken-bin +``` + +On MacOS, install Chicken with Homebrew: + +``` +brew install chicken +``` + +Then compile and install Chicken like so: + +``` +make +make install +``` + +### Overrides + +The following can be overriden by environment or make variables: + +- `CSC` the chicken compiler command. Usually `csc`, sometimes `chicken-csc`. +- `PREFIX` file-system prefix where the executables will be installed. Defaults to `/usr/local`. + +## Usage + +To use deepenv, simply `cd` to the place where you want to run a +program, and run with: + +``` +deepenv <program> [arguments] +``` + +If a `.env` file exists in this folder or any parent folder, they will +be loaded as environment variables when `program` runs. + +## Environment merging strategy + +All `.env` files encountered from the current working directory, all +the way to the filesystem root are loaded and merged together, with +environment variables defined deeper in the tree shadowing their +parent definitions. The very top level is the existing environment +variables. + +For example, given the following file structure: + +``` +/ +/.env ++- /foo + +- .env +``` + +Assuming `/.env` defines `FOO=123` and `/foo/.env` defines `FOO=456`, +running `deepenv <program>` in `/foo` will result in `FOO` being set +to `456`. diff --git a/deepenv.scm b/deepenv.scm index 98c9400..87a5c12 100644 --- a/deepenv.scm +++ b/deepenv.scm @@ -22,6 +22,8 @@ (chicken string) (chicken process) (chicken process-context) + (chicken condition) + (chicken format) srfi-1 srfi-13 srfi-14) @@ -104,11 +106,21 @@ (car executables) program))) -(let* ((parents (path-parents (current-directory))) - (environment (fold .env-union '() (cons (get-environment-variables) (reverse (map load-dir-.env parents))))) - (program (resolve-program (car (command-line-arguments)))) - (arguments (cdr (command-line-arguments)))) - (if program - (process-execute program arguments environment) - (display "Program not found\n"))) +(define (run-with-.env directory command arguments) + (let* ((parents (path-parents directory)) + (environment (fold .env-union '() (cons (get-environment-variables) (reverse (map load-dir-.env parents))))) + (program (resolve-program command))) + (condition-case + (process-execute program arguments environment) + ((exn) (printf "Program `~a' not found!~%" command))))) + +(let ((not-enough-args (< (length (command-line-arguments)) 1)) + (user-asking-help (find (lambda (item) (string=? item "--help")) (command-line-arguments)))) + (if (or not-enough-args user-asking-help) + (begin + (display "Deepenv sources .env files in the current and parent directories, then runs a program.\n") + (display "Usage: deepenv <program> <arguments>\n")) + (run-with-.env (current-directory) + (car (command-line-arguments)) + (cdr (command-line-arguments))))) |