UNPKG

firmament-vita

Version:

Firmament module for automating VITA tasks

184 lines (173 loc) 5.98 kB
import {injectable, inject} from 'inversify'; import {VitaFileUtil} from "../interfaces/vita-file-util"; import { FindFilesOptions, UnZipFileResult, UnZipFileOptions, UnZipFileStatus, CopyFileResult } from "../interfaces/vita-options-results"; import {ForceErrorImpl, CommandUtil} from "firmament-yargs"; import {VitaSpawn} from "../interfaces/vita-spawn"; const fs = require('fs'); const find = require('find'); const path = require('path'); const async = require('async'); const mkdirp = require('mkdirp'); @injectable() export class VitaFileUtilImpl extends ForceErrorImpl implements VitaFileUtil { constructor(@inject('VitaSpawn')private vitaSpawn: VitaSpawn, @inject('CommandUtil')private commandUtil: CommandUtil) { super(); } findFilesSync(options: FindFilesOptions) { try { options.pattern = options.pattern || /.*/; options.files = options.files || []; options.folders = options.folders || [process.cwd()]; options.folders.forEach(folder => { try { options.files = options.files.concat(find.fileSync(options.pattern, folder)); } catch (err) { } }); } catch (err) { } return options.files; } findFiles(options: FindFilesOptions, cb: (err: Error, files?: string[])=>void) { this.checkCallback(cb)(null, this.findFilesSync(options)); } unZipFiles(options: UnZipFileOptions, cbStatus: (err: Error, unZipFileStatus: UnZipFileStatus)=>void, cbFinal: (err: Error, unZipFileResults?: UnZipFileResult[])=>void) { cbStatus = this.checkCallback(cbStatus); cbFinal = this.checkCallback(cbFinal); options.deleteOriginalZipFile = options.deleteOriginalZipFile || false; options.zippedFiles = options.zippedFiles || []; options.targetFolder = options.targetFolder || ''; options.foldersOfZippedFiles = options.foldersOfZippedFiles || []; options.zippedFiles = this.findFilesSync({ pattern: /\.gz$/, files: options.zippedFiles, folders: options.foldersOfZippedFiles }); if (options.targetFolder) { try { mkdirp.sync(options.targetFolder); } catch (err) { cbFinal(err); return; } } let fnArray = []; options.zippedFiles.forEach(inFile => { //We know all filenames end in '.gz' because of our search pattern. Remove //last 3 characters for uncompressed filename. let outFile = inFile.slice(0, -3); if (options.targetFolder) { outFile = path.resolve(options.targetFolder, path.basename(outFile)); } fnArray.push(async.apply(this.spawnUnZipOperation.bind(this), inFile, outFile, options.deleteOriginalZipFile, cbStatus)); }); async.parallelLimit(fnArray, 3, (err, results) => { cbFinal(err, results); }); } deleteFile(file: string) { fs.unlink(file); } deleteFiles(files: string[]) { files.forEach(file => { try { this.deleteFile(file); this.commandUtil.log(`Deleting: ${file}`); } catch (err) { this.commandUtil.error(err.toString()); } }); } copyFile(inFile: string, outFile: string, cb: (err: Error, copyFileResult: CopyFileResult)=>void) { let rd = fs.createReadStream(inFile); rd.on("error", function (err) { done(err); }); let wr = fs.createWriteStream(outFile); wr.on("error", function (err) { done(err); }); wr.on("close", function (err) { done(err); }); rd.pipe(wr); function done(err) { if (cb) { cb(null, {error: err, inFile, outFile}); cb = null; } } } private spawnUnZipOperation(inFile: string, outFile: string, deleteZipFile: boolean, cbStatus: (err: Error, unZipFileStatus: UnZipFileStatus)=>void, cbFinal: (err: Error, unZipFileResult: UnZipFileResult)=>void) { let testResult = ''; this.vitaSpawn.spawnIt( 'gunzip', ['--test', inFile], (err: Error, result: any) => { }, (err: Error, result: any) => { if (err) { cbFinal(null, {error: err, zippedFilePath: inFile}); return; } let listResult = ''; this.vitaSpawn.spawnIt( 'gunzip', ['--list', inFile], (err: Error, result: Uint8Array) => { listResult += result.toString(); }, (err: Error, result: any) => { if (err) { cbFinal(null, {error: err, zippedFilePath: inFile}); return; } //SuperHACK to get the uncompressed file size from 'gunzip --list' let re = /(\d+)/g; let r = re.exec(listResult); let totalBytes = parseInt(r[1]);//uncompressed file size (bytes) let bytesWritten = 0; let writeFileStream = fs.createWriteStream(outFile); this.vitaSpawn.spawnIt( 'gunzip', ['--stdout', inFile], (err: Error, result: Uint8Array) => { bytesWritten += result.length; let taskName = `UnZipping ${path.basename(outFile)}`; let current = bytesWritten; let total = totalBytes; cbStatus(null, {taskName, current, total}); writeFileStream.write(result); }, (err: Error, result: any) => { writeFileStream.close(); if (err) { cbFinal(null, {error: err, zippedFilePath: inFile}); return; } if (deleteZipFile) { this.deleteFile(inFile); } cbFinal(err, {unzippedFilePath: outFile, zippedFilePath: inFile}); } ); } ); } ); } }