Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke external programs using full paths #13

Merged
merged 2 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
uses: cachix/install-nix-action@v30
- name: Run tests
run: |
nix develop '.#ci' --command ./tests.bats
nix develop '.#ci' --command bats tests.bats nix-tests.bats
55 changes: 32 additions & 23 deletions bash-env-json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,20 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

VERSION="0.9.1"
VERSION="0.9.2a"
USAGE="bash-env-json [--help] [--shellfns <comma-separated-function-names>] [path]"

shopt -s extglob

# external dependencies are ideally invoked via full paths,
# so make it straightforward for the Nix flake to substitute for these
function _env() { env "$@"; }
function _jq() { jq "$@"; }
function _mktemp() { mktemp "$@"; }
function _rm() { rm "$@"; }
function _sed() { sed "$@"; }
function _touch() { touch "$@"; }

function capture() {
local -n _capture_env="$1"
local -n _capture_shellvars="$2"
Expand All @@ -37,12 +46,12 @@ function capture() {
# environment variables
while IFS='=' read -r -d '' _name _value; do
_capture_env["$_name"]="${_value}"
done < <(env -0)
done < <(_env -0)

# shellvars
for _name in $(
set -o posix
set | sed -n -e '/^[a-zA-Z_][a-zA-Z_0-9]*=/s/=.*$//p'
set | _sed -n -e '/^[a-zA-Z_][a-zA-Z_0-9]*=/s/=.*$//p'
set +o posix
); do
if test -v "$_name" -a ! "${_capture_env[$_name]+EXISTS}" -a ! "${_inhibit_shellvars[$_name]+EXISTS}"; then
Expand All @@ -52,9 +61,9 @@ function capture() {
}

function emit_value() {
# jq -R produces nothing on empty input, but we want ""
# `jq -R` produces nothing on empty input, but we want ""
if test -n "$1"; then
echo -n "$1" | jq -R
echo -n "$1" | _jq -R
else
echo -n '""'
fi
Expand Down Expand Up @@ -82,17 +91,17 @@ function emit_error() {
}

function emit_error_exit() {
emit_error "$@" | jq
emit_error "$@" | _jq
exit 1
}

function emit_help_exit() {
emit_meta '{' '}' usage | jq
emit_meta '{' '}' usage | _jq
exit 0
}

function emit_version_exit() {
emit_meta '{' '}' | jq
emit_meta '{' '}' | _jq
exit 0
}

Expand Down Expand Up @@ -136,11 +145,11 @@ function eval_or_source() {
local _source _path _error_file
_path="$1"

_error_file=$(mktemp -u)
touch "$_error_file"
_error_file=$(_mktemp -u)
_touch "$_error_file"
# shellcheck disable=SC2094
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"
_rm -f "$_error_file"

if test -n "$_path"; then
# source from file if specified
Expand All @@ -161,19 +170,19 @@ function eval_or_source() {
if ! eval "$_source" >/dev/null 2>&4; then
exec 4>&-
# discard error location, because it is this file not the one sourced
emit_error_exit "$(sed -e 's/^.*line\s*[0-9]*:\s*//' <&3)"
emit_error_exit "$(_sed -e 's/^.*line\s*[0-9]*:\s*//' <&3)"
fi
fi
}

function invoke_safely() {
local _fn="$1"

_error_file=$(mktemp -u)
touch "$_error_file"
_error_file=$(_mktemp -u)
_touch "$_error_file"
# shellcheck disable=SC2094
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"
_rm -f "$_error_file"

"$_fn" >/dev/null 2>&4 || {
exec 4>&-
Expand Down Expand Up @@ -233,14 +242,14 @@ function main() {
capture _env_current _shellvars_current

# accumulate result in a file until we know we are error-free
_result_file=$(mktemp -u)
touch "$_result_file"
_result_file=$(_mktemp -u)
_touch "$_result_file"
# shellcheck disable=SC2094
exec 5<"$_result_file" 6>"$_result_file"
rm -f "$_result_file"
_rm -f "$_result_file"

emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6
emit "{" "env" _env_previous _env_current >&6
emit "," "shellvars" _shellvars_previous _shellvars_current >&6

test "${#_shellfn_names[@]}" -gt 0 && {
echo ",\"fn\":{" >&6
Expand All @@ -253,8 +262,8 @@ function main() {
capture _env_current _shellvars_current

echo "$_fn_comma\"$_fn\":" >&6
emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6
emit "{" "env" _env_previous _env_current >&6
emit "," "shellvars" _shellvars_previous _shellvars_current >&6
echo "}" >&6
_fn_comma=","
done
Expand All @@ -266,7 +275,7 @@ function main() {
emit_meta ',' '}' >&6
exec 6>&-

jq <&5
_jq <&5
}

function bad_usage() {
Expand Down
26 changes: 18 additions & 8 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
description = "Nix package for bash-env";
description = "Nix package for bash-env-json";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
Expand All @@ -17,18 +17,28 @@
let
inherit (pkgs) bash coreutils gnused jq makeWrapper writeShellScriptBin;
inherit (pkgs.lib) makeBinPath;

substFullPaths = program_package:
let replaceList = pkgs.lib.attrsets.mapAttrsToList (name: pkg: { from = " ${name} "; to = " ${pkg}/bin/${name} "; }) program_package; in
builtins.replaceStrings (map (x: x.from) replaceList) (map (x: x.to) replaceList);

in
(writeShellScriptBin "bash-env-json" (builtins.readFile ./bash-env-json)).overrideAttrs (old: {
buildInputs = [ bash jq makeWrapper ];
(writeShellScriptBin "bash-env-json"
(substFullPaths
{
env = pkgs.coreutils;
jq = pkgs.jq;
mktemp = pkgs.coreutils;
rm = pkgs.coreutils;
sed = pkgs.gnused;
touch = pkgs.coreutils;
}
(builtins.readFile ./bash-env-json))).overrideAttrs (old: {
buildInputs = [ bash ];
buildCommand =
''
${old.buildCommand}
patchShebangs $out
wrapProgram $out/bin/bash-env-json --prefix PATH : ${makeBinPath [
coreutils
gnused
jq
]}
'';
});
in
Expand Down
15 changes: 15 additions & 0 deletions nix-tests.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bats
#
# simple tests for the Nix packaging

@test "simple" {
actual=$(echo 'export SOME_VARIABLE=some_value' | bash-env-json | jq -r '.env.SOME_VARIABLE')
expected='some_value'
test "$actual" == "$expected"
}

@test "path" {
actual=$(echo 'export PATH=/oops' | bash-env-json | jq -r '.env.PATH')
expected='/oops'
test "$actual" == "$expected"
}