mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-04 00:42:01 +08:00
115 lines
4.2 KiB
TypeScript
115 lines
4.2 KiB
TypeScript
import type { LocalContext } from '../runtime/context';
|
|
|
|
// Bash is the interpreter for user-owned files. The CLI supplies paths/argv as
|
|
// separate arguments; no user argument is interpolated into this fixed bridge.
|
|
export function shellSessionArguments(
|
|
context: LocalContext,
|
|
argv: string[],
|
|
scriptArgs: string[],
|
|
command = false,
|
|
timeoutMarker = '',
|
|
): string[] {
|
|
const scriptIndex = command
|
|
? argv.findIndex((arg) => /\.(?:js|mjs|py|pyc|sh|ts)$/.test(arg))
|
|
: 0;
|
|
const bridge = `
|
|
__ql_env=$1; __ql_before=$2; __ql_after=$3; __ql_command=$4; __ql_index=$5; __ql_count=$6; __ql_timeout=$7; shift 7
|
|
__ql_hook_args=( "\${@:1:__ql_count}" ); shift "$__ql_count"
|
|
__ql_script_args=( "$@" )
|
|
# Reserve an internal descriptor before sourcing user code. In particular, fd 3
|
|
# and fd 9 remain available for user redirections and locks. Bash 3 also supports
|
|
# this numeric descriptor, unlike Bash 4's dynamic descriptor syntax.
|
|
if [ -n "$__ql_timeout" ]; then exec 19>&3 3>&-; fi
|
|
__ql_after_started=false
|
|
__ql_run_after() {
|
|
__ql_after_started=true
|
|
if [ -n "$__ql_timeout" ]; then printf A >&19; fi
|
|
if [ "$__ql_nounset" = true ]; then set -u; fi
|
|
export NODE_PATH="\${PREV_NODE_PATH:-}"
|
|
unset QL_NODE_GLOBAL_PATH
|
|
if [ -f "$__ql_after" ]; then . "$__ql_after" "\${__ql_hook_args[@]}"; fi
|
|
if [ -n "\${task_after:-}" ]; then eval "\${task_after%;}"; fi
|
|
}
|
|
__ql_timeout_exit() {
|
|
if [ -f "$__ql_timeout" ] && [ "$__ql_after_started" = false ]; then
|
|
_task_exit_code=124
|
|
__ql_run_after
|
|
exit 124
|
|
fi
|
|
}
|
|
if [ -f "$__ql_env" ]; then . "$__ql_env"; fi
|
|
if [ -f "$__ql_before" ]; then . "$__ql_before" "\${__ql_hook_args[@]}"; fi
|
|
if [ -n "\${task_before:-}" ]; then eval "\${task_before%;}"; fi
|
|
__ql_nounset=false
|
|
case $- in *u*) __ql_nounset=true; set +u;; esac
|
|
if [ -n "\${__ql_selected_name:-}" ]; then
|
|
printf -v "$__ql_selected_name" '%s' "$__ql_selected_value"
|
|
export "$__ql_selected_name"
|
|
fi
|
|
unset __ql_selected_name __ql_selected_value
|
|
__ql_args=( "\${__ql_hook_args[@]}" )
|
|
if [ "$__ql_index" -lt 0 ]; then __ql_index=0; fi
|
|
__ql_file=\${__ql_args[__ql_index]}
|
|
__ql_resolve=false
|
|
cd "$dir_scripts" || exit 1
|
|
if [ -n "\${work_dir:-}" ] && [ -d "$work_dir" ]; then
|
|
cd "$work_dir" || exit 1
|
|
__ql_resolve=true
|
|
elif [[ "$__ql_file" == */* ]] && [ -d "\${__ql_file%/*}" ]; then
|
|
cd "\${__ql_file%/*}" || exit 1
|
|
__ql_resolve=true
|
|
fi
|
|
if [ "$__ql_resolve" = true ] && [[ "$__ql_file" == */* ]]; then
|
|
__ql_args[__ql_index]="./\${__ql_file##*/}"
|
|
fi
|
|
if [ -n "$__ql_timeout" ]; then
|
|
# Preserve a user-owned EXIT trap. If it prevents our cleanup, the parent
|
|
# performs the fallback after the process group has stopped.
|
|
if [ -z "$(trap -p EXIT)" ]; then trap '__ql_timeout_exit' EXIT; fi
|
|
printf T >&19
|
|
fi
|
|
if [ "$__ql_command" = true ]; then
|
|
"\${__ql_args[@]}" "\${__ql_script_args[@]}"
|
|
_task_exit_code=$?
|
|
else
|
|
# Match task.sh: keep script exit/exec/options inside a child shell while
|
|
# retaining before-hook variables and functions for the script.
|
|
# Keep the supervisor alive until the child's signal/EXIT traps finish, but
|
|
# do not turn user cancellation into an ordinary completion with after hooks.
|
|
__ql_saved_signals=$(trap -p INT TERM HUP QUIT ALRM TSTP)
|
|
__ql_cancel_code=''
|
|
trap '__ql_cancel_code=$((128 + $(kill -l INT)))' INT
|
|
trap '__ql_cancel_code=$((128 + $(kill -l TERM)))' TERM
|
|
trap '__ql_cancel_code=$((128 + $(kill -l HUP)))' HUP
|
|
trap '__ql_cancel_code=$((128 + $(kill -l QUIT)))' QUIT
|
|
trap '__ql_cancel_code=$((128 + $(kill -l ALRM)))' ALRM
|
|
trap '__ql_cancel_code=$((128 + $(kill -l TSTP)))' TSTP
|
|
( . "\${__ql_args[0]}" "\${__ql_script_args[@]}" )
|
|
_task_exit_code=$?
|
|
trap - INT TERM HUP QUIT ALRM TSTP
|
|
eval "$__ql_saved_signals"
|
|
if [ -n "$__ql_cancel_code" ] && ! [ -f "$__ql_timeout" ]; then exit "$__ql_cancel_code"; fi
|
|
fi
|
|
if [ -n "$__ql_timeout" ] && [ -f "$__ql_timeout" ]; then _task_exit_code=124; fi
|
|
__ql_run_after
|
|
exit "$_task_exit_code"
|
|
`;
|
|
return [
|
|
'--noprofile',
|
|
'--norc',
|
|
'-c',
|
|
bridge,
|
|
'ql-shell-session',
|
|
context.paths.file_env!,
|
|
context.paths.file_task_before!,
|
|
context.paths.file_task_after!,
|
|
String(command),
|
|
String(scriptIndex),
|
|
String(argv.length),
|
|
timeoutMarker,
|
|
...argv,
|
|
...(command ? [] : argv.slice(1)),
|
|
...scriptArgs,
|
|
];
|
|
}
|