Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict'
  2. const cp = require('child_process') // eslint-disable-line security/detect-child-process
  3. const path = require('path')
  4. const {promisify} = require('util')
  5. const fs = require('graceful-fs')
  6. const flattenDeep = require('lodash.flattendeep')
  7. const hasha = require('hasha')
  8. const releaseZalgo = require('release-zalgo')
  9. const PACKAGE_FILE = require.resolve('./package.json')
  10. const TEN_MEBIBYTE = 1024 * 1024 * 10
  11. const execFile = promisify(cp.execFile)
  12. const readFile = {
  13. async: promisify(fs.readFile),
  14. sync: fs.readFileSync
  15. }
  16. const tryReadFile = {
  17. async (file) {
  18. return readFile.async(file).catch(() => null)
  19. },
  20. sync (file) {
  21. try {
  22. return fs.readFileSync(file)
  23. } catch (err) {
  24. return null
  25. }
  26. }
  27. }
  28. const tryExecFile = {
  29. async (file, args, options) {
  30. return execFile(file, args, options)
  31. .then(({stdout}) => stdout)
  32. .catch(() => null)
  33. },
  34. sync (file, args, options) {
  35. try {
  36. return cp.execFileSync(file, args, options)
  37. } catch (err) {
  38. return null
  39. }
  40. }
  41. }
  42. const git = {
  43. tryGetRef (zalgo, dir, head) {
  44. const m = /^ref: (.+)$/.exec(head.toString('utf8').trim())
  45. if (!m) return null
  46. return zalgo.run(tryReadFile, path.join(dir, '.git', m[1]))
  47. },
  48. tryGetDiff (zalgo, dir) {
  49. return zalgo.run(tryExecFile,
  50. 'git',
  51. // Attempt to get consistent output no matter the platform. Diff both
  52. // staged and unstaged changes.
  53. ['--no-pager', 'diff', 'HEAD', '--no-color', '--no-ext-diff'],
  54. {
  55. cwd: dir,
  56. maxBuffer: TEN_MEBIBYTE,
  57. env: Object.assign({}, process.env, {
  58. // Force the GIT_DIR to prevent git from diffing a parent repository
  59. // in case the directory isn't actually a repository.
  60. GIT_DIR: path.join(dir, '.git')
  61. }),
  62. // Ignore stderr.
  63. stdio: ['ignore', 'pipe', 'ignore']
  64. })
  65. }
  66. }
  67. function addPackageData (zalgo, pkgPath) {
  68. const dir = path.dirname(pkgPath)
  69. return zalgo.all([
  70. dir,
  71. zalgo.run(readFile, pkgPath),
  72. zalgo.run(tryReadFile, path.join(dir, '.git', 'HEAD'))
  73. .then(head => {
  74. if (!head) return []
  75. return zalgo.all([
  76. zalgo.run(tryReadFile, path.join(dir, '.git', 'packed-refs')),
  77. git.tryGetRef(zalgo, dir, head),
  78. git.tryGetDiff(zalgo, dir)
  79. ])
  80. .then(results => {
  81. return [head].concat(results.filter(Boolean))
  82. })
  83. })
  84. ])
  85. }
  86. function computeHash (zalgo, paths, pepper, salt) {
  87. const inputs = []
  88. if (pepper) inputs.push(pepper)
  89. if (typeof salt !== 'undefined') {
  90. if (Buffer.isBuffer(salt) || typeof salt === 'string') {
  91. inputs.push(salt)
  92. } else if (typeof salt === 'object' && salt !== null) {
  93. inputs.push(JSON.stringify(salt))
  94. } else {
  95. throw new TypeError('Salt must be an Array, Buffer, Object or string')
  96. }
  97. }
  98. // TODO: Replace flattenDeep with Array#flat(Infinity) after node.js 10 is dropped
  99. return zalgo.all(paths.map(pkgPath => addPackageData(zalgo, pkgPath)))
  100. .then(furtherInputs => hasha(flattenDeep([inputs, furtherInputs]), {algorithm: 'sha256'}))
  101. }
  102. let ownHash = null
  103. let ownHashPromise = null
  104. function run (zalgo, paths, salt) {
  105. if (!ownHash) {
  106. return zalgo.run({
  107. async () {
  108. if (!ownHashPromise) {
  109. ownHashPromise = computeHash(zalgo, [PACKAGE_FILE])
  110. }
  111. return ownHashPromise
  112. },
  113. sync () {
  114. return computeHash(zalgo, [PACKAGE_FILE])
  115. }
  116. })
  117. .then(hash => {
  118. ownHash = Buffer.from(hash, 'hex')
  119. ownHashPromise = null
  120. return run(zalgo, paths, salt)
  121. })
  122. }
  123. if (paths === PACKAGE_FILE && typeof salt === 'undefined') {
  124. // Special case that allow the pepper value to be obtained. Mainly here for
  125. // testing purposes.
  126. return zalgo.returns(ownHash.toString('hex'))
  127. }
  128. paths = Array.isArray(paths) ? paths : [paths]
  129. return computeHash(zalgo, paths, ownHash, salt)
  130. }
  131. module.exports = (paths, salt) => {
  132. try {
  133. return run(releaseZalgo.async(), paths, salt)
  134. } catch (err) {
  135. return Promise.reject(err)
  136. }
  137. }
  138. module.exports.sync = (paths, salt) => {
  139. const result = run(releaseZalgo.sync(), paths, salt)
  140. return releaseZalgo.unwrapSync(result)
  141. }