🚀 Update getPatch to write files to disk

This commit is contained in:
C-3PO 2018-07-09 15:23:11 +02:00
parent b6eccc2dab
commit 440611913d
Signed by: c3po
GPG key ID: 62993C4BB4D86F24
2 changed files with 92 additions and 12 deletions

View file

@ -29,10 +29,17 @@ if (!to.match(/^(0|[1-9][0-9]{0,2})$/)) {
//TODO: set target directory where patch should be installed
//TODO: set temp directory where patch files should be stored.
//TODO: set location of xdelta3 executable
//TODO: set from=any so it detects current version automatically
//TODO: set from=any so it detects current version automatically (based on .version files)
//TODO: set to=manifest/current to install whatever is the current version in manifest/on CDN
(async () => {
const patch = await getPatch(product as Product, Number(from), Number(to));
//console.log(patch);
await getPatch({
/* tslint:disable:object-literal-sort-keys */
product: product as Product,
from: Number(from),
to: Number(to),
sourceDirectory: process.cwd(),
targetDirectory: process.cwd(),
/* tslint:enable:object-literal-sort-keys */
});
})();

View file

@ -1,4 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
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';
@ -6,10 +9,46 @@ import extractFileAsStream from './extractFileAsStream';
import getSolidpkg from './getSolidpkg';
import readSsnFile from './reader/readSsnFile';
import getFileFromDisks from './streams/getFileFromDisks';
import streamToArrayBuffer from './streams/streamToArrayBuffer';
import verifyPatch from './verify/verifyPatch';
import verifyProductName from './verify/verifyProductName';
interface IGetPatchArgs {
/** The product that should be patched. */
product: Product;
/** The release that we want to patch from, or -1 if patching fresh. */
from: number;
/** The release that we want to patch to. */
to: number;
/** The source directory where the files from the "from" release are stored. Not needed if from=-1. */
sourceDirectory: string | undefined;
/** The target directory where the files should be extracted to. */
targetDirectory: string;
}
/** Downloads and applies the specified patch. */
export default async function getPatch({ product, from, to, sourceDirectory, targetDirectory }: IGetPatchArgs) {
//Verify function arguments
if (!verifyProductName(product)) {
throw new TypeError(`"${product}" is not a valid product.`);
}
if (typeof from !== 'number' || (from | 0) !== from || from < -1 || from > 999) {
throw new TypeError(`from must be an integer greater than or equal to -1 but it is "${from}"`);
}
if (typeof to !== 'number' || (to | 0) !== to || to < 0 || to > 999) {
throw new TypeError(`to must be an integer greater than or equal to 0 but it is "${to}"`);
}
if (sourceDirectory === undefined && from !== -1) {
throw new Error('Must specify a sourceDirectory if patching from a release other than -1.');
}
const sourceDir = (from === -1) ? '' : path.resolve(sourceDirectory as string);
const targetDir = path.resolve(targetDirectory);
await createDirRecursively(targetDir);
//--------------------------------------------------------------------------------------------------------------
//Download and verify files
export default async function getPatch(product: Product, from: number, to: number) {
const solidpkg = await getSolidpkg(product, from, to);
function createUrlObject({ name, length }: {name: string, length: number}) {
@ -33,13 +72,21 @@ export default async function getPatch(product: Product, from: number, to: numbe
//TODO: Verify that downloaded files match the hash in `solidpkg.pieces`
//--------------------------------------------------------------------------------------------------------------
//Perform the patching
//Extract newly added files
fileEntries.filter((file) => file.diffType === SsnDiffType.NewFile).forEach(async (file) => {
try {
//extract file
const fileStream = await getFileFromDisks(diskFilenames, { diskStart: file.diskNumberStart, offset: file.offset, length: file.compressedSize });
const fileContents = await extractFileAsStream(file, fileStream);
console.debug(file.name, file.compressedSize, await streamToArrayBuffer(fileContents));
//TODO: need to write to disk
//write to disk
const outputName = path.join(targetDir, file.name);
await createDirRecursively(path.dirname(outputName));
const outputStream = fs.createWriteStream(outputName);
fileContents.pipe(outputStream);
} catch (error) {
console.error(`Could not extract file "${file.name}"`, error);
}
@ -48,17 +95,43 @@ export default async function getPatch(product: Product, from: number, to: numbe
//Extract changed files
fileEntries.filter((file) => file.diffType === SsnDiffType.Changed).forEach(async (file) => {
try {
//extract file
const fileStream = await getFileFromDisks(diskFilenames, { diskStart: file.diskNumberStart, offset: file.offset, length: file.compressedSize });
const fileContents = await extractFileAsStream(file, fileStream);
console.debug(file.name, file.compressedSize, await streamToArrayBuffer(fileContents));
//TODO: need to apply diffing, then write to disk
//TODO: need to apply xdelta3 diffing, then write to disk
//if source === target, need to create .temp file, and when it's done, delete source file and rename .temp to actual name
console.warn(`Could not extract "${file.name}"; xdelta3 diffing is not yet implemented.`);
} catch (error) {
console.error(`Could not extract file "${file.name}"`, error);
}
});
//Need to delete deleted files
if (sourceDirectory === targetDirectory) {
fileEntries.filter((file) => file.diffType === SsnDiffType.Deleted).forEach((file) => {
//TODO: need to delete 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);
}
});
});
}
//Need to copy unchanged files (if we are patching into a different directory)
if (sourceDirectory !== targetDirectory) {
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);
}
});
});
}
}