tswow/tswow-scripts/util/System.ts

160 lines
5.8 KiB
TypeScript
Raw Permalink Normal View History

2020-11-29 16:57:02 +01:00
/*
* This file is part of tswow (https://github.com/tswow)
*
* Copyright (C) 2020 tswow <https://github.com/tswow/>
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import * as child_process from 'child_process';
import * as readline from 'readline';
2020-12-16 17:28:20 +01:00
import { wfs } from './FileSystem';
2021-11-10 15:06:45 +01:00
import { FilePath } from './FileTree';
2020-11-29 16:57:02 +01:00
/**
* Contains functions for running external programs and managing processes and working directories.
*
* As opposed to the built-in 'child_process' module, wsys functions are synchronous unless otherwise stated
* and prefer promises to callbacks.
*/
export namespace wsys {
/**
* Execute a function in a specific working directory.
* @param dir The directory to execute in
* @param cb The function to execute
*/
export async function inDirectory(dir: string, cb: () => any) {
const old = process.cwd();
process.chdir(dir);
2020-12-16 15:34:32 +01:00
try {
2020-12-05 15:50:03 +01:00
await cb();
2020-12-16 15:34:32 +01:00
} catch (err) {
2020-12-05 15:50:03 +01:00
process.chdir(old);
throw err;
}
2020-11-29 16:57:02 +01:00
process.chdir(old);
}
/**
* Execute a function in a specific working directory, does not allow async calls.
* TODO: This should be the default behavior, not the other way around
* @param dir
* @param cb
*/
export function inDirectorySync(dir: string, cb: () => any) {
const old = process.cwd();
process.chdir(dir);
2020-12-16 15:34:32 +01:00
try {
2020-12-05 15:50:03 +01:00
cb();
2020-12-16 15:34:32 +01:00
} catch (err) {
2020-12-05 15:50:03 +01:00
process.chdir(old);
throw err;
}
2020-11-29 16:57:02 +01:00
process.chdir(old);
}
/**
* Checks if a process is running
* @param winName Name of the process in windows
* @param macName Name of the process in mac
* @param linuxName Name of the process in linux
* @returns true if the process is found running, false otherwise.
*/
export function isRunning(winName: string, macName: string, linuxName: string) {
const plat = process.platform;
const cmd = plat === 'win32' ? 'tasklist' : (plat === 'darwin' ? 'ps -ax | grep ' + macName : (plat === 'linux' ? 'ps -A' : ''));
const proc = plat === 'win32' ? winName : (plat === 'darwin' ? macName : (plat === 'linux' ? linuxName : ''));
if (cmd === '' || proc === '') {
return false;
}
2020-12-16 17:28:20 +01:00
return exec(cmd, 'pipe').toLowerCase().indexOf(proc.toLowerCase()) > -1;
2020-11-29 16:57:02 +01:00
}
/**
* Executes a child process asynchronously
* @param program Command to execute
* @throws if the child process exits with an error
* @returns Promise when the child process exits
*/
export function execAsync(program: string, cwd?: string) {
2020-12-16 17:28:20 +01:00
return new Promise<string>((res, rej) => {
child_process.exec(program, {cwd: cwd ? cwd : process.cwd()}, (err, stdout, stderr) => {
return err ? rej(err) : res(stdout);
2020-11-29 16:57:02 +01:00
});
});
}
/**
* Execute a child process.
* @param program Command to execute
* @param stdio How to handle output from the child process
* ('inherit' will display output to the current command window,
* 'pipe' will return output as a string instead)
* @returns Command output of the child process if `stdio` is 'pipe', undefined otherwise.
*/
2022-07-05 11:44:40 +02:00
export function exec(program: string, stdio: 'ignore'|'inherit'|'pipe' = 'pipe', settings: child_process.ExecSyncOptionsWithBufferEncoding = {}) {
2020-12-16 17:28:20 +01:00
let str = '';
2022-07-05 11:44:40 +02:00
const data = child_process.execSync(program, {stdio: stdio, ...settings});
2020-12-16 17:28:20 +01:00
if( data !== undefined && data !== null ) {
str = data.toString();
}
return str;
2020-11-29 16:57:02 +01:00
}
/**
* Executes a child process in a specific working directory.
* @param dirname Working directory to run the child process in
* @param program Command to execute
* @param stdio How to handle output from the child process
* ('inherit' will display output to the current command window,
* 'pipe' will return output as a string instead)
* @returns Command output of the child process if `stdio` is 'pipe', undefined otherwise.
*/
2022-07-05 11:44:40 +02:00
export function execIn(dirname: FilePath, program: string, stdio: 'ignore'|'inherit'|'pipe' = 'inherit', settings: child_process.ExecSyncOptionsWithBufferEncoding = {}) {
2020-12-16 15:34:32 +01:00
let str = '';
2021-09-13 12:36:54 +02:00
const data = child_process.execSync(program,
2022-07-05 11:44:40 +02:00
{stdio: stdio, cwd: wfs.absPath(dirname), ...settings});
2020-12-16 17:28:20 +01:00
if(stdio==='pipe' && data !== null && data !== undefined) {
str = data.toString();
}
return str;
2020-11-29 16:57:02 +01:00
}
/**
* Sleeps for a specified time
* @param timeout Milliseconds to sleep for.
* @returns Promise that resolves after `timeout` milliseconds.
*/
export function sleep(timeout: number) {
return new Promise<void>((res) => {
setTimeout(() => {
res();
}, timeout);
});
}
/**
* Accept user input in the terminal.
* @param query Text to display before the input
*/
2020-12-30 18:03:16 +01:00
export function userInput(query: string) : Promise<string> {
2020-11-29 16:57:02 +01:00
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise(resolve => rl.question(query, ans => {
rl.close();
resolve(ans);
}));
}
}