aboutsummaryrefslogtreecommitdiff
path: root/node_modules/package-hash/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/package-hash/index.js')
-rw-r--r--node_modules/package-hash/index.js170
1 files changed, 170 insertions, 0 deletions
diff --git a/node_modules/package-hash/index.js b/node_modules/package-hash/index.js
new file mode 100644
index 000000000..8947a02d9
--- /dev/null
+++ b/node_modules/package-hash/index.js
@@ -0,0 +1,170 @@
+'use strict'
+
+const cp = require('child_process')
+const fs = require('fs')
+const path = require('path')
+
+const gfs = require('graceful-fs')
+const flattenDeep = require('lodash.flattendeep')
+const md5hex = require('md5-hex')
+const releaseZalgo = require('release-zalgo')
+
+const PACKAGE_FILE = require.resolve('./package.json')
+const TEN_MEBIBYTE = 1024 * 1024 * 10
+
+const readFile = {
+ async (file) {
+ return new Promise((resolve, reject) => {
+ gfs.readFile(file, (err, contents) => {
+ err ? reject(err) : resolve(contents)
+ })
+ })
+ },
+ sync (file) {
+ return fs.readFileSync(file)
+ }
+}
+
+const tryReadFile = {
+ async (file) {
+ return new Promise(resolve => {
+ gfs.readFile(file, (err, contents) => {
+ resolve(err ? null : contents)
+ })
+ })
+ },
+
+ sync (file) {
+ try {
+ return fs.readFileSync(file)
+ } catch (err) {
+ return null
+ }
+ }
+}
+
+const tryExecFile = {
+ async (file, args, options) {
+ return new Promise(resolve => {
+ cp.execFile(file, args, options, (err, stdout) => {
+ resolve(err ? null : stdout)
+ })
+ })
+ },
+
+ sync (file, args, options) {
+ try {
+ return cp.execFileSync(file, args, options)
+ } catch (err) {
+ return null
+ }
+ }
+}
+
+const git = {
+ tryGetRef (zalgo, dir, head) {
+ const m = /^ref: (.+)$/.exec(head.toString('utf8').trim())
+ if (!m) return null
+
+ return zalgo.run(tryReadFile, path.join(dir, '.git', m[1]))
+ },
+
+ tryGetDiff (zalgo, dir) {
+ return zalgo.run(tryExecFile,
+ 'git',
+ // Attempt to get consistent output no matter the platform. Diff both
+ // staged and unstaged changes.
+ ['--no-pager', 'diff', 'HEAD', '--no-color', '--no-ext-diff'],
+ {
+ cwd: dir,
+ maxBuffer: TEN_MEBIBYTE,
+ env: Object.assign({}, process.env, {
+ // Force the GIT_DIR to prevent git from diffing a parent repository
+ // in case the directory isn't actually a repository.
+ GIT_DIR: path.join(dir, '.git')
+ }),
+ // Ignore stderr.
+ stdio: ['ignore', 'pipe', 'ignore']
+ })
+ }
+}
+
+function addPackageData (zalgo, pkgPath) {
+ const dir = path.dirname(pkgPath)
+
+ return zalgo.all([
+ dir,
+ zalgo.run(readFile, pkgPath),
+ zalgo.run(tryReadFile, path.join(dir, '.git', 'HEAD'))
+ .then(head => {
+ if (!head) return []
+
+ return zalgo.all([
+ zalgo.run(tryReadFile, path.join(dir, '.git', 'packed-refs')),
+ git.tryGetRef(zalgo, dir, head),
+ git.tryGetDiff(zalgo, dir)
+ ])
+ .then(results => {
+ return [head].concat(results.filter(Boolean))
+ })
+ })
+ ])
+}
+
+function computeHash (zalgo, paths, pepper, salt) {
+ const inputs = []
+ if (pepper) inputs.push(pepper)
+
+ if (typeof salt !== 'undefined') {
+ if (Buffer.isBuffer(salt) || typeof salt === 'string') {
+ inputs.push(salt)
+ } else if (typeof salt === 'object' && salt !== null) {
+ inputs.push(JSON.stringify(salt))
+ } else {
+ throw new TypeError('Salt must be an Array, Buffer, Object or string')
+ }
+ }
+
+ return zalgo.all(paths.map(pkgPath => addPackageData(zalgo, pkgPath)))
+ .then(furtherInputs => md5hex(flattenDeep([inputs, furtherInputs])))
+}
+
+let ownHash = null
+let ownHashPromise = null
+function run (zalgo, paths, salt) {
+ if (!ownHash) {
+ return zalgo.run({
+ async () {
+ if (!ownHashPromise) {
+ ownHashPromise = computeHash(zalgo, [PACKAGE_FILE])
+ }
+ return ownHashPromise
+ },
+ sync () {
+ return computeHash(zalgo, [PACKAGE_FILE])
+ }
+ })
+ .then(hash => {
+ ownHash = new Buffer(hash, 'hex')
+ ownHashPromise = null
+ return run(zalgo, paths, salt)
+ })
+ }
+
+ if (paths === PACKAGE_FILE && typeof salt === 'undefined') {
+ // Special case that allow the pepper value to be obtained. Mainly here for
+ // testing purposes.
+ return zalgo.returns(ownHash.toString('hex'))
+ }
+
+ paths = Array.isArray(paths) ? paths : [paths]
+ return computeHash(zalgo, paths, ownHash, salt)
+}
+
+module.exports = (paths, salt) => {
+ return run(releaseZalgo.async(), paths, salt)
+}
+module.exports.sync = (paths, salt) => {
+ const result = run(releaseZalgo.sync(), paths, salt)
+ return releaseZalgo.unwrapSync(result)
+}