mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 20:20:49 +00:00
Cleanup
This commit is contained in:
parent
1cf8fd1241
commit
d064d46668
32 changed files with 429 additions and 400 deletions
|
|
@ -3,8 +3,7 @@ import * as os from "os";
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { ECOSYSTEM_JS, ECOSYSTEM_PY } from "../config/settings.js";
|
||||
import { getSafeChainDir } from "../config/environmentVariables.js";
|
||||
export { getSafeChainDir };
|
||||
import { getSafeChainBaseDir } from "../config/safeChainDir.js";
|
||||
import { safeSpawn } from "../utils/safeSpawn.js";
|
||||
import { ui } from "../environment/userInteraction.js";
|
||||
|
||||
|
|
@ -125,12 +124,10 @@ export function getPackageManagerList() {
|
|||
|
||||
/**
|
||||
* Returns the safe-chain base directory.
|
||||
* Uses SAFE_CHAIN_DIR environment variable when set, otherwise defaults to ~/.safe-chain.
|
||||
* Uses the packaged binary location when available, otherwise defaults to ~/.safe-chain.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getSafeChainBaseDir() {
|
||||
return getSafeChainDir() ?? path.join(os.homedir(), ".safe-chain");
|
||||
}
|
||||
export { getSafeChainBaseDir };
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
|
|
|
|||
|
|
@ -185,64 +185,23 @@ describe("removeLinesMatchingPatternTests", () => {
|
|||
});
|
||||
|
||||
describe("getSafeChainBaseDir / getBinDir / getShimsDir / getScriptsDir", () => {
|
||||
const customDir = "/usr/local/.safe-chain";
|
||||
|
||||
let originalSafeChainDir;
|
||||
|
||||
beforeEach(() => {
|
||||
originalSafeChainDir = process.env.SAFE_CHAIN_DIR;
|
||||
delete process.env.SAFE_CHAIN_DIR;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalSafeChainDir !== undefined) {
|
||||
process.env.SAFE_CHAIN_DIR = originalSafeChainDir;
|
||||
} else {
|
||||
delete process.env.SAFE_CHAIN_DIR;
|
||||
}
|
||||
});
|
||||
|
||||
it("defaults base dir to ~/.safe-chain when SAFE_CHAIN_DIR is not set", async () => {
|
||||
it("defaults base dir to ~/.safe-chain when no packaged install dir is available", async () => {
|
||||
const { getSafeChainBaseDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getSafeChainBaseDir(), path.join(homedir(), ".safe-chain"));
|
||||
});
|
||||
|
||||
it("uses SAFE_CHAIN_DIR as base dir when set", async () => {
|
||||
process.env.SAFE_CHAIN_DIR = customDir;
|
||||
const { getSafeChainBaseDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getSafeChainBaseDir(), customDir);
|
||||
});
|
||||
|
||||
it("getBinDir returns ~/.safe-chain/bin by default", async () => {
|
||||
const { getBinDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getBinDir(), path.join(homedir(), ".safe-chain", "bin"));
|
||||
});
|
||||
|
||||
it("getBinDir returns custom dir + /bin when SAFE_CHAIN_DIR is set", async () => {
|
||||
process.env.SAFE_CHAIN_DIR = customDir;
|
||||
const { getBinDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getBinDir(), `${customDir}/bin`);
|
||||
});
|
||||
|
||||
it("getShimsDir returns ~/.safe-chain/shims by default", async () => {
|
||||
const { getShimsDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getShimsDir(), path.join(homedir(), ".safe-chain", "shims"));
|
||||
});
|
||||
|
||||
it("getShimsDir returns custom dir + /shims when SAFE_CHAIN_DIR is set", async () => {
|
||||
process.env.SAFE_CHAIN_DIR = customDir;
|
||||
const { getShimsDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getShimsDir(), `${customDir}/shims`);
|
||||
});
|
||||
|
||||
it("getScriptsDir returns ~/.safe-chain/scripts by default", async () => {
|
||||
const { getScriptsDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getScriptsDir(), path.join(homedir(), ".safe-chain", "scripts"));
|
||||
});
|
||||
|
||||
it("getScriptsDir returns custom dir + /scripts when SAFE_CHAIN_DIR is set", async () => {
|
||||
process.env.SAFE_CHAIN_DIR = customDir;
|
||||
const { getScriptsDir } = await import("./helpers.js");
|
||||
assert.strictEqual(getScriptsDir(), `${customDir}/scripts`);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Function to remove shim from PATH (POSIX-compliant)
|
||||
remove_shim_from_path() {
|
||||
_safe_chain_shims="{{SHIMS_DIR}}"
|
||||
_safe_chain_shims=$(CDPATH= cd -- "$(dirname -- "$0")" 2>/dev/null && pwd -P)
|
||||
echo "$PATH" | sed "s|${_safe_chain_shims}:||g"
|
||||
}
|
||||
|
||||
|
|
@ -13,11 +13,7 @@ if command -v safe-chain >/dev/null 2>&1; then
|
|||
PATH=$(remove_shim_from_path) exec safe-chain {{PACKAGE_MANAGER}} "$@"
|
||||
else
|
||||
# safe-chain is not reachable — warn the user so they know protection is inactive
|
||||
if [ -n "$SAFE_CHAIN_DIR" ]; then
|
||||
printf "\033[43;30mWarning:\033[0m safe-chain is not accessible. Check that '%s/bin' is readable and executable by the current user.\n" "$SAFE_CHAIN_DIR" >&2
|
||||
else
|
||||
printf "\033[43;30mWarning:\033[0m safe-chain is not available to protect you from installing malware. {{PACKAGE_MANAGER}} will run without it.\n" >&2
|
||||
fi
|
||||
printf "\033[43;30mWarning:\033[0m safe-chain is not available to protect you from installing malware. {{PACKAGE_MANAGER}} will run without it.\n" >&2
|
||||
|
||||
# Dynamically find original {{PACKAGE_MANAGER}} (excluding this shim directory)
|
||||
original_cmd=$(PATH=$(remove_shim_from_path) command -v {{PACKAGE_MANAGER}})
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ REM Generated wrapper for {{PACKAGE_MANAGER}} by safe-chain
|
|||
REM This wrapper intercepts {{PACKAGE_MANAGER}} calls for non-interactive environments
|
||||
|
||||
REM Remove shim directory from PATH to prevent infinite loops
|
||||
set "SHIM_DIR={{SHIMS_DIR}}"
|
||||
set "SHIM_DIR=%~dp0"
|
||||
if "%SHIM_DIR:~-1%"=="\" set "SHIM_DIR=%SHIM_DIR:~0,-1%"
|
||||
call set "CLEAN_PATH=%%PATH:%SHIM_DIR%;=%%"
|
||||
|
||||
REM Check if aikido command is available with clean PATH
|
||||
|
|
|
|||
|
|
@ -69,8 +69,7 @@ function createUnixShims(shimsDir) {
|
|||
for (const toolInfo of getToolsToSetup()) {
|
||||
const shimContent = template
|
||||
.replaceAll("{{PACKAGE_MANAGER}}", toolInfo.tool)
|
||||
.replaceAll("{{AIKIDO_COMMAND}}", toolInfo.aikidoCommand)
|
||||
.replaceAll("{{SHIMS_DIR}}", shimsDir);
|
||||
.replaceAll("{{AIKIDO_COMMAND}}", toolInfo.aikidoCommand);
|
||||
|
||||
const shimPath = path.join(shimsDir, toolInfo.tool);
|
||||
fs.writeFileSync(shimPath, shimContent, "utf-8");
|
||||
|
|
@ -109,8 +108,7 @@ function createWindowsShims(shimsDir) {
|
|||
for (const toolInfo of getToolsToSetup()) {
|
||||
const shimContent = template
|
||||
.replaceAll("{{PACKAGE_MANAGER}}", toolInfo.tool)
|
||||
.replaceAll("{{AIKIDO_COMMAND}}", toolInfo.aikidoCommand)
|
||||
.replaceAll("{{SHIMS_DIR}}", shimsDir);
|
||||
.replaceAll("{{AIKIDO_COMMAND}}", toolInfo.aikidoCommand);
|
||||
|
||||
const shimPath = `${shimsDir}/${toolInfo.tool}.cmd`;
|
||||
fs.writeFileSync(shimPath, shimContent, "utf-8");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
# Guard against PATH separator injection: reject SAFE_CHAIN_DIR values containing ':'
|
||||
set -l safe_chain_base $HOME/.safe-chain
|
||||
if set -q SAFE_CHAIN_DIR; and not string match -q '*:*' -- $SAFE_CHAIN_DIR
|
||||
set safe_chain_base $SAFE_CHAIN_DIR
|
||||
end
|
||||
set -l safe_chain_script (status filename)
|
||||
set -l safe_chain_base (path dirname (path dirname $safe_chain_script))
|
||||
set -gx PATH $PATH $safe_chain_base/bin
|
||||
|
||||
function npx
|
||||
|
|
|
|||
|
|
@ -1,10 +1,22 @@
|
|||
# Guard against PATH separator injection: reject SAFE_CHAIN_DIR values containing ':'
|
||||
case "${SAFE_CHAIN_DIR}" in
|
||||
*:*) _sc_base="${HOME}/.safe-chain" ;;
|
||||
*) _sc_base="${SAFE_CHAIN_DIR:-${HOME}/.safe-chain}" ;;
|
||||
esac
|
||||
_get_safe_chain_script_path() {
|
||||
if [ -n "${BASH_SOURCE[0]:-}" ]; then
|
||||
printf '%s\n' "${BASH_SOURCE[0]}"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "${ZSH_VERSION:-}" ]; then
|
||||
eval 'printf "%s\n" "${(%):-%N}"'
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s\n' "$0"
|
||||
}
|
||||
|
||||
_sc_script_path="$(_get_safe_chain_script_path)"
|
||||
_sc_scripts_dir=$(CDPATH= cd -- "$(dirname -- "$_sc_script_path")" 2>/dev/null && pwd -P)
|
||||
_sc_base=$(dirname -- "$_sc_scripts_dir")
|
||||
export PATH="$PATH:${_sc_base}/bin"
|
||||
unset _sc_base
|
||||
unset _sc_base _sc_script_path _sc_scripts_dir
|
||||
|
||||
function npx() {
|
||||
wrapSafeChainCommand "npx" "$@"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
# $IsWindows is only available in PowerShell Core 6.0+. If it doesn't exist, assume Windows PowerShell
|
||||
$isWindowsPlatform = if (Test-Path variable:IsWindows) { $IsWindows } else { $true }
|
||||
$pathSeparator = if ($isWindowsPlatform) { ';' } else { ':' }
|
||||
# Guard against PATH separator injection: reject SAFE_CHAIN_DIR values containing the path separator
|
||||
$safeChainBase = if ($env:SAFE_CHAIN_DIR -and -not $env:SAFE_CHAIN_DIR.Contains($pathSeparator)) { $env:SAFE_CHAIN_DIR } else { Join-Path $HOME '.safe-chain' }
|
||||
$safeChainBase = Split-Path -Parent $PSScriptRoot
|
||||
$safeChainBin = Join-Path $safeChainBase 'bin'
|
||||
$env:PATH = "$env:PATH$pathSeparator$safeChainBin"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import {
|
|||
doesExecutableExistOnSystem,
|
||||
removeLinesMatchingPattern,
|
||||
getScriptsDir,
|
||||
getSafeChainDir,
|
||||
} from "../helpers.js";
|
||||
import { execSync, spawnSync } from "child_process";
|
||||
import * as os from "os";
|
||||
|
|
@ -54,15 +53,6 @@ function teardown(tools) {
|
|||
function setup() {
|
||||
const startupFile = getStartupFile();
|
||||
|
||||
const customDir = getSafeChainDir();
|
||||
if (customDir) {
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`export SAFE_CHAIN_DIR="${customDir}" # Safe-chain installation directory`,
|
||||
eol
|
||||
);
|
||||
}
|
||||
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`source ${path.join(getScriptsDir(), "init-posix.sh")} # Safe-chain bash initialization script`,
|
||||
|
|
@ -143,18 +133,7 @@ function cygpathw(path) {
|
|||
|
||||
/** @param {string} preamble */
|
||||
function buildManualInstructions(preamble) {
|
||||
const customDir = getSafeChainDir();
|
||||
const instructions = [preamble];
|
||||
|
||||
if (customDir) {
|
||||
instructions.push(
|
||||
` export SAFE_CHAIN_DIR="${customDir}"`,
|
||||
` source ${path.join(getScriptsDir(), "init-posix.sh")}`,
|
||||
);
|
||||
} else {
|
||||
instructions.push(` source ~/.safe-chain/scripts/init-posix.sh`);
|
||||
}
|
||||
|
||||
const instructions = [preamble, ` source ${path.join(getScriptsDir(), "init-posix.sh")}`];
|
||||
instructions.push(`Then restart your terminal or run: source ~/.bashrc`);
|
||||
return instructions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ describe("Bash shell integration", () => {
|
|||
let bash;
|
||||
let windowsCygwinPath = "";
|
||||
let platform = "linux";
|
||||
let getSafeChainDirResult = undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create temporary startup file for testing
|
||||
|
|
@ -21,7 +20,6 @@ describe("Bash shell integration", () => {
|
|||
namedExports: {
|
||||
doesExecutableExistOnSystem: () => true,
|
||||
getScriptsDir: () => "/test-home/.safe-chain/scripts",
|
||||
getSafeChainDir: () => getSafeChainDirResult,
|
||||
addLineToFile: (filePath, line) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, "", "utf-8");
|
||||
|
|
@ -91,7 +89,6 @@ describe("Bash shell integration", () => {
|
|||
// Reset mocks
|
||||
mock.reset();
|
||||
platform = "linux";
|
||||
getSafeChainDirResult = undefined;
|
||||
});
|
||||
|
||||
describe("isInstalled", () => {
|
||||
|
|
@ -203,26 +200,18 @@ describe("Bash shell integration", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SAFE_CHAIN_DIR", () => {
|
||||
it("should write export line to rc file when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
describe("custom install dir", () => {
|
||||
it("writes only the source line to the rc file", () => {
|
||||
bash.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(
|
||||
content.includes('export SAFE_CHAIN_DIR="/custom/safe-chain" # Safe-chain installation directory')
|
||||
content.includes("source /test-home/.safe-chain/scripts/init-posix.sh")
|
||||
);
|
||||
});
|
||||
|
||||
it("should not write export line when no custom dir is set", () => {
|
||||
getSafeChainDirResult = undefined;
|
||||
bash.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should remove export line on teardown", () => {
|
||||
it("removes legacy export lines on teardown", () => {
|
||||
const initialContent = [
|
||||
'#!/bin/bash',
|
||||
'export SAFE_CHAIN_DIR="/custom/safe-chain" # Safe-chain installation directory',
|
||||
|
|
@ -236,12 +225,9 @@ describe("Bash shell integration", () => {
|
|||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should show custom manual setup instructions when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
|
||||
it("shows source-only manual setup instructions", () => {
|
||||
assert.deepStrictEqual(bash.getManualSetupInstructions(), [
|
||||
"Add the following line to your ~/.bashrc file:",
|
||||
' export SAFE_CHAIN_DIR="/custom/safe-chain"',
|
||||
" source /test-home/.safe-chain/scripts/init-posix.sh",
|
||||
"Then restart your terminal or run: source ~/.bashrc",
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import {
|
|||
doesExecutableExistOnSystem,
|
||||
removeLinesMatchingPattern,
|
||||
getScriptsDir,
|
||||
getSafeChainDir,
|
||||
} from "../helpers.js";
|
||||
import { execSync } from "child_process";
|
||||
import path from "path";
|
||||
|
|
@ -53,15 +52,6 @@ function teardown(tools) {
|
|||
function setup() {
|
||||
const startupFile = getStartupFile();
|
||||
|
||||
const customDir = getSafeChainDir();
|
||||
if (customDir) {
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`set -gx SAFE_CHAIN_DIR "${customDir}" # Safe-chain installation directory`,
|
||||
eol
|
||||
);
|
||||
}
|
||||
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`source ${path.join(getScriptsDir(), "init-fish.fish")} # Safe-chain Fish initialization script`,
|
||||
|
|
@ -86,18 +76,7 @@ function getStartupFile() {
|
|||
|
||||
/** @param {string} preamble */
|
||||
function buildManualInstructions(preamble) {
|
||||
const customDir = getSafeChainDir();
|
||||
const instructions = [preamble];
|
||||
|
||||
if (customDir) {
|
||||
instructions.push(
|
||||
` set -gx SAFE_CHAIN_DIR "${customDir}"`,
|
||||
` source ${path.join(getScriptsDir(), "init-fish.fish")}`,
|
||||
);
|
||||
} else {
|
||||
instructions.push(` source ~/.safe-chain/scripts/init-fish.fish`);
|
||||
}
|
||||
|
||||
const instructions = [preamble, ` source ${path.join(getScriptsDir(), "init-fish.fish")}`];
|
||||
instructions.push(
|
||||
`Then restart your terminal or run: source ~/.config/fish/config.fish`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { knownAikidoTools } from "../helpers.js";
|
|||
describe("Fish shell integration", () => {
|
||||
let mockStartupFile;
|
||||
let fish;
|
||||
let getSafeChainDirResult = undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create temporary startup file for testing
|
||||
|
|
@ -19,7 +18,6 @@ describe("Fish shell integration", () => {
|
|||
namedExports: {
|
||||
doesExecutableExistOnSystem: () => true,
|
||||
getScriptsDir: () => "/test-home/.safe-chain/scripts",
|
||||
getSafeChainDir: () => getSafeChainDirResult,
|
||||
addLineToFile: (filePath, line) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, "", "utf-8");
|
||||
|
|
@ -55,7 +53,6 @@ describe("Fish shell integration", () => {
|
|||
|
||||
// Reset mocks
|
||||
mock.reset();
|
||||
getSafeChainDirResult = undefined;
|
||||
});
|
||||
|
||||
describe("isInstalled", () => {
|
||||
|
|
@ -156,26 +153,18 @@ describe("Fish shell integration", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SAFE_CHAIN_DIR", () => {
|
||||
it("should write set line to config file when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
describe("custom install dir", () => {
|
||||
it("writes only the source line to the config file", () => {
|
||||
fish.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(
|
||||
content.includes('set -gx SAFE_CHAIN_DIR "/custom/safe-chain" # Safe-chain installation directory')
|
||||
content.includes("source /test-home/.safe-chain/scripts/init-fish.fish")
|
||||
);
|
||||
});
|
||||
|
||||
it("should not write set line when no custom dir is set", () => {
|
||||
getSafeChainDirResult = undefined;
|
||||
fish.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should remove set line on teardown", () => {
|
||||
it("removes legacy set lines on teardown", () => {
|
||||
const initialContent = [
|
||||
'set -gx SAFE_CHAIN_DIR "/custom/safe-chain" # Safe-chain installation directory',
|
||||
"source /test-home/.safe-chain/scripts/init-fish.fish # Safe-chain Fish initialization script",
|
||||
|
|
@ -188,12 +177,9 @@ describe("Fish shell integration", () => {
|
|||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should show custom manual setup instructions when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
|
||||
it("shows source-only manual setup instructions", () => {
|
||||
assert.deepStrictEqual(fish.getManualSetupInstructions(), [
|
||||
"Add the following line to your ~/.config/fish/config.fish file:",
|
||||
' set -gx SAFE_CHAIN_DIR "/custom/safe-chain"',
|
||||
" source /test-home/.safe-chain/scripts/init-fish.fish",
|
||||
"Then restart your terminal or run: source ~/.config/fish/config.fish",
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import {
|
|||
removeLinesMatchingPattern,
|
||||
validatePowerShellExecutionPolicy,
|
||||
getScriptsDir,
|
||||
getSafeChainDir,
|
||||
} from "../helpers.js";
|
||||
import { execSync } from "child_process";
|
||||
import path from "path";
|
||||
|
|
@ -58,14 +57,6 @@ async function setup() {
|
|||
|
||||
const startupFile = getStartupFile();
|
||||
|
||||
const customDir = getSafeChainDir();
|
||||
if (customDir) {
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`$env:SAFE_CHAIN_DIR = '${customDir}' # Safe-chain installation directory`,
|
||||
);
|
||||
}
|
||||
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`. "${path.join(getScriptsDir(), "init-pwsh.ps1")}" # Safe-chain PowerShell initialization script`,
|
||||
|
|
@ -89,18 +80,7 @@ function getStartupFile() {
|
|||
|
||||
/** @param {string} preamble */
|
||||
function buildManualInstructions(preamble) {
|
||||
const customDir = getSafeChainDir();
|
||||
const instructions = [preamble];
|
||||
|
||||
if (customDir) {
|
||||
instructions.push(
|
||||
` $env:SAFE_CHAIN_DIR = '${customDir}'`,
|
||||
` . "${path.join(getScriptsDir(), "init-pwsh.ps1")}"`,
|
||||
);
|
||||
} else {
|
||||
instructions.push(` . "$HOME\\.safe-chain\\scripts\\init-pwsh.ps1"`);
|
||||
}
|
||||
|
||||
const instructions = [preamble, ` . "${path.join(getScriptsDir(), "init-pwsh.ps1")}"`];
|
||||
instructions.push(`Then restart your terminal or run: . $PROFILE`);
|
||||
return instructions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ describe("PowerShell Core shell integration", () => {
|
|||
let mockStartupFile;
|
||||
let powershell;
|
||||
let executionPolicyResult;
|
||||
let getSafeChainDirResult = undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create temporary startup file for testing
|
||||
|
|
@ -27,7 +26,6 @@ describe("PowerShell Core shell integration", () => {
|
|||
mock.module("../helpers.js", {
|
||||
namedExports: {
|
||||
doesExecutableExistOnSystem: () => true,
|
||||
getSafeChainDir: () => getSafeChainDirResult,
|
||||
addLineToFile: (filePath, line) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, "", "utf-8");
|
||||
|
|
@ -65,7 +63,6 @@ describe("PowerShell Core shell integration", () => {
|
|||
|
||||
// Reset mocks
|
||||
mock.reset();
|
||||
getSafeChainDirResult = undefined;
|
||||
});
|
||||
|
||||
describe("isInstalled", () => {
|
||||
|
|
@ -209,26 +206,18 @@ describe("PowerShell Core shell integration", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SAFE_CHAIN_DIR", () => {
|
||||
it("should write $env:SAFE_CHAIN_DIR line to profile when custom dir is set", async () => {
|
||||
getSafeChainDirResult = "C:\\custom\\safe-chain";
|
||||
describe("custom install dir", () => {
|
||||
it("writes only the source line to the profile", async () => {
|
||||
await powershell.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(
|
||||
content.includes("$env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain' # Safe-chain installation directory")
|
||||
content.includes('. "/test-home/.safe-chain/scripts/init-pwsh.ps1"')
|
||||
);
|
||||
});
|
||||
|
||||
it("should not write $env:SAFE_CHAIN_DIR line when no custom dir is set", async () => {
|
||||
getSafeChainDirResult = undefined;
|
||||
await powershell.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should remove $env:SAFE_CHAIN_DIR line on teardown", () => {
|
||||
it("removes legacy env lines on teardown", () => {
|
||||
const initialContent = [
|
||||
"# PowerShell profile",
|
||||
"$env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain' # Safe-chain installation directory",
|
||||
|
|
@ -242,12 +231,9 @@ describe("PowerShell Core shell integration", () => {
|
|||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should show custom manual setup instructions when custom dir is set", () => {
|
||||
getSafeChainDirResult = "C:\\custom\\safe-chain";
|
||||
|
||||
it("shows source-only manual setup instructions", () => {
|
||||
assert.deepStrictEqual(powershell.getManualSetupInstructions(), [
|
||||
'Add the following line to your PowerShell profile (run "echo $PROFILE" to find its location):',
|
||||
" $env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain'",
|
||||
' . "/test-home/.safe-chain/scripts/init-pwsh.ps1"',
|
||||
"Then restart your terminal or run: . $PROFILE",
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import {
|
|||
removeLinesMatchingPattern,
|
||||
validatePowerShellExecutionPolicy,
|
||||
getScriptsDir,
|
||||
getSafeChainDir,
|
||||
} from "../helpers.js";
|
||||
import { execSync } from "child_process";
|
||||
import path from "path";
|
||||
|
|
@ -58,14 +57,6 @@ async function setup() {
|
|||
|
||||
const startupFile = getStartupFile();
|
||||
|
||||
const customDir = getSafeChainDir();
|
||||
if (customDir) {
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`$env:SAFE_CHAIN_DIR = '${customDir}' # Safe-chain installation directory`,
|
||||
);
|
||||
}
|
||||
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`. "${path.join(getScriptsDir(), "init-pwsh.ps1")}" # Safe-chain PowerShell initialization script`,
|
||||
|
|
@ -89,18 +80,7 @@ function getStartupFile() {
|
|||
|
||||
/** @param {string} preamble */
|
||||
function buildManualInstructions(preamble) {
|
||||
const customDir = getSafeChainDir();
|
||||
const instructions = [preamble];
|
||||
|
||||
if (customDir) {
|
||||
instructions.push(
|
||||
` $env:SAFE_CHAIN_DIR = '${customDir}'`,
|
||||
` . "${path.join(getScriptsDir(), "init-pwsh.ps1")}"`,
|
||||
);
|
||||
} else {
|
||||
instructions.push(` . "$HOME\\.safe-chain\\scripts\\init-pwsh.ps1"`);
|
||||
}
|
||||
|
||||
const instructions = [preamble, ` . "${path.join(getScriptsDir(), "init-pwsh.ps1")}"`];
|
||||
instructions.push(`Then restart your terminal or run: . $PROFILE`);
|
||||
return instructions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ describe("Windows PowerShell shell integration", () => {
|
|||
let mockStartupFile;
|
||||
let windowsPowershell;
|
||||
let executionPolicyResult;
|
||||
let getSafeChainDirResult = undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create temporary startup file for testing
|
||||
|
|
@ -27,7 +26,6 @@ describe("Windows PowerShell shell integration", () => {
|
|||
mock.module("../helpers.js", {
|
||||
namedExports: {
|
||||
doesExecutableExistOnSystem: () => true,
|
||||
getSafeChainDir: () => getSafeChainDirResult,
|
||||
addLineToFile: (filePath, line) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, "", "utf-8");
|
||||
|
|
@ -65,7 +63,6 @@ describe("Windows PowerShell shell integration", () => {
|
|||
|
||||
// Reset mocks
|
||||
mock.reset();
|
||||
getSafeChainDirResult = undefined;
|
||||
});
|
||||
|
||||
describe("isInstalled", () => {
|
||||
|
|
@ -209,26 +206,18 @@ describe("Windows PowerShell shell integration", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SAFE_CHAIN_DIR", () => {
|
||||
it("should write $env:SAFE_CHAIN_DIR line to profile when custom dir is set", async () => {
|
||||
getSafeChainDirResult = "C:\\custom\\safe-chain";
|
||||
describe("custom install dir", () => {
|
||||
it("writes only the source line to the profile", async () => {
|
||||
await windowsPowershell.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(
|
||||
content.includes("$env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain' # Safe-chain installation directory")
|
||||
content.includes('. "/test-home/.safe-chain/scripts/init-pwsh.ps1"')
|
||||
);
|
||||
});
|
||||
|
||||
it("should not write $env:SAFE_CHAIN_DIR line when no custom dir is set", async () => {
|
||||
getSafeChainDirResult = undefined;
|
||||
await windowsPowershell.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should remove $env:SAFE_CHAIN_DIR line on teardown", () => {
|
||||
it("removes legacy env lines on teardown", () => {
|
||||
const initialContent = [
|
||||
"# Windows PowerShell profile",
|
||||
"$env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain' # Safe-chain installation directory",
|
||||
|
|
@ -242,12 +231,9 @@ describe("Windows PowerShell shell integration", () => {
|
|||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should show custom manual teardown instructions when custom dir is set", () => {
|
||||
getSafeChainDirResult = "C:\\custom\\safe-chain";
|
||||
|
||||
it("shows source-only manual teardown instructions", () => {
|
||||
assert.deepStrictEqual(windowsPowershell.getManualTeardownInstructions(), [
|
||||
'Remove the following line from your PowerShell profile (run "echo $PROFILE" to find its location):',
|
||||
" $env:SAFE_CHAIN_DIR = 'C:\\custom\\safe-chain'",
|
||||
' . "/test-home/.safe-chain/scripts/init-pwsh.ps1"',
|
||||
"Then restart your terminal or run: . $PROFILE",
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import {
|
|||
doesExecutableExistOnSystem,
|
||||
removeLinesMatchingPattern,
|
||||
getScriptsDir,
|
||||
getSafeChainDir,
|
||||
} from "../helpers.js";
|
||||
import { execSync } from "child_process";
|
||||
import path from "path";
|
||||
|
|
@ -53,15 +52,6 @@ function teardown(tools) {
|
|||
function setup() {
|
||||
const startupFile = getStartupFile();
|
||||
|
||||
const customDir = getSafeChainDir();
|
||||
if (customDir) {
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`export SAFE_CHAIN_DIR="${customDir}" # Safe-chain installation directory`,
|
||||
eol
|
||||
);
|
||||
}
|
||||
|
||||
addLineToFile(
|
||||
startupFile,
|
||||
`source ${path.join(getScriptsDir(), "init-posix.sh")} # Safe-chain Zsh initialization script`,
|
||||
|
|
@ -86,18 +76,7 @@ function getStartupFile() {
|
|||
|
||||
/** @param {string} preamble */
|
||||
function buildManualInstructions(preamble) {
|
||||
const customDir = getSafeChainDir();
|
||||
const instructions = [preamble];
|
||||
|
||||
if (customDir) {
|
||||
instructions.push(
|
||||
` export SAFE_CHAIN_DIR="${customDir}"`,
|
||||
` source ${path.join(getScriptsDir(), "init-posix.sh")}`,
|
||||
);
|
||||
} else {
|
||||
instructions.push(` source ~/.safe-chain/scripts/init-posix.sh`);
|
||||
}
|
||||
|
||||
const instructions = [preamble, ` source ${path.join(getScriptsDir(), "init-posix.sh")}`];
|
||||
instructions.push(`Then restart your terminal or run: source ~/.zshrc`);
|
||||
return instructions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import { knownAikidoTools } from "../helpers.js";
|
|||
describe("Zsh shell integration", () => {
|
||||
let mockStartupFile;
|
||||
let zsh;
|
||||
let getSafeChainDirResult = undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create temporary startup file for testing
|
||||
|
|
@ -19,7 +18,6 @@ describe("Zsh shell integration", () => {
|
|||
namedExports: {
|
||||
doesExecutableExistOnSystem: () => true,
|
||||
getScriptsDir: () => "/test-home/.safe-chain/scripts",
|
||||
getSafeChainDir: () => getSafeChainDirResult,
|
||||
addLineToFile: (filePath, line) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, "", "utf-8");
|
||||
|
|
@ -55,7 +53,6 @@ describe("Zsh shell integration", () => {
|
|||
|
||||
// Reset mocks
|
||||
mock.reset();
|
||||
getSafeChainDirResult = undefined;
|
||||
});
|
||||
|
||||
describe("isInstalled", () => {
|
||||
|
|
@ -174,26 +171,18 @@ describe("Zsh shell integration", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SAFE_CHAIN_DIR", () => {
|
||||
it("should write export line to rc file when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
describe("custom install dir", () => {
|
||||
it("writes only the source line to the rc file", () => {
|
||||
zsh.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(
|
||||
content.includes('export SAFE_CHAIN_DIR="/custom/safe-chain" # Safe-chain installation directory')
|
||||
content.includes("source /test-home/.safe-chain/scripts/init-posix.sh")
|
||||
);
|
||||
});
|
||||
|
||||
it("should not write export line when no custom dir is set", () => {
|
||||
getSafeChainDirResult = undefined;
|
||||
zsh.setup();
|
||||
|
||||
const content = fs.readFileSync(mockStartupFile, "utf-8");
|
||||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should remove export line on teardown", () => {
|
||||
it("removes legacy export lines on teardown", () => {
|
||||
const initialContent = [
|
||||
"#!/bin/zsh",
|
||||
'export SAFE_CHAIN_DIR="/custom/safe-chain" # Safe-chain installation directory',
|
||||
|
|
@ -207,12 +196,9 @@ describe("Zsh shell integration", () => {
|
|||
assert.ok(!content.includes("SAFE_CHAIN_DIR"));
|
||||
});
|
||||
|
||||
it("should show custom manual teardown instructions when custom dir is set", () => {
|
||||
getSafeChainDirResult = "/custom/safe-chain";
|
||||
|
||||
it("shows source-only manual teardown instructions", () => {
|
||||
assert.deepStrictEqual(zsh.getManualTeardownInstructions(), [
|
||||
"Remove the following line from your ~/.zshrc file:",
|
||||
' export SAFE_CHAIN_DIR="/custom/safe-chain"',
|
||||
" source /test-home/.safe-chain/scripts/init-posix.sh",
|
||||
"Then restart your terminal or run: source ~/.zshrc",
|
||||
]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue