startWithNodeEnvironment method
Future<ShellSession>
startWithNodeEnvironment(
- ShellRequest request,
- Map<
String, String> nodeEnvironment
start, given the node side of the session's environment — the live environment with the profile over it — already computed (by a decorating backend falling back to this one), so it is not read a second time.
Implementation
Future<ShellSession> startWithNodeEnvironment(
ShellRequest request,
Map<String, String> nodeEnvironment,
) async {
if (allowCommand != null && !allowCommand!(request)) {
throw ProcessException(
request.command ?? defaultShell,
request.args,
'Command not permitted by node policy',
);
}
// The shell and the start directory are the node's choices, so they are
// looked up in the node's environment only: a client-sent `PATH` in
// [ShellRequest.env] must not pick which `bash.exe` the node probes and
// runs (a node policy vets the request's command, not its environment).
final (executable, args) = resolveShellInvocation(
request,
defaultShell,
environment: nodeEnvironment,
);
// Client's choice, then the node's, then the user's home (a profile `HOME`
// first) — and only then wherever this process happens to be standing.
// See `resolveStartDirectory`.
final cwd = resolveStartDirectory(
requested: request.cwd,
configured: workingDirectory,
environment: nodeEnvironment,
);
// The session's whole environment, built here rather than merged with
// this process's by `Process.start`: that merge matches names by exact
// case, so a profile `PATH` next to the inherited `Path` reached the child
// as two variables, the first (stale) one winning.
final env = mergeEnvironment([
nodeEnvironment,
_ptyEnv(request),
request.env,
]);
final process = await Process.start(
executable,
args,
workingDirectory: cwd,
// `withUserHome` only fills in `HOME` when nothing supplies one — a node
// run as a service is handed no `HOME`, and a shell without one is
// subtly broken rather than obviously so. `withPubCacheBin` does the same
// for the pub cache `bin` directory, so `dart pub global
// activate`-installed CLIs (`omnyshell` among them) are runnable in a
// session that sources no rc. [env] is complete, so it is also what
// both consult instead of this process's environment.
environment: mergeEnvironment([
withPubCacheBin(
withUserHome(env, processEnvironment: env),
processEnvironment: env,
),
]),
includeParentEnvironment: false,
);
return ProcessShellSession(
process,
shellFamily: classifyShellFamily(executable),
);
}