@plugjs/plug
Version:
PlugJS Build System ===================
92 lines • 4.28 kB
JavaScript
import { assert } from "../asserts.js";
import { Files } from "../files.js";
import { chmod, copyFile, fsConstants, mkdir } from "../fs.js";
import { $p } from "../logging.js";
import { assertAbsolutePath, getAbsoluteParent, resolveAbsolutePath } from "../paths.js";
import { install } from "../pipe.js";
/* ========================================================================== *
* INSTALLATION / IMPLEMENTATION *
* ========================================================================== */
/** Copy the curent {@link Files} to a different directory */
install('copy', class Copy {
_directory;
_options;
constructor(_directory, _options = {}) {
this._directory = _directory;
this._options = _options;
}
async pipe(files, context) {
/* Destructure our options with some defaults and compute write flags */
const { mode, dirMode, overwrite = 'fail', rename = (s) => s } = this._options;
const flags = overwrite === 'overwrite' ? 0 : fsConstants.COPYFILE_EXCL;
const dmode = parseMode(dirMode);
const fmode = parseMode(mode);
/* Our files builder for all written files */
const directory = context.resolve(this._directory);
const builder = Files.builder(directory);
/* Iterate through all the mappings of the source files */
for (const [relative, absolute] of files.pathMappings()) {
/* The target absolute is the (possibly) renamed relative source file
* relocated to the the target directory */
const target = resolveAbsolutePath(builder.directory, rename(relative));
/* We never copy a file onto itself, but not fail either */
if (target === absolute) {
context.log.warn('Cowardly refusing to copy same file', $p(absolute));
continue;
}
/* Create the parent directory, recursively */
const directory = getAbsoluteParent(target);
const firstParent = await mkdir(directory, { recursive: true });
/* Set the mode for all created directories */
if (firstParent && (dmode !== undefined)) {
assertAbsolutePath(firstParent);
for (let dir = directory;; dir = getAbsoluteParent(dir)) {
context.log.trace(`Setting mode ${stringifyMode(dmode)} for directory`, $p(dir));
await chmod(dir, dmode);
if (dir === firstParent)
break;
}
}
context.log.trace(`Copying "${$p(absolute)}" to "${$p(target)}"`);
try {
/* Actually _copy_ the file */
await copyFile(absolute, target, flags);
/* Set the mode, if we need to */
if (fmode !== undefined) {
context.log.trace(`Setting mode ${stringifyMode(fmode)} for file`, $p(target));
await chmod(target, fmode);
}
/* Record this file */
builder.add(target);
}
catch (error) {
/* Just log that we skipped the file if we have to */
if ((error.code === 'EEXIST') && (overwrite === 'skip')) {
context.log.warn(`Not overwriting existing file ${$p(target)}`);
}
else {
throw error;
}
}
}
const result = builder.build();
context.log.info('Copied', result.length, 'files to', $p(builder.directory));
return result;
}
});
/* ========================================================================== *
* INTERNALS *
* ========================================================================== */
function parseMode(mode) {
if (mode === undefined)
return undefined;
if (typeof mode === 'number')
return mode;
const parsed = parseInt(mode, 8);
assert(!isNaN(parsed), `Invalid mode "${mode}"`);
return parsed;
}
function stringifyMode(mode) {
return mode.toString(8).padStart(4, '0');
}
//# sourceMappingURL=copy.js.map