diffWithApk
This commit is contained in:
parent
dbe1f9b26d
commit
00ddfcecb2
@ -61,6 +61,15 @@
|
|||||||
"hasValue": true
|
"hasValue": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"diffWithApk": {
|
||||||
|
"description": "Create diff patch from a Android package(.apk)",
|
||||||
|
"options": {
|
||||||
|
"output": {
|
||||||
|
"default": "build/output/diff-${time}.apk-patch",
|
||||||
|
"hasValue": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalOptions":{
|
"globalOptions":{
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import {ZipFile} from 'yazl';
|
import {ZipFile} from 'yazl';
|
||||||
import {open as openZipFile} from 'yauzl';
|
import {open as openZipFile} from 'yauzl';
|
||||||
|
import {diff} from 'node-bsdiff';
|
||||||
|
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
@ -65,6 +66,105 @@ async function pack(dir, output){
|
|||||||
console.log('Bundled saved to: ' + realOutput);
|
console.log('Bundled saved to: ' + realOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readEntire(entry, zipFile) {
|
||||||
|
const buffers = [];
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
zipFile.openReadStream(entry, (err, stream) => {
|
||||||
|
stream.pipe({
|
||||||
|
write(chunk) {
|
||||||
|
buffers.push(chunk);
|
||||||
|
},
|
||||||
|
end() {
|
||||||
|
resolve(Buffer.concat(buffers));
|
||||||
|
},
|
||||||
|
on() {
|
||||||
|
},
|
||||||
|
once() {
|
||||||
|
},
|
||||||
|
emit() {
|
||||||
|
},
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function diffWithApk(origin, next, output) {
|
||||||
|
const originEntries = {};
|
||||||
|
const originMap = {};
|
||||||
|
|
||||||
|
let originSource;
|
||||||
|
|
||||||
|
await enumZipEntries(origin, (entry, zipFile) => {
|
||||||
|
if (!/\/$/.test(entry.fileName)) {
|
||||||
|
// isFile
|
||||||
|
originEntries[entry.fileName] = entry.crc32;
|
||||||
|
originMap[entry.crc32] = entry.fileName;
|
||||||
|
|
||||||
|
if (entry.fileName === 'assets/index.android.bundle') {
|
||||||
|
// This is source.
|
||||||
|
return readEntire(entry, zipFile).then(v=>originSource = v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
originSource = originSource || new Buffer(0);
|
||||||
|
|
||||||
|
const copies = {};
|
||||||
|
|
||||||
|
var zipfile = new ZipFile();
|
||||||
|
|
||||||
|
const writePromise = new Promise((resolve, reject)=>{
|
||||||
|
zipfile.outputStream.on('error', err => {throw err;});
|
||||||
|
zipfile.outputStream.pipe(fs.createWriteStream(output))
|
||||||
|
.on("close", function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await enumZipEntries(next, (entry, nextZipfile) => {
|
||||||
|
if (/\/$/.test(entry.fileName)) {
|
||||||
|
// Directory
|
||||||
|
zipfile.addEmptyDirectory(entry.fileName);
|
||||||
|
} else if (entry.fileName === 'index.bundlejs') {
|
||||||
|
console.log('Found bundle');
|
||||||
|
return readEntire(entry, nextZipfile).then( newSource => {
|
||||||
|
console.log('Begin diff');
|
||||||
|
zipfile.addBuffer(diff(originSource, newSource), 'index.bundlejs.patch');
|
||||||
|
console.log('End diff');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// If same file.
|
||||||
|
if (originEntries[entry.fileName] === entry.crc32) {
|
||||||
|
copies[entry.fileName] = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If moved from other place
|
||||||
|
if (originMap[entry.crc32]){
|
||||||
|
copies[entry.fileName] = originMap[entry.crc32];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject)=>{
|
||||||
|
nextZipfile.openReadStream(entry, function(err, readStream) {
|
||||||
|
if (err){
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
zipfile.addReadStream(readStream, entry.fileName);
|
||||||
|
readStream.on('end', () => {
|
||||||
|
console.log('add finished');
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(copies);
|
||||||
|
zipfile.addBuffer(new Buffer(JSON.stringify({copies})), '__diff.json');
|
||||||
|
zipfile.end();
|
||||||
|
await writePromise;
|
||||||
|
}
|
||||||
|
|
||||||
function enumZipEntries(zipFn, callback) {
|
function enumZipEntries(zipFn, callback) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
openZipFile(zipFn, {lazyEntries:true}, (err, zipfile) => {
|
openZipFile(zipFn, {lazyEntries:true}, (err, zipfile) => {
|
||||||
@ -205,5 +305,20 @@ export const commands = {
|
|||||||
zipfile.addBuffer(new Buffer(JSON.stringify({copies})), '__diff.json');
|
zipfile.addBuffer(new Buffer(JSON.stringify({copies})), '__diff.json');
|
||||||
zipfile.end();
|
zipfile.end();
|
||||||
await writePromise;
|
await writePromise;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
async diffWithApk({args, options}) {
|
||||||
|
const [origin, next] = args;
|
||||||
|
const {output} = options;
|
||||||
|
|
||||||
|
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
|
||||||
|
|
||||||
|
if (!origin || !next) {
|
||||||
|
console.error('pushy diffWithApk <origin> <next>');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await diffWithApk(origin, next, realOutput);
|
||||||
|
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"fs-promise": "^0.4.1",
|
"fs-promise": "^0.4.1",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^2.2.1",
|
||||||
"mkdir-recursive": "^0.2.1",
|
"mkdir-recursive": "^0.2.1",
|
||||||
"node-bsdiff": "^0.1.1",
|
"node-bsdiff": "^0.1.2",
|
||||||
"read": "^1.0.7",
|
"read": "^1.0.7",
|
||||||
"yauzl": "^2.4.1",
|
"yauzl": "^2.4.1",
|
||||||
"yazl": "^2.3.0"
|
"yazl": "^2.3.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user