Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Usage looks like this:
- ```
- $ node auto-patch.js get \
- --original node_modules/epub.js/build/epub.js \
- --changed epubjs.changed > patches/epubjs.patch
- $ node auto-patch.js apply patches/epubjs.patch
- ```
- The patch knows the hash of the resulting file, so, before applying,
- it checks if the hashes are different. If they are the same,
- it silently skips patching, so the second command above can be rerun
- multiple times without corrupting the file.
- Example automatic patching with npm:
- {
- ...,
- "scripts": {
- "patch-epubjs": "node auto-patch.js apply patches/epubjs.patch",
- "prepare": "npm run patch-epubjs",
- ...
- }
- }
- Requires: "node": ">=8.5.0"
- */
- const Crypto = require('crypto')
- const DiffMatchPatch = new (require('diff-match-patch'))
- const Fs = require('fs')
- const debug = require('debug')('auto-patch')
- const getHash = (s) =>
- {
- const hash = Crypto.createHash('sha256')
- hash.update(s)
- return hash.digest('hex')
- }
- const getPatch = (originalString, changedString) =>
- {
- const patches = DiffMatchPatch.patch_make(originalString, changedString)
- return DiffMatchPatch.patch_toText(patches)
- }
- const applyPatch = (string, patch) =>
- {
- const patches = DiffMatchPatch.patch_fromText(patch)
- return DiffMatchPatch.patch_apply(patches, string)[0]
- }
- const getStringContents = (path) => String(Fs.readFileSync(path))
- const getAutoPatch = (originalFile, changedFile, optPath = undefined) =>
- {
- const originalString = getStringContents(originalFile)
- const changedString = getStringContents(changedFile)
- const path = optPath || originalFile
- const hash = getHash(changedString)
- const patch = getPatch(originalString, changedString)
- const json =
- {
- path,
- hash,
- patch
- }
- return json
- }
- const overwriteFile = (path, stringContents) =>
- Fs.writeFileSync(path, stringContents)
- const backupOriginal = (path) => Fs.copyFileSync(path, path + '.unpatched')
- const applyAutoPatch = (autoPatch) =>
- {
- const path = autoPatch.path
- const currentString = getStringContents(path)
- const currentHash = getHash(currentString)
- if (currentHash == autoPatch.hash) {
- debug(`${path} is already patched. Skipping.`)
- return
- }
- const patchedString = applyPatch(currentString, autoPatch.patch)
- if (autoPatch.hash != getHash(patchedString)) {
- console.error(
- `Patch for ${path} is corrupted,` +
- ` specified hash does not match the resulting hash.`
- )
- return
- }
- debug(`Backing up and patching ${path}.`)
- backupOriginal(path)
- overwriteFile(path, patchedString)
- }
- const argv = require('minimist')(process.argv.slice(2));
- switch (true) {
- case argv._[0] == 'get':
- // usage:
- // `node auto-patch.js get --original original.js --changed changed.js`
- // optionally, --path, that the resulting patch will patch,
- // can be specified separately. otherwise will be same as --original.
- {
- const patch = getAutoPatch(argv.original, argv.changed, argv.path)
- const json = JSON.stringify(patch)
- process.stdout.write(json)
- }
- break
- case argv._[0] == 'apply':
- // usage: node auto-patch.js apply path/to/the.patch
- {
- const json = getStringContents(argv._[1])
- const patch = JSON.parse(json)
- applyAutoPatch(patch)
- }
- break
- default:
- console.error('Wrong arguments.')
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement