From 664c907ace1e49e4d617bdf975a5b4701326294e Mon Sep 17 00:00:00 2001 From: technofab Date: Fri, 18 Jul 2025 16:40:03 +0200 Subject: [PATCH] feat: add config variables and PRJ compat BREAKING CHANGE: rename use_envreload to use_ren/use_rensa --- README.md | 24 ++++++---- direnvrc | 141 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 130 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 398201e..cad1e4f 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,23 @@ ## Usage -```console -direnv fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/main/direnvrc -``` +1. Use latest release/tag: [![Latest Release](https://gitlab.com/rensa-nix/direnv/-/badges/release.svg)](https://gitlab.com/rensa-nix/direnv/-/releases) +1. Get hash for release: + ```bash + direnv fetchurl https://gitlab.com/rensa-nix/direnv/-/raw//direnvrc + ``` +1. Add this to your `.envrc`: + ```bash + # configure rensa here if needed, like: + # REN_DO_WATCH=false + # etc. + source $(fetchurl https://gitlab.com/rensa-nix/direnv/-/raw//direnvrc ) + use ren //repo/shells/default + ``` -`.envrc`: +## Configuration -```bash -source $(fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/main/direnvrc ) - -use envreload //repo/shells/default -``` +See [direnvrc](./direnvrc) at the top. ## Formatting & Linting diff --git a/direnvrc b/direnvrc index 15668fa..96a91e8 100644 --- a/direnvrc +++ b/direnvrc @@ -14,6 +14,19 @@ readonly RENSA_DIRENV_VERSION="0.1.0" readonly DIRENV_MIN_VERSION="2.21.3" readonly BASH_MIN_VERSION="4.4" +# +# CONFIGURATION ENV VARS +# +REN_FLAKE_ATTR=${REN_FLAKE_ATTR-"__ren"} +# whether to enable watching the files for changes +REN_DO_WATCH=${REN_DO_WATCH-true} +# whether to add the shell profile or flake inputs to gcroots +REN_DO_GCROOTS=${REN_DO_GCROOTS-true} +# whether to archive the flake inputs and gcroot them (only works if REN_DO_GCROOT is true) +REN_DO_ARCHIVE=${REN_DO_ARCHIVE-true} +# whether to enable compat mode which sets PRJ env variables +REN_DO_PRJ_COMPAT=${REN_DO_PRJ_COMAT-true} + # # LOGGING # @@ -76,9 +89,9 @@ __ren_get_cell_path() { if [[ -z "$__cell_path_cache" ]]; then local cell="$1" local cellsFrom - cellsFrom=$(__ren_nix eval --raw ".#__std.cellsFrom" 2>/dev/null || true) + cellsFrom=$(__ren_nix eval --raw ".#${REN_FLAKE_ATTR}.cellsFrom" 2>/dev/null || true) if [[ -z "$cellsFrom" ]]; then - __ren_log TRACE "Could not determine 'cellsFrom' path from flake." + __ren_log ERROR "Could not determine 'cellsFrom' path from flake." return 1 fi __cell_path_cache=$cellsFrom @@ -108,12 +121,73 @@ __ren_init_project() { export REN_ROOT="$git_repo" export REN_STATE="${REN_ROOT}/.ren" - mkdir -p "${REN_STATE}/direnv" + mkdir -p "${REN_STATE}" + # shellcheck disable=SC2034 direnv_layout_dir="${REN_STATE}/direnv" + mkdir -p "${REN_STATE}/direnv" # add nested gitignore which ignores the whole state dir echo "**/*" >"$REN_STATE/.gitignore" + + if [ "$REN_DO_PRJ_COMPAT" = true ]; then + __ren_log INFO "Setting PRJ env variables for compat" + __ren_init_prj_spec + else + __ren_log TRACE "Not setting PRJ env variables" + fi +} + +# compat with other stuff that uses PRJ_... +# we explicitly don't want any dirs to be in the project dir, put them all +# in .ren, so they don't clutter everything up +__ren_init_prj_spec() { + export PRJ_ROOT=${PRJ_ROOT:="${REN_STATE}"} + + export PRJ_CONFIG_HOME=${PRJ_CONFIG_HOME:="${REN_STATE}/config"} + mkdir -p "${PRJ_CONFIG_HOME}" + + export PRJ_RUNTIME_DIR=${PRJ_RUNTIME_DIR:="${REN_STATE}/runtime"} + mkdir -p "${PRJ_RUNTIME_DIR}" + + # load project id if exists + if [[ -z "${PRJ_ID:-}" && -f "${PRJ_CONFIG_HOME}/prj_id" ]]; then + export PRJ_ID=$(<"${PRJ_CONFIG_HOME}/prj_id") + fi + + # PRJ_CACHE_HOME - shared if PRJ_ID is set + if [[ -z "${PRJ_CACHE_HOME:-}" ]]; then + if [[ -n "${PRJ_ID:-}" ]]; then + export PRJ_CACHE_HOME="${XDG_CACHE_HOME}/prj/${PRJ_ID}" + else + export PRJ_CACHE_HOME="${REN_STATE}/cache" + fi + fi + mkdir -p "${PRJ_CACHE_HOME}" + + # PRJ_DATA_HOME - shared if PRJ_ID is set + if [[ -z "${PRJ_DATA_HOME:-}" ]]; then + if [[ -n "${PRJ_ID:-}" ]]; then + export PRJ_DATA_HOME="${XDG_DATA_HOME}/prj/${PRJ_ID}" + else + export PRJ_DATA_HOME="${REN_STATE}/data" + fi + fi + # NOTE: stuff like devshell uses PRJ_DATA_DIR instead, even though numtide + # wrote the spec? :D + # technically not supported so we just overwrite it, use PRJ_DATA_HOME instead + export PRJ_DATA_DIR=$PRJ_DATA_HOME + mkdir -p "${PRJ_DATA_HOME}" + + # PRJ_PATH - shared if PRJ_ID is set + if [[ -z "${PRJ_PATH:-}" ]]; then + if [[ -n "${PRJ_ID:-}" ]]; then + export PRJ_PATH="${HOME}/.local/bin/prj/${PRJ_ID}" + else + export PRJ_PATH="${REN_STATE}/bin" + fi + fi + mkdir -p "${PRJ_PATH}" } # @@ -208,16 +282,18 @@ __ren_update_gcroots() { local __layout_dir="$1" tmp_profile="$2" profile="$3" cell="$4" __ren_add_gcroot "$tmp_profile" "$profile" rm -f "$tmp_profile"* - # add gcroots for the main flake - __ren_add_flake_input_gcroots "$REN_ROOT" "$__layout_dir" + if [ "$REN_DO_ARCHIVE" = true ]; then + # add gcroots for the main flake + __ren_add_flake_input_gcroots "$REN_ROOT" "$__layout_dir" - # if a cell is specified, also gcroot it's flake inputs, if it has a flake - if [[ -n "$cell" ]]; then - local cell_path - if cell_path=$(__ren_get_cell_path "$cell"); then - if [[ -f "${cell_path}/flake.nix" ]]; then - __ren_log TRACE "Found cell flake. Adding GC roots for inputs from '${cell_path}'." - __ren_add_flake_input_gcroots "$cell_path" "$__layout_dir" + # if a cell is specified, also gcroot it's flake inputs, if it has a flake + if [[ -n "$cell" ]]; then + local cell_path + if cell_path=$(__ren_get_cell_path "$cell"); then + if [[ -f "${cell_path}/flake.nix" ]]; then + __ren_log TRACE "Found cell flake. Adding GC roots for inputs from '${cell_path}'." + __ren_add_flake_input_gcroots "$cell_path" "$__layout_dir" + fi fi fi fi @@ -298,15 +374,18 @@ __ren_is_rebuild_needed() { echo 1 return fi - local watches=() - __ren_get_direnv_watches watches - for file in "${watches[@]}"; do - if [[ "$file" -nt "$profile_rc" ]]; then - __ren_log INFO "Cache invalidated by: $file" - echo 1 - return - fi - done + + if [ "$REN_DO_WATCH" = true ]; then + local watches=() + __ren_get_direnv_watches watches + for file in "${watches[@]}"; do + if [[ "$file" -nt "$profile_rc" ]]; then + __ren_log INFO "Cache invalidated by: $file" + echo 1 + return + fi + done + fi echo 0 } @@ -330,7 +409,11 @@ __ren_build_and_cache() { if build_output=$(__ren_nix print-dev-env --profile "$tmp_profile" "$flake_attr"); then __ren_clean_old_gcroots "$__layout_dir" echo "$build_output" >"$profile_rc" - __ren_update_gcroots "$__layout_dir" "$tmp_profile" "$profile" "$cell" + + # only add new gcroots if enabled, cleaning old is always fine + if [ "$REN_DO_GCROOTS" = true ]; then + __ren_update_gcroots "$__layout_dir" "$tmp_profile" "$profile" "$cell" + fi __ren_log TRACE "Cache for '$target_spec' renewed successfully." return 0 @@ -344,9 +427,9 @@ __ren_build_and_cache() { # ENTRYPOINTS # -# usage in .envrc: use_envreload +# usage in .envrc: use ren # can be `//cell/block/target` or a direct flake attr like `.#myShell` -use_envreload() { +use_ren() { if [[ -z ${REN_SKIP_VERSION_CHECK:-} ]]; then __ren_require_version "bash" "$BASH_VERSION" "$BASH_MIN_VERSION" __ren_require_cmd_version "direnv" "$DIRENV_MIN_VERSION" @@ -363,11 +446,13 @@ use_envreload() { local target_spec="${1-}" if [[ -z "$target_spec" ]]; then - __ren_log ERROR "use_envreload requires a target argument, e.g., //repo/devShells/default or .#myShell" + __ren_log ERROR "use ren requires a target argument, e.g., //repo/devShells/default or .#myShell" return 1 fi - __ren_setup_watches "$@" + if [ "$REN_DO_WATCH" = true ]; then + __ren_setup_watches "$@" + fi local __layout_dir profile profile_rc __layout_dir=$(direnv_layout_dir) @@ -391,6 +476,10 @@ use_envreload() { __ren_import_env "$profile_rc" } +use_rensa() { + use_ren "$@" +} + # initialize project environment variables immediately upon sourcing the script, # allows the user to use $REN_STATE etc. in .envrc __ren_init_project