diff --git a/cmd_dump.go b/cmd_dump.go index e6fe349b7..61dec01f9 100644 --- a/cmd_dump.go +++ b/cmd_dump.go @@ -1,26 +1,44 @@ package main -import "fmt" +import ( + "fmt" + "os" +) -// `direnv dump` +// CmdDump is `direnv dump` var CmdDump = &Cmd{ Name: "dump", Desc: "Used to export the inner bash state at the end of execution", - Args: []string{"[SHELL]"}, + Args: []string{"[SHELL]", "[FILE]"}, Private: true, Action: actionSimple(func(env Env, args []string) (err error) { target := "gzenv" + w := os.Stdout if len(args) > 1 { target = args[1] } + var filePath string + if len(args) > 2 { + filePath = args[2] + } else { + filePath = os.Getenv("DIRENV_DUMP_FILE_PATH") + } + + if filePath != "" { + w, err = os.OpenFile(filePath, os.O_WRONLY, 0666) + if err != nil { + return err + } + } + shell := DetectShell(target) if shell == nil { return fmt.Errorf("unknown target shell '%s'", target) } - fmt.Println(shell.Dump(env)) + _, err = fmt.Fprintln(w, shell.Dump(env)) return }), diff --git a/stdlib.go b/stdlib.go index 50e94f4cd..ee474ae08 100644 --- a/stdlib.go +++ b/stdlib.go @@ -260,18 +260,48 @@ const STDLIB = "#!/usr/bin/env bash\n" + "# the results with direnv_load.\n" + "#\n" + "direnv_load() {\n" + - " local exports\n" + - " # backup and restore watches in case of nix-shell --pure\n" + - " local __watches=$DIRENV_WATCHES\n" + + " # Backup watches in case of `nix-shell --pure`\n" + + " local prev_watches=$DIRENV_WATCHES\n" + + " local prev_dump_file_path=${DIRENV_DUMP_FILE_PATH:-}\n" + + "\n" + + " # Create pipe\n" + + " DIRENV_DUMP_FILE_PATH=$(mktemp -u)\n" + + " export DIRENV_DUMP_FILE_PATH\n" + + " mkfifo \"$DIRENV_DUMP_FILE_PATH\"\n" + + "\n" + + " # Run program in the background\n" + + " (\"$@\")&\n" + "\n" + - " exports=$(\"$direnv\" apply_dump <(\"$@\"))\n" + + " # Apply the output of the dump\n" + + " local exports\n" + + " exports=$(\"$direnv\" apply_dump \"$DIRENV_DUMP_FILE_PATH\")\n" + " local es=$?\n" + + "\n" + + " # Regroup\n" + + " rm \"$DIRENV_DUMP_FILE_PATH\"\n" + + " wait # wait on the child process to exit\n" + + " local es2=$?\n" + + "\n" + " if [[ $es -ne 0 ]]; then\n" + " return $es\n" + " fi\n" + + "\n" + + " if [[ $es2 -ne 0 ]]; then\n" + + " return $es2\n" + + " fi\n" + + "\n" + " eval \"$exports\"\n" + "\n" + - " export DIRENV_WATCHES=$__watches\n" + + " # Restore watches if the dump wiped them\n" + + " if [[ -z \"$DIRENV_WATCHES\" ]]; then\n" + + " export DIRENV_WATCHES=$prev_watches\n" + + " fi\n" + + " # Allow nesting\n" + + " if [[ -n \"$prev_dump_file_path\" ]]; then\n" + + " export DIRENV_DUMP_FILE_PATH=$prev_dump_file_path\n" + + " else\n" + + " unset DIRENV_DUMP_FILE_PATH\n" + + " fi\n" + "}\n" + "\n" + "# Usage: PATH_add [ ...]\n" + diff --git a/stdlib.sh b/stdlib.sh index 39e2732dc..dbca16e19 100755 --- a/stdlib.sh +++ b/stdlib.sh @@ -258,18 +258,48 @@ source_up() { # the results with direnv_load. # direnv_load() { - local exports - # backup and restore watches in case of nix-shell --pure - local __watches=$DIRENV_WATCHES + # Backup watches in case of `nix-shell --pure` + local prev_watches=$DIRENV_WATCHES + local prev_dump_file_path=${DIRENV_DUMP_FILE_PATH:-} + + # Create pipe + DIRENV_DUMP_FILE_PATH=$(mktemp -u) + export DIRENV_DUMP_FILE_PATH + mkfifo "$DIRENV_DUMP_FILE_PATH" + + # Run program in the background + ("$@")& - exports=$("$direnv" apply_dump <("$@")) + # Apply the output of the dump + local exports + exports=$("$direnv" apply_dump "$DIRENV_DUMP_FILE_PATH") local es=$? + + # Regroup + rm "$DIRENV_DUMP_FILE_PATH" + wait # wait on the child process to exit + local es2=$? + if [[ $es -ne 0 ]]; then return $es fi + + if [[ $es2 -ne 0 ]]; then + return $es2 + fi + eval "$exports" - export DIRENV_WATCHES=$__watches + # Restore watches if the dump wiped them + if [[ -z "$DIRENV_WATCHES" ]]; then + export DIRENV_WATCHES=$prev_watches + fi + # Allow nesting + if [[ -n "$prev_dump_file_path" ]]; then + export DIRENV_DUMP_FILE_PATH=$prev_dump_file_path + else + unset DIRENV_DUMP_FILE_PATH + fi } # Usage: PATH_add [ ...] diff --git a/test/scenarios/dump/.envrc b/test/scenarios/dump/.envrc index 4a73d18e5..a2a92028b 100644 --- a/test/scenarios/dump/.envrc +++ b/test/scenarios/dump/.envrc @@ -2,5 +2,5 @@ direnv_load env \ LS_COLORS='*.ogg=38;5;45:*.wav=38;5;45' \ LESSOPEN='||/usr/bin/lesspipe.sh %s' \ THREE_BACKSLASHES='\\\' \ - bash -c "direnv dump" + bash -c "echo to stdout && echo to stderr >&2 && direnv dump"