diff --git a/src/modes/internal.activate.test.ts b/src/modes/internal.activate.test.ts index 13db4bcb..12cb2cfe 100644 --- a/src/modes/internal.activate.test.ts +++ b/src/modes/internal.activate.test.ts @@ -2,7 +2,7 @@ import { fixturesd, null_logger as logger } from "../utils/test-utils.ts" import { _internals as _devenv_internals } from "../utils/devenv.ts" import specimen0, { _internals } from "./internal.activate.ts" -import { assertRejects } from "deno/assert/mod.ts" +import { assertEquals, assertRejects } from "deno/assert/mod.ts" import * as mock from "deno/testing/mock.ts" import { SemVer, Path, utils, semver } from "pkgx" @@ -66,4 +66,11 @@ Deno.test("internal.activate.ts", async runner => { await runner.step("coverage++", () => { _internals.datadir() }) + + await runner.step("apply_userenv", () => { + const userenv = { PATH: "/foo/bar:$PATH" } + const env = { PATH: "/baz:$PATH"} + _internals.apply_userenv(env, userenv) + assertEquals(env.PATH, "/foo/bar:/baz:$PATH") + }) }) diff --git a/src/modes/internal.activate.ts b/src/modes/internal.activate.ts index e768f9c1..316ef6d6 100644 --- a/src/modes/internal.activate.ts +++ b/src/modes/internal.activate.ts @@ -7,7 +7,7 @@ import devenv from "../utils/devenv.ts" import undent from "outdent" export default async function(dir: Path, { powder, ...opts }: { powder: PackageRequirement[], logger: Logger }) { - const { install, construct_env, datadir, getenv } = _internals + const { install, construct_env, datadir, getenv, apply_userenv } = _internals if (!dir.isDirectory()) { throw new PkgxError(`not a directory: ${dir}`) @@ -37,13 +37,11 @@ export default async function(dir: Path, { powder, ...opts }: { powder: PackageR return installed.filter(x => set.has(x.project)) })(installations.pkgenv) - let rv = '' - - /// env specified in devenv files takes precedence - Object.assign(env, userenv) + // substitute or replace calculated env with user-supplied env from the keyfiles + apply_userenv(env, userenv) + let rv = '' for (const [key, value] of Object.entries(env)) { - const existing_value = getenv(key) if (value == existing_value) { delete env[key] @@ -118,9 +116,23 @@ export default async function(dir: Path, { powder, ...opts }: { powder: PackageR return [rv, rv_pkgenv] as [string, PackageRequirement[]] } +function apply_userenv(env: Record, userenv: Record) { + for (const [key, value] of Object.entries(userenv)) { + if (!(key in env) && !value.includes(`$${key}`) && !value.includes(`\${${key}}`)) { + /// user supplied env completely overrides this key or the key is empty + env[key] = value + } else { + env[key] = value + .replaceAll(`$${key}`, env[key]) + .replaceAll(`\${${key}}`, env[key]) + } + } +} + export const _internals = { install, construct_env, datadir: () => hooks.useConfig().data, - getenv: Deno.env.get + getenv: Deno.env.get, + apply_userenv }