blob_hash.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /** @module */
  2. 'use strict'
  3. const BPromise = require('bluebird')
  4. const fs = BPromise.promisifyAll(require('fs'))
  5. const crypto = require('crypto')
  6. const { pipeline } = require('stream')
  7. const assert = require('./assert')
  8. function getGitBlobHeader(byteLength) {
  9. return 'blob ' + byteLength + '\x00'
  10. }
  11. function getBlobHash(byteLength) {
  12. const hash = crypto.createHash('sha1')
  13. hash.setEncoding('hex')
  14. hash.update(getGitBlobHeader(byteLength))
  15. return hash
  16. }
  17. /**
  18. * Compute the git blob hash for a blob from a readable stream of its content.
  19. *
  20. * @function
  21. * @param {number} byteLength
  22. * @param {stream.Readable} stream
  23. * @return {Promise.<string>} hexadecimal SHA-1 hash
  24. */
  25. exports.fromStream = BPromise.method(function blobHashFromStream(
  26. byteLength,
  27. stream
  28. ) {
  29. assert.integer(byteLength, 'blobHash: bad byteLength')
  30. assert.object(stream, 'blobHash: bad stream')
  31. const hash = getBlobHash(byteLength)
  32. return new BPromise(function (resolve, reject) {
  33. pipeline(stream, hash, function (err) {
  34. if (err) {
  35. reject(err)
  36. } else {
  37. hash.end()
  38. resolve(hash.read())
  39. }
  40. })
  41. })
  42. })
  43. /**
  44. * Compute the git blob hash for a blob with the given string content.
  45. *
  46. * @param {string} string
  47. * @return {string} hexadecimal SHA-1 hash
  48. */
  49. exports.fromString = function blobHashFromString(string) {
  50. assert.string(string, 'blobHash: bad string')
  51. const hash = getBlobHash(Buffer.byteLength(string))
  52. hash.update(string, 'utf8')
  53. hash.end()
  54. return hash.read()
  55. }
  56. /**
  57. * Compute the git blob hash for the content of a file
  58. *
  59. * @param {string} filePath
  60. * @return {string} hexadecimal SHA-1 hash
  61. */
  62. exports.fromFile = function blobHashFromFile(pathname) {
  63. assert.string(pathname, 'blobHash: bad pathname')
  64. function getByteLengthOfFile() {
  65. return fs.statAsync(pathname).then(stat => stat.size)
  66. }
  67. const fromStream = this.fromStream
  68. return getByteLengthOfFile(pathname).then(function (byteLength) {
  69. const stream = fs.createReadStream(pathname)
  70. return fromStream(byteLength, stream)
  71. })
  72. }