MichaReiser/speedy.js

View on GitHub
packages/compiler/src/code-generation/build-directory.ts

Summary

Maintainability
A
0 mins
Test Coverage
import * as fs from "fs";
import * as path from "path";
import * as tmp from "tmp";

export interface TempFsObject {
    name: string;
    removeCallback(): void;
}

/**
 * Stores the result of a build and allows to delete the directory together with all created files
 */
export class BuildDirectory {
    private tempObjects: TempFsObject[] = [];
    private directoriesToClean: string[] = [];
    path: string;

    /**
     * Creates a new build directory that safes the intermediate files at the given path
     * @param directory a path or a temp object that points to a directory
     */
    constructor(directory: string | TempFsObject) {
        if (typeof(directory) === "string") {
            this.path = directory;
        } else {
            this.path = directory.name;
            this.tempObjects.push(directory);
        }
    }

    /**
     * Creates a new temporary build directory
     * @return {BuildDirectory} the build directory
     */
    static createTempBuildDirectory() {
        return new BuildDirectory(tmp.dirSync());
    }

    /**
     * Returns a new temporary file in the build directory with the given postfix.
     * The file is deleted when the file directory is removed
     * @param postfix the postfix of the file
     * @return {string} the path to the temporary file
     */
    getTempFileName(postfix?: string) {
        const file = tmp.fileSync({ dir: this.path, postfix });
        this.tempObjects.push(file);
        return file.name;
    }

    /**
     * Creates a temporary sub directory in the build directory
     * @param postfix a postfix for the name of the directory
     * @return {string} the absolute path to the sub directory
     */
    getTempSubdirectory(postfix?: string) {
        const dir = tmp.dirSync({ dir: this.path, postfix });
        this.tempObjects.push(dir);
        this.directoriesToClean.push(dir.name);
        return dir.name;
    }

    /**
     * Deletes all files and sub directories in the build directory and finally deletes the build directory itself.
     * Methods called on the build directory object will fail thereafter.
     */
    remove(): void {
        for (const dir of this.directoriesToClean) {
            this.deleteDirectory(dir);
        }

        for (let i = this.tempObjects.length - 1; i >= 0; --i) {
            this.tempObjects[i].removeCallback();
        }
    }

    private deleteDirectory(dir: string) {
        for (const file of fs.readdirSync(dir)) {
            const filePath = path.join(dir, file);

            if (fs.lstatSync(filePath).isDirectory()) {
                this.deleteDirectory(filePath);
            } else {
                fs.unlinkSync(filePath);
            }
        }
    }
}