#!/bin/bash

# expenv == dotenv-with-overrides

# Usage: expenv [-d secrets_directory] foo
# Will run `foo` with any environment variables provided by .secrets or overrides, optionally
# searching a specified directory for .secrets and overrides. The directory defaults to `pwd`.
#
# expenv will always attempt to load [secrets_directory]/.secrets before any overrides.
#
# Specify overrides with a comma-separated list in the EXPENV_OVERRIDES env var.
#
# Some example overrides and load orders:
#
# EXPENV_OVERRIDES=prod
# 1. .secrets
# 2. .secrets.prod
#
# EXPENV_OVERRIDES=local,prod
# 1. .secrets
# 2. .secrets.local
# 3. .secrets.prod

set -eo pipefail

secrets_directory="$(pwd)"

while getopts 'd:' OPTION; do
  case "$OPTION" in
    d)
      secrets_directory="$OPTARG"
      ;;

    ?)
      echo "script usage: $(basename $0) [-d secrets_directory] <command>" >&2
      exit 1
      ;;
  esac
done
shift "$(($OPTIND -1))"

export_vars() {
  local env_file="$secrets_directory/$1"

  if [ -f "$env_file" ]
  then
    # loop over the lines of the .secrets file, which are `KEY="val"` formatted
    while IFS='' read -r line || [ -n "$line" ]; do
      # skip comment lines and make sure the line follows our expectations
      # i don't like that this will fail silently, but seems much better than putting garbage in env
      if echo "$line" | grep -E '^[A-Z0-9_]+=".+"$' >/dev/null; then
        eval "export $line"
      fi
    done <"$env_file"
  else
    # this goes to stderr so machine-read stdout doesn't break
    (>&2 echo "Unable to add env vars from $env_file.")
  fi
}

# first lets export the vars from the base/default file
export_vars .secrets

# next process the overrides, in order
IFS=',' read -ra overrides <<< "$EXPENV_OVERRIDES"
for override in "${overrides[@]}"; do
  to_export=".secrets.$override"
  export_vars "$to_export"
done

eval "$@"
