🚀 Update getPatch to write files to disk
This commit is contained in:
parent
b6eccc2dab
commit
440611913d
2 changed files with 92 additions and 12 deletions
|
@ -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 */
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -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
|
||||
fileEntries.filter((file) => file.diffType === SsnDiffType.Deleted).forEach((file) => {
|
||||
//TODO: need to delete file
|
||||
});
|
||||
if (sourceDirectory === targetDirectory) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue