blob_hash.js 2.0 KB

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