diff --git a/src/ssn/getPatch.ts b/src/ssn/getPatch.ts index f630127..d432034 100644 --- a/src/ssn/getPatch.ts +++ b/src/ssn/getPatch.ts @@ -4,9 +4,10 @@ import downloadUrlContents from '../cdn/downloadUrlContents'; import createDirRecursively from '../cdn/funcs/createDirRecursively'; import getUrlContents from '../cdn/getUrlContents'; import { Product } from '../interfaces/ISettings'; -import { SsnDiffType } from '../interfaces/ISsnFileEntry'; +import { ISsnFileEntry, SsnDiffType } from '../interfaces/ISsnFileEntry'; import getSolidpkg from './getSolidpkg'; import launch from './patcher-installer/launch'; +import taskManager from './patcher-installer/taskManager'; import readSsnFile from './reader/readSsnFile'; import verifyPatch from './verify/verifyPatch'; import verifyProductName from './verify/verifyProductName'; @@ -78,8 +79,7 @@ export default async function getPatch({ product, from, to, sourceDirectory, tar //-------------------------------------------------------------------------------------------------------------- //Perform the patching - //Extract newly added files - fileEntries.filter((file) => file.diffType === SsnDiffType.NewFile).forEach(async (file) => { + const extractAdded = async (file: ISsnFileEntry) => { try { //create file write stream const outputName = path.join(targetDir, file.name); @@ -93,10 +93,9 @@ export default async function getPatch({ product, from, to, sourceDirectory, tar } catch (error) { console.error(`Could not extract file "${file.name}"`, error); } - }); + }; - //Extract changed files - fileEntries.filter((file) => file.diffType === SsnDiffType.Changed).forEach(async (file) => { + const extractChanged = async (file: ISsnFileEntry) => { try { const sourceFile = path.join(sourceDir, file.name); const outputName = path.join(targetDir, file.name); @@ -132,36 +131,51 @@ export default async function getPatch({ product, from, to, sourceDirectory, tar console.error(`Could not extract file "${file.name}"`, error); //TODO: need to delete .tmp file } - }); + }; - //Need to delete deleted files - if (sourceDir === targetDir) { - fileEntries.filter((file) => file.diffType === SsnDiffType.Deleted).forEach((file) => { - //delete file - const fileName = path.join(targetDir, file.name); - fs.unlink(fileName, (error) => { - if (error) { - console.error(`Could not delete removed file "${file.name}"`, error); - } - }); - //TODO: delete folder (and parent folders) that are empty + const deleteRemoved = (file: ISsnFileEntry) => { + //delete file + const fileName = path.join(targetDir, file.name); + fs.unlink(fileName, (error) => { + if (error) { + console.error(`Could not delete removed file "${file.name}"`, error); + } }); + //TODO: delete folder (and parent folders) that are empty + }; + + const copyUnchanged = async (file: ISsnFileEntry) => { + //copy file + const sourceName = path.join(sourceDir, file.name); + const targetName = path.join(targetDir, file.name); + await createDirRecursively(path.dirname(targetName)); + fs.copyFile(sourceName, targetName, (error) => { + if (error) { + console.error(`Could not copy unchanged file "${file.name}"`, error); + } + }); + }; + + const tasks: Array<() => Promise> = []; + + //Extract newly added files + tasks.push(...fileEntries.filter((file) => file.diffType === SsnDiffType.NewFile).map((file) => extractAdded.bind(null, file))); + + //Extract changed files + tasks.push(...fileEntries.filter((file) => file.diffType === SsnDiffType.Changed).map((file) => extractChanged.bind(null, file))); + + //Need to delete removed files + if (sourceDir === targetDir) { + tasks.push(...fileEntries.filter((file) => file.diffType === SsnDiffType.Deleted).map((file) => deleteRemoved.bind(null, file))); } //Need to copy unchanged files (if we are patching into a different directory) if (sourceDir !== targetDir) { - fileEntries.filter((file) => file.diffType === SsnDiffType.Unchanged).forEach(async (file) => { - //copy file - const sourceName = path.join(sourceDir, file.name); - const targetName = path.join(targetDir, file.name); - await createDirRecursively(path.dirname(targetName)); - fs.copyFile(sourceName, targetName, (error) => { - if (error) { - console.error(`Could not copy unchanged file "${file.name}"`, error); - } - }); - }); + tasks.push(...fileEntries.filter((file) => file.diffType === SsnDiffType.Unchanged).map((file) => copyUnchanged.bind(null, file))); } + //run tasks + taskManager(tasks, 5); + //TODO: add option to delete downloaded files once patching is complete } diff --git a/src/ssn/patcher-installer/taskManager.ts b/src/ssn/patcher-installer/taskManager.ts new file mode 100644 index 0000000..6c22aa9 --- /dev/null +++ b/src/ssn/patcher-installer/taskManager.ts @@ -0,0 +1,23 @@ +export default function taskManager(tasks: Array<() => Promise>, maxConcurrentTasks: number): Promise { + return new Promise((resolve, reject) => { + const remainingTasks = tasks; + //const currentlyRunningTasks: Array> = []; + + const startNewTask = () => { + if (remainingTasks.length === 0) { + return resolve(); + } + + const curTask = remainingTasks.pop() as () => Promise; + const curPromise = curTask(); + //currentlyRunningTasks.push(curPromise); + curPromise.then(() => { + return startNewTask(); + }); + }; + + for (let i = 0; i < maxConcurrentTasks; i += 1) { + startNewTask(); + } + }); +}