get.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. 'use strict'
  2. const BB = require('bluebird')
  3. const fs = require('fs')
  4. const index = require('./lib/entry-index')
  5. const memo = require('./lib/memoization')
  6. const pipe = require('mississippi').pipe
  7. const pipeline = require('mississippi').pipeline
  8. const read = require('./lib/content/read')
  9. const through = require('mississippi').through
  10. module.exports = function get (cache, key, opts) {
  11. return getData(false, cache, key, opts)
  12. }
  13. module.exports.byDigest = function getByDigest (cache, digest, opts) {
  14. return getData(true, cache, digest, opts)
  15. }
  16. function getData (byDigest, cache, key, opts) {
  17. opts = opts || {}
  18. const memoized = (
  19. byDigest
  20. ? memo.get.byDigest(cache, key, opts)
  21. : memo.get(cache, key, opts)
  22. )
  23. if (memoized && opts.memoize !== false) {
  24. return BB.resolve(byDigest ? memoized : {
  25. metadata: memoized.entry.metadata,
  26. data: memoized.data,
  27. integrity: memoized.entry.integrity,
  28. size: memoized.entry.size
  29. })
  30. }
  31. return (
  32. byDigest ? BB.resolve(null) : index.find(cache, key, opts)
  33. ).then(entry => {
  34. if (!entry && !byDigest) {
  35. throw new index.NotFoundError(cache, key)
  36. }
  37. return read(cache, byDigest ? key : entry.integrity, {
  38. integrity: opts.integrity,
  39. size: opts.size
  40. }).then(data => byDigest ? data : {
  41. metadata: entry.metadata,
  42. data: data,
  43. size: entry.size,
  44. integrity: entry.integrity
  45. }).then(res => {
  46. if (opts.memoize && byDigest) {
  47. memo.put.byDigest(cache, key, res, opts)
  48. } else if (opts.memoize) {
  49. memo.put(cache, entry, res.data, opts)
  50. }
  51. return res
  52. })
  53. })
  54. }
  55. module.exports.stream = getStream
  56. function getStream (cache, key, opts) {
  57. opts = opts || {}
  58. let stream = through()
  59. const memoized = memo.get(cache, key, opts)
  60. if (memoized && opts.memoize !== false) {
  61. stream.on('newListener', function (ev, cb) {
  62. ev === 'metadata' && cb(memoized.entry.metadata)
  63. ev === 'integrity' && cb(memoized.entry.integrity)
  64. ev === 'size' && cb(memoized.entry.size)
  65. })
  66. stream.write(memoized.data, () => stream.end())
  67. return stream
  68. }
  69. index.find(cache, key).then(entry => {
  70. if (!entry) {
  71. return stream.emit(
  72. 'error', new index.NotFoundError(cache, key)
  73. )
  74. }
  75. let memoStream
  76. if (opts.memoize) {
  77. let memoData = []
  78. let memoLength = 0
  79. memoStream = through((c, en, cb) => {
  80. memoData && memoData.push(c)
  81. memoLength += c.length
  82. cb(null, c, en)
  83. }, cb => {
  84. memoData && memo.put(cache, entry, Buffer.concat(memoData, memoLength), opts)
  85. cb()
  86. })
  87. } else {
  88. memoStream = through()
  89. }
  90. opts.size = opts.size == null ? entry.size : opts.size
  91. stream.emit('metadata', entry.metadata)
  92. stream.emit('integrity', entry.integrity)
  93. stream.emit('size', entry.size)
  94. stream.on('newListener', function (ev, cb) {
  95. ev === 'metadata' && cb(entry.metadata)
  96. ev === 'integrity' && cb(entry.integrity)
  97. ev === 'size' && cb(entry.size)
  98. })
  99. pipe(
  100. read.readStream(cache, entry.integrity, opts),
  101. memoStream,
  102. stream
  103. )
  104. }, err => stream.emit('error', err))
  105. return stream
  106. }
  107. module.exports.stream.byDigest = getStreamDigest
  108. function getStreamDigest (cache, integrity, opts) {
  109. opts = opts || {}
  110. const memoized = memo.get.byDigest(cache, integrity, opts)
  111. if (memoized && opts.memoize !== false) {
  112. const stream = through()
  113. stream.write(memoized, () => stream.end())
  114. return stream
  115. } else {
  116. let stream = read.readStream(cache, integrity, opts)
  117. if (opts.memoize) {
  118. let memoData = []
  119. let memoLength = 0
  120. const memoStream = through((c, en, cb) => {
  121. memoData && memoData.push(c)
  122. memoLength += c.length
  123. cb(null, c, en)
  124. }, cb => {
  125. memoData && memo.put.byDigest(
  126. cache,
  127. integrity,
  128. Buffer.concat(memoData, memoLength),
  129. opts
  130. )
  131. cb()
  132. })
  133. stream = pipeline(stream, memoStream)
  134. }
  135. return stream
  136. }
  137. }
  138. module.exports.info = info
  139. function info (cache, key, opts) {
  140. opts = opts || {}
  141. const memoized = memo.get(cache, key, opts)
  142. if (memoized && opts.memoize !== false) {
  143. return BB.resolve(memoized.entry)
  144. } else {
  145. return index.find(cache, key)
  146. }
  147. }
  148. module.exports.hasContent = read.hasContent
  149. module.exports.copy = function cp (cache, key, dest, opts) {
  150. return copy(false, cache, key, dest, opts)
  151. }
  152. module.exports.copy.byDigest = function cpDigest (cache, digest, dest, opts) {
  153. return copy(true, cache, digest, dest, opts)
  154. }
  155. function copy (byDigest, cache, key, dest, opts) {
  156. opts = opts || {}
  157. if (read.copy) {
  158. return (
  159. byDigest ? BB.resolve(null) : index.find(cache, key, opts)
  160. ).then(entry => {
  161. if (!entry && !byDigest) {
  162. throw new index.NotFoundError(cache, key)
  163. }
  164. return read.copy(
  165. cache, byDigest ? key : entry.integrity, dest, opts
  166. ).then(() => byDigest ? key : {
  167. metadata: entry.metadata,
  168. size: entry.size,
  169. integrity: entry.integrity
  170. })
  171. })
  172. } else {
  173. return getData(byDigest, cache, key, opts).then(res => {
  174. return fs.writeFileAsync(dest, byDigest ? res : res.data)
  175. .then(() => byDigest ? key : {
  176. metadata: res.metadata,
  177. size: res.size,
  178. integrity: res.integrity
  179. })
  180. })
  181. }
  182. }