You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.9 KiB
112 lines
2.9 KiB
import fg from "fast-glob";
|
|
import fs from "fs";
|
|
import assert from "assert";
|
|
import { log } from "./logging.js";
|
|
import Path from "path";
|
|
import { execSync } from "child_process";
|
|
|
|
/**
|
|
* Fixes some common problems with fast-glob on windows.
|
|
*/
|
|
export const glob = (path) => {
|
|
if(process.platform === "win32") {
|
|
// fast-glob doesn't understand \\ or C:\
|
|
const fixed_path = path.replace("C:","").replaceAll('\\', '/')
|
|
|
|
return fg.sync(fixed_path);
|
|
} else {
|
|
return fg.sync(path);
|
|
}
|
|
}
|
|
|
|
export const changed = (source, target) => {
|
|
// we want the source to error if it doesn't exist
|
|
const s_stat = fs.statSync(source);
|
|
// but target might not exist, which would mean it's a change
|
|
const t_stat = fs.statSync(target, {throwIfNoEntry: false});
|
|
|
|
return !t_stat || s_stat.mtimeMs > t_stat.mtimeMs;
|
|
}
|
|
|
|
/* Makes a directory recursively. */
|
|
export const mkdir = (dir) => {
|
|
if(!fs.existsSync(dir)) {
|
|
log.debug(`making dir ${dir}`);
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Given any path to a file, makes sure all its directories are in place.
|
|
*
|
|
* @param { string } -- path to file
|
|
*/
|
|
export const mkdir_to = (target) => {
|
|
let dirs = Path.parse(target);
|
|
mkdir(dirs.dir);
|
|
}
|
|
|
|
/* Convenience function that makes sure the dir is there then writes the data. */
|
|
export const write = (target, data) => {
|
|
mkdir_to(target);
|
|
fs.writeFileSync(target, data);
|
|
}
|
|
|
|
/** Like write but does an OS copy after making the target dir. When given a
|
|
* filter it will give the filter function the arguments, let it return contents,
|
|
* then write those instead of a copy.
|
|
*/
|
|
export const copy = (src, dest, filter=null) => {
|
|
mkdir_to(dest);
|
|
|
|
if(filter) {
|
|
try {
|
|
let raw_data = fs.readFileSync(src);
|
|
let data = filter(src, dest, raw_data);
|
|
write(dest, data);
|
|
} catch (error) {
|
|
log.error(error, "Problem with filter write in copy");
|
|
}
|
|
} else {
|
|
fs.copyFileSync(src, dest);
|
|
}
|
|
}
|
|
|
|
export const rm = (file_name, ignore=false) => {
|
|
log.warn("Deleting file", file_name);
|
|
try {
|
|
fs.unlinkSync(file_name);
|
|
} catch(error) {
|
|
if(ignore) {
|
|
log.debug(`Requested delete file ${file_name} doesn't exist, but ignored.`);
|
|
} else {
|
|
log.error(error, file_name);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
export const index_rollup = (src_index, target_index, contents, key) => {
|
|
let index = JSON.parse(fs.readFileSync(src_index));
|
|
|
|
index[key] = glob(contents).map(f => JSON.parse(fs.readFileSync(f)));
|
|
assert(index[key] !== undefined, `Attempt to load contents into ${key} for ${src_index} failed with undefined.`);
|
|
|
|
write(target_index, JSON.stringify(index));
|
|
|
|
return index;
|
|
}
|
|
|
|
export const exec = (cmd, opts) => {
|
|
log.info(`EXEC ${cmd}`);
|
|
return execSync(cmd, opts);
|
|
}
|
|
|
|
export const exec_i = (cmd, opts={}) => {
|
|
return exec(cmd, {stdio: [process.stdout, process.stderr, process.stdin], ...opts});
|
|
}
|
|
|
|
|
|
export default {
|
|
index_rollup, rm, exec, changed, mkdir, mkdir_to, write, copy, exec_i, glob
|
|
}
|
|
|