mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
WIP
This commit is contained in:
parent
fa4c46c23d
commit
f400c5576a
12 changed files with 59 additions and 213 deletions
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -2096,6 +2096,8 @@
|
|||
"aikido-npx": "bin/aikido-npx.js",
|
||||
"aikido-pip": "bin/aikido-pip.js",
|
||||
"aikido-pip3": "bin/aikido-pip3.js",
|
||||
"aikido-python": "bin/aikido-python.js",
|
||||
"aikido-python3": "bin/aikido-python3.js",
|
||||
"aikido-pnpm": "bin/aikido-pnpm.js",
|
||||
"aikido-pnpx": "bin/aikido-pnpx.js",
|
||||
"aikido-yarn": "bin/aikido-yarn.js",
|
||||
|
|
|
|||
22
packages/safe-chain/bin/aikido-python.js
Normal file
22
packages/safe-chain/bin/aikido-python.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
|
||||
import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js";
|
||||
import { setEcoSystem, ECOSYSTEM_PY } from "../src/config/settings.js";
|
||||
import { main } from "../src/main.js";
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
|
||||
const supportedArgs = ["pip", "pip3"];
|
||||
|
||||
if (argv[0] === "-m" && argv[1] && supportedArgs.includes(argv[1])) {
|
||||
setEcoSystem(ECOSYSTEM_PY);
|
||||
|
||||
initializePackageManager(argv[1]);
|
||||
var exitCode = await main(argv.slice(2));
|
||||
process.exit(exitCode);
|
||||
} else {
|
||||
// Fallback: run the real python
|
||||
const { spawn } = await import("child_process");
|
||||
spawn("python", argv, { stdio: "inherit" });
|
||||
}
|
||||
22
packages/safe-chain/bin/aikido-python3.js
Normal file
22
packages/safe-chain/bin/aikido-python3.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
|
||||
import { initializePackageManager } from "../src/packagemanager/currentPackageManager.js";
|
||||
import { setEcoSystem, ECOSYSTEM_PY } from "../src/config/settings.js";
|
||||
import { main } from "../src/main.js";
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
|
||||
const supportedArgs = ["pip", "pip3"];
|
||||
|
||||
if (argv[0] === "-m" && argv[1] && supportedArgs.includes(argv[1])) {
|
||||
setEcoSystem(ECOSYSTEM_PY);
|
||||
// python3 -m pip or python3 -m pip3: always use pip3 package manager
|
||||
initializePackageManager("pip3");
|
||||
var exitCode = await main(argv.slice(2));
|
||||
process.exit(exitCode);
|
||||
} else {
|
||||
// Fallback: run the real python3
|
||||
const { spawn } = await import("child_process");
|
||||
spawn("python3", argv, { stdio: "inherit" });
|
||||
}
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
"aikido-bunx": "bin/aikido-bunx.js",
|
||||
"aikido-pip": "bin/aikido-pip.js",
|
||||
"aikido-pip3": "bin/aikido-pip3.js",
|
||||
"aikido-python": "bin/aikido-python.js",
|
||||
"aikido-python3": "bin/aikido-python3.js",
|
||||
"safe-chain": "bin/safe-chain.js"
|
||||
},
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ export const knownAikidoTools = [
|
|||
{ tool: "bunx", aikidoCommand: "aikido-bunx" },
|
||||
{ tool: "pip", aikidoCommand: "aikido-pip" },
|
||||
{ tool: "pip3", aikidoCommand: "aikido-pip3" },
|
||||
{ tool: "python", aikidoCommand: "aikido-python" },
|
||||
{ tool: "python3", aikidoCommand: "aikido-python3" },
|
||||
// When adding a new tool here, also update the documentation for the new tool in the README.md
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Generated wrapper for python/python3 by safe-chain
|
||||
# Intercepts `python[3] -m pip[...]` in CI environments
|
||||
|
||||
# Function to remove shim from PATH (POSIX-compliant)
|
||||
remove_shim_from_path() {
|
||||
echo "$PATH" | sed "s|$HOME/.safe-chain/shims:||g"
|
||||
}
|
||||
|
||||
# Determine which python variant we were invoked as based on the script name
|
||||
invoked=$(basename "$0")
|
||||
|
||||
# If invoked as `python -m pip[...]` or `python3 -m pip[...]`, route to aikido
|
||||
if [ "$1" = "-m" ] && [ -n "$2" ] && echo "$2" | grep -Eq '^pip(3)?$'; then
|
||||
mod="$2"
|
||||
shift 2
|
||||
if [ "$invoked" = "python3" ] || [ "$mod" = "pip3" ]; then
|
||||
PATH=$(remove_shim_from_path) exec aikido-pip3 "$@"
|
||||
else
|
||||
PATH=$(remove_shim_from_path) exec aikido-pip "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Otherwise, find and exec the real python/python3 matching the invoked name
|
||||
original_cmd=$(PATH=$(remove_shim_from_path) command -v "$invoked")
|
||||
if [ -n "$original_cmd" ]; then
|
||||
exec "$original_cmd" "$@"
|
||||
else
|
||||
echo "Error: Could not find original $invoked" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -7,6 +7,8 @@ remove_shim_from_path() {
|
|||
echo "$PATH" | sed "s|$HOME/.safe-chain/shims:||g"
|
||||
}
|
||||
|
||||
echo "[safe-chain debug] command -v {{AIKIDO_COMMAND}} (raw PATH): $(command -v {{AIKIDO_COMMAND}} 2>/dev/null || echo notfound)" >&2
|
||||
echo "[safe-chain debug] PATH (raw): $PATH" >&2
|
||||
if command -v {{AIKIDO_COMMAND}} >/dev/null 2>&1; then
|
||||
# Remove shim directory from PATH when calling {{AIKIDO_COMMAND}} to prevent infinite loops
|
||||
PATH=$(remove_shim_from_path) exec {{AIKIDO_COMMAND}} "$@"
|
||||
|
|
@ -19,4 +21,4 @@ else
|
|||
echo "Error: Could not find original {{PACKAGE_MANAGER}}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
@echo off
|
||||
REM Generated wrapper for python/python3 by safe-chain
|
||||
REM Intercepts `python[3] -m pip[...]` in CI environments
|
||||
|
||||
REM Remove shim directory from PATH to prevent infinite loops
|
||||
set "SHIM_DIR=%USERPROFILE%\.safe-chain\shims"
|
||||
call set "CLEAN_PATH=%%PATH:%SHIM_DIR%;=%%"
|
||||
|
||||
REM Determine invoked name (python or python3) from the script name
|
||||
set "INVOKED=%~n0"
|
||||
|
||||
REM Check for -m pip or -m pip3 without parentheses to avoid parser issues
|
||||
if /I "%1" NEQ "-m" goto FALLBACK
|
||||
|
||||
set "SECOND=%2"
|
||||
if /I "%SECOND%"=="pip3" goto CALL_PIP3
|
||||
if /I "%SECOND%"=="pip" goto CALL_PIP
|
||||
goto FALLBACK
|
||||
|
||||
:CALL_PIP3
|
||||
shift
|
||||
shift
|
||||
set "PATH=%CLEAN_PATH%" & aikido-pip3 %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
goto :eof
|
||||
|
||||
:CALL_PIP
|
||||
shift
|
||||
shift
|
||||
if /I "%INVOKED%"=="python3" (
|
||||
set "PATH=%CLEAN_PATH%" & aikido-pip3 %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
) else (
|
||||
set "PATH=%CLEAN_PATH%" & aikido-pip %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM Fallback to real python/python3 matching the invoked name
|
||||
:FALLBACK
|
||||
for /f "tokens=*" %%i in ('set "PATH=%CLEAN_PATH%" ^& where %INVOKED% 2^>nul') do (
|
||||
"%%i" %*
|
||||
goto :eof
|
||||
)
|
||||
|
||||
echo Error: Could not find original %INVOKED% 1>&2
|
||||
exit /b 1
|
||||
|
|
@ -66,53 +66,12 @@ function createUnixShims(shimsDir) {
|
|||
created++;
|
||||
}
|
||||
|
||||
// Also create python and python3 shims to support `python[3] -m pip[3]` in CI
|
||||
createUnixPythonShims(shimsDir);
|
||||
|
||||
ui.writeInformation(
|
||||
`Created ${created} Unix shim(s) in ${shimsDir}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} shimsDir
|
||||
*/
|
||||
function createUnixPythonShims(shimsDir) {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const entries = [
|
||||
{
|
||||
name: "python",
|
||||
template: path.resolve(
|
||||
__dirname,
|
||||
"path-wrappers",
|
||||
"templates",
|
||||
"unix-python-wrapper.template.sh"
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "python3",
|
||||
template: path.resolve(
|
||||
__dirname,
|
||||
"path-wrappers",
|
||||
"templates",
|
||||
"unix-python-wrapper.template.sh"
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (!fs.existsSync(entry.template)) {
|
||||
ui.writeError(`Template file not found: ${entry.template}`);
|
||||
continue;
|
||||
}
|
||||
const shimContent = fs.readFileSync(entry.template, "utf-8");
|
||||
const shimPath = `${shimsDir}/${entry.name}`;
|
||||
fs.writeFileSync(shimPath, shimContent, "utf-8");
|
||||
fs.chmodSync(shimPath, 0o755);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} shimsDir
|
||||
|
|
@ -149,53 +108,11 @@ function createWindowsShims(shimsDir) {
|
|||
created++;
|
||||
}
|
||||
|
||||
// Also create python and python3 shims for Windows to support `python[3] -m pip[3]` in CI
|
||||
createWindowsPythonShims(shimsDir);
|
||||
|
||||
ui.writeInformation(
|
||||
`Created ${created} Windows shim(s) in ${shimsDir}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} shimsDir
|
||||
*/
|
||||
function createWindowsPythonShims(shimsDir) {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const entries = [
|
||||
{
|
||||
name: "python.cmd",
|
||||
template: path.resolve(
|
||||
__dirname,
|
||||
"path-wrappers",
|
||||
"templates",
|
||||
"windows-python-wrapper.template.cmd"
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "python3.cmd",
|
||||
template: path.resolve(
|
||||
__dirname,
|
||||
"path-wrappers",
|
||||
"templates",
|
||||
"windows-python-wrapper.template.cmd"
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (!fs.existsSync(entry.template)) {
|
||||
ui.writeError(`Windows template file not found: ${entry.template}`);
|
||||
continue;
|
||||
}
|
||||
const shimContent = fs.readFileSync(entry.template, "utf-8");
|
||||
const shimPath = `${shimsDir}/${entry.name}`;
|
||||
fs.writeFileSync(shimPath, shimContent, "utf-8");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} shimsDir
|
||||
*
|
||||
|
|
|
|||
|
|
@ -79,26 +79,10 @@ end
|
|||
|
||||
# `python -m pip`, `python -m pip3`.
|
||||
function python
|
||||
if test (count $argv) -ge 2; and test $argv[1] = "-m"; and string match -qr '^pip(3)?$' -- $argv[2]
|
||||
set mod $argv[2]
|
||||
set args $argv[3..-1]
|
||||
if test $mod = "pip3"
|
||||
wrapSafeChainCommand "pip3" "aikido-pip3" $args
|
||||
else
|
||||
wrapSafeChainCommand "pip" "aikido-pip" $args
|
||||
end
|
||||
else
|
||||
command python $argv
|
||||
end
|
||||
wrapSafeChainCommand "python" "aikido-python" $argv
|
||||
end
|
||||
|
||||
# `python3 -m pip`, `python3 -m pip3'.
|
||||
function python3
|
||||
if test (count $argv) -ge 2; and test $argv[1] = "-m"; and string match -qr '^pip(3)?$' -- $argv[2]
|
||||
set args $argv[3..-1]
|
||||
# python3 always uses pip3, regardless of whether user types `pip` or `pip3`
|
||||
wrapSafeChainCommand "pip3" "aikido-pip3" $args
|
||||
else
|
||||
command python3 $argv
|
||||
end
|
||||
wrapSafeChainCommand "python3" "aikido-python3" $argv
|
||||
end
|
||||
|
|
|
|||
|
|
@ -71,26 +71,10 @@ function pip3() {
|
|||
|
||||
# `python -m pip`, `python -m pip3`.
|
||||
function python() {
|
||||
if [[ "$1" == "-m" && "$2" == pip* ]]; then
|
||||
local mod="$2"
|
||||
shift 2
|
||||
if [[ "$mod" == "pip3" ]]; then
|
||||
wrapSafeChainCommand "pip3" "aikido-pip3" "$@"
|
||||
else
|
||||
wrapSafeChainCommand "pip" "aikido-pip" "$@"
|
||||
fi
|
||||
else
|
||||
command python "$@"
|
||||
fi
|
||||
wrapSafeChainCommand "python" "aikido-python" "$@"
|
||||
}
|
||||
|
||||
# `python3 -m pip`, `python3 -m pip3'.
|
||||
function python3() {
|
||||
if [[ "$1" == "-m" && "$2" == pip* ]]; then
|
||||
shift 2
|
||||
# python3 always uses pip3, regardless of whether user types `pip` or `pip3`
|
||||
wrapSafeChainCommand "pip3" "aikido-pip3" "$@"
|
||||
else
|
||||
command python3 "$@"
|
||||
fi
|
||||
wrapSafeChainCommand "python3" "aikido-python3" "$@"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,27 +97,11 @@ function pip3 {
|
|||
|
||||
# `python -m pip`, `python -m pip3`.
|
||||
function python {
|
||||
param([Parameter(ValueFromRemainingArguments=$true)]$Args)
|
||||
if ($Args.Length -ge 2 -and $Args[0] -eq '-m' -and $Args[1] -match '^pip(3)?$') {
|
||||
$pipArgs = if ($Args.Length -gt 2) { $Args | Select-Object -Skip 2 } else { @() }
|
||||
if ($Args[1] -eq 'pip3') { Invoke-WrappedCommand 'pip3' 'aikido-pip3' $pipArgs }
|
||||
else { Invoke-WrappedCommand 'pip' 'aikido-pip' $pipArgs }
|
||||
}
|
||||
else {
|
||||
Invoke-RealCommand 'python' $Args
|
||||
}
|
||||
Invoke-WrappedCommand 'python' 'aikido-python' $args
|
||||
}
|
||||
|
||||
# `python3 -m pip`, `python3 -m pip3'.
|
||||
function python3 {
|
||||
param([Parameter(ValueFromRemainingArguments=$true)]$Args)
|
||||
if ($Args.Length -ge 2 -and $Args[0] -eq '-m' -and $Args[1] -match '^pip(3)?$') {
|
||||
# python3 always uses pip3, regardless of whether user types `pip` or `pip3`
|
||||
$pipArgs = if ($Args.Length -gt 2) { $Args | Select-Object -Skip 2 } else { @() }
|
||||
Invoke-WrappedCommand 'pip3' 'aikido-pip3' $pipArgs
|
||||
}
|
||||
else {
|
||||
Invoke-RealCommand 'python3' $Args
|
||||
}
|
||||
Invoke-WrappedCommand 'python3' 'aikido-python3' $args
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue