Files
renovate/lib/util/exec/utils.ts
T
Sebastian Poxhofer c32e2391a0 refactor(linters): add prefer-coerce-object rule (#45493)
Refs #45216

The object counterpart to `prefer-coerce-array`: `x ?? {}` becomes
`coerceObject(x)`. The rule flags a `??` whose default is a bare `{}`
literal, so a populated default or an asserted `({} as Foo)` still
passes; a `x ?? y ?? {}` chain maps onto `coerceObject(x, y)`.

Every hit across `lib/` converted cleanly, so no disable comments were
needed.
2026-08-28 09:27:59 +00:00

95 lines
2.0 KiB
TypeScript

import {
isBoolean,
isNonEmptyStringAndNotWhitespace,
isObject,
isString,
} from '@sindresorhus/is';
import { join } from 'shlex';
import { getCustomEnv, getUserEnv } from '../env.ts';
import { coerceObject } from '../object.ts';
import { getChildProcessEnv } from './env.ts';
import type { CommandWithOptions, ExecOptions } from './types.ts';
export type ResolvedChildEnv = Record<string, string>;
export function getChildEnv({
extraEnv,
env: forcedEnv = {},
}: Pick<ExecOptions, 'env' | 'extraEnv'> = {}): ResolvedChildEnv {
const globalConfigEnv = getCustomEnv();
const userConfiguredEnv = getUserEnv();
const inheritedKeys: string[] = [];
for (const [key, val] of Object.entries(coerceObject(extraEnv))) {
if (isString(val)) {
inheritedKeys.push(key);
}
}
const parentEnv = getChildProcessEnv(inheritedKeys);
const combinedEnv = {
...extraEnv,
...parentEnv,
...globalConfigEnv,
...userConfiguredEnv,
...forcedEnv,
};
const result: Record<string, string> = {};
for (const [key, val] of Object.entries(combinedEnv)) {
if (isString(val)) {
result[key] = `${val}`;
}
}
return result;
}
export function isCommandWithOptions(cmd: unknown): cmd is CommandWithOptions {
if (!(isObject(cmd) && 'command' in cmd)) {
return false;
}
if (!Array.isArray(cmd.command)) {
return false;
}
if (!cmd.command.length) {
return false;
}
if (cmd.command.some((v) => !isString(v))) {
return false;
}
if ('ignoreFailure' in cmd && !isBoolean(cmd.ignoreFailure)) {
return false;
}
if (
'shell' in cmd &&
!(isBoolean(cmd.shell) || isNonEmptyStringAndNotWhitespace(cmd.shell))
) {
return false;
}
return true;
}
export function asRawCommand(cmd: string | CommandWithOptions): string {
if (isCommandWithOptions(cmd)) {
return join(cmd.command);
}
return cmd;
}
export function asRawCommands(
cmds: string | (string | CommandWithOptions)[],
): string[] {
if (isString(cmds)) {
return [cmds];
}
return cmds.map((cmd) => asRawCommand(cmd));
}