parcoursup/node_modules/package-hash/index.js

163 lines
4.2 KiB
JavaScript
Raw Normal View History

2023-03-05 13:23:23 +01:00
'use strict'
const cp = require('child_process') // eslint-disable-line security/detect-child-process
const path = require('path')
const {promisify} = require('util')
const fs = require('graceful-fs')
const flattenDeep = require('lodash.flattendeep')
const hasha = require('hasha')
const releaseZalgo = require('release-zalgo')
const PACKAGE_FILE = require.resolve('./package.json')
const TEN_MEBIBYTE = 1024 * 1024 * 10
const execFile = promisify(cp.execFile)
const readFile = {
async: promisify(fs.readFile),
sync: fs.readFileSync
}
const tryReadFile = {
async (file) {
return readFile.async(file).catch(() => null)
},
sync (file) {
try {
return fs.readFileSync(file)
} catch (err) {
return null
}
}
}
const tryExecFile = {
async (file, args, options) {
return execFile(file, args, options)
.then(({stdout}) => stdout)
.catch(() => null)
},
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')
}
}
// TODO: Replace flattenDeep with Array#flat(Infinity) after node.js 10 is dropped
return zalgo.all(paths.map(pkgPath => addPackageData(zalgo, pkgPath)))
.then(furtherInputs => hasha(flattenDeep([inputs, furtherInputs]), {algorithm: 'sha256'}))
}
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 = Buffer.from(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) => {
try {
return run(releaseZalgo.async(), paths, salt)
} catch (err) {
return Promise.reject(err)
}
}
module.exports.sync = (paths, salt) => {
const result = run(releaseZalgo.sync(), paths, salt)
return releaseZalgo.unwrapSync(result)
}