🚀 Add xdelta3 support
This commit is contained in:
parent
b5037c2a71
commit
6bb8ccea22
2 changed files with 52 additions and 3 deletions
|
@ -11,6 +11,7 @@ import readSsnFile from './reader/readSsnFile';
|
||||||
import getFileFromDisks from './streams/getFileFromDisks';
|
import getFileFromDisks from './streams/getFileFromDisks';
|
||||||
import verifyPatch from './verify/verifyPatch';
|
import verifyPatch from './verify/verifyPatch';
|
||||||
import verifyProductName from './verify/verifyProductName';
|
import verifyProductName from './verify/verifyProductName';
|
||||||
|
import performDiffing from './xdelta3/performDiffing';
|
||||||
|
|
||||||
interface IGetPatchArgs {
|
interface IGetPatchArgs {
|
||||||
/** The product that should be patched. */
|
/** The product that should be patched. */
|
||||||
|
@ -103,9 +104,31 @@ export default async function getPatch({ product, from, to, sourceDirectory, tar
|
||||||
const fileStream = await getFileFromDisks(diskFilenames, { diskStart: file.diskNumberStart, offset: file.offset, length: file.compressedSize });
|
const fileStream = await getFileFromDisks(diskFilenames, { diskStart: file.diskNumberStart, offset: file.offset, length: file.compressedSize });
|
||||||
const fileContents = await extractFileAsStream(file, fileStream);
|
const fileContents = await extractFileAsStream(file, fileStream);
|
||||||
|
|
||||||
//TODO: need to apply xdelta3 diffing, then write to disk
|
//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
|
const sourceFile = path.join(sourceDir, file.name);
|
||||||
console.warn(`Could not extract "${file.name}"; xdelta3 diffing is not yet implemented.`);
|
const outputName = path.join(targetDir, file.name);
|
||||||
|
const outputNameTemp = `${outputName}.tmp`;
|
||||||
|
await performDiffing(sourceFile, fileContents, outputNameTemp);
|
||||||
|
|
||||||
|
//clean up: delete source file if necessary, and remove .tmp file extension
|
||||||
|
if (sourceDir === targetDir) {
|
||||||
|
fs.unlink(sourceFile, (deleteError) => {
|
||||||
|
if (deleteError) {
|
||||||
|
throw new Error(`Could not delete old source file "${sourceFile}": ${deleteError.name}`);
|
||||||
|
}
|
||||||
|
fs.rename(outputNameTemp, outputName, (renameError) => {
|
||||||
|
if (renameError) {
|
||||||
|
throw new Error(`Could not rename output file "${outputNameTemp}": ${renameError.name}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fs.rename(outputNameTemp, outputName, (renameError) => {
|
||||||
|
if (renameError) {
|
||||||
|
throw new Error(`Could not rename output file "${outputNameTemp}": ${renameError.name}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Could not extract file "${file.name}"`, error);
|
console.error(`Could not extract file "${file.name}"`, error);
|
||||||
}
|
}
|
||||||
|
|
26
src/ssn/xdelta3/performDiffing.ts
Normal file
26
src/ssn/xdelta3/performDiffing.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import * as childProcess from 'child_process';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as stream from 'stream';
|
||||||
|
|
||||||
|
export default function performDiffing(sourceFile: string, diffStream: stream.Readable, targetFile: string): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
//const sourceStream = fs.createReadStream(sourceFile);
|
||||||
|
const targetStream = fs.createWriteStream(targetFile);
|
||||||
|
|
||||||
|
//spawn xdelta3 process, set up listeners
|
||||||
|
const process = childProcess.spawn('xdelta3', ['-d', '-s', sourceFile]);
|
||||||
|
diffStream.pipe(process.stdin);
|
||||||
|
process.stdout.pipe(targetStream);
|
||||||
|
process.stderr.on('data', (chunk) => {
|
||||||
|
reject(`Error during xdelta3: ${chunk}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('exit', (code, signal) => {
|
||||||
|
if (code === 0) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(`xdelta3 exited with code "${code}" due to signal "${signal}".`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue