file.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const Fetcher = require('./fetcher.js')
  2. const fsm = require('fs-minipass')
  3. const cacache = require('cacache')
  4. const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
  5. const _exeBins = Symbol('_exeBins')
  6. const { resolve } = require('path')
  7. const fs = require('fs')
  8. const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
  9. class FileFetcher extends Fetcher {
  10. constructor (spec, opts) {
  11. super(spec, opts)
  12. // just the fully resolved filename
  13. this.resolved = this.spec.fetchSpec
  14. }
  15. get types () {
  16. return ['file']
  17. }
  18. manifest () {
  19. if (this.package) {
  20. return Promise.resolve(this.package)
  21. }
  22. // have to unpack the tarball for this.
  23. return cacache.tmp.withTmp(this.cache, this.opts, dir =>
  24. this.extract(dir)
  25. .then(() => this[_readPackageJson](dir + '/package.json'))
  26. .then(mani => this.package = {
  27. ...mani,
  28. _integrity: this.integrity && String(this.integrity),
  29. _resolved: this.resolved,
  30. _from: this.from,
  31. }))
  32. }
  33. [_exeBins] (pkg, dest) {
  34. if (!pkg.bin) {
  35. return Promise.resolve()
  36. }
  37. return Promise.all(Object.keys(pkg.bin).map(k => new Promise(res => {
  38. const script = resolve(dest, pkg.bin[k])
  39. // Best effort. Ignore errors here, the only result is that
  40. // a bin script is not executable. But if it's missing or
  41. // something, we just leave it for a later stage to trip over
  42. // when we can provide a more useful contextual error.
  43. fs.stat(script, (er, st) => {
  44. if (er) {
  45. return res()
  46. }
  47. const mode = st.mode | 0o111
  48. if (mode === st.mode) {
  49. return res()
  50. }
  51. fs.chmod(script, mode, res)
  52. })
  53. })))
  54. }
  55. extract (dest) {
  56. // if we've already loaded the manifest, then the super got it.
  57. // but if not, read the unpacked manifest and chmod properly.
  58. return super.extract(dest)
  59. .then(result => this.package ? result
  60. : this[_readPackageJson](dest + '/package.json').then(pkg =>
  61. this[_exeBins](pkg, dest)).then(() => result))
  62. }
  63. [_tarballFromResolved] () {
  64. // create a read stream and return it
  65. return new fsm.ReadStream(this.resolved)
  66. }
  67. packument () {
  68. // simulate based on manifest
  69. return this.manifest().then(mani => ({
  70. name: mani.name,
  71. 'dist-tags': {
  72. [this.defaultTag]: mani.version,
  73. },
  74. versions: {
  75. [mani.version]: {
  76. ...mani,
  77. dist: {
  78. tarball: `file:${this.resolved}`,
  79. integrity: this.integrity && String(this.integrity),
  80. },
  81. },
  82. },
  83. }))
  84. }
  85. }
  86. module.exports = FileFetcher