remove.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use strict'
  2. var path = require('path')
  3. var fs = require('graceful-fs')
  4. var rimraf = require('rimraf')
  5. var asyncMap = require('slide').asyncMap
  6. var mkdirp = require('gentle-fs').mkdir
  7. var npm = require('../../npm.js')
  8. var andIgnoreErrors = require('../and-ignore-errors.js')
  9. var move = require('../../utils/move.js')
  10. var isInside = require('path-is-inside')
  11. var vacuum = require('fs-vacuum')
  12. // This is weird because we want to remove the module but not it's node_modules folder
  13. // allowing for this allows us to not worry about the order of operations
  14. module.exports = function (staging, pkg, log, next) {
  15. log.silly('remove', pkg.path)
  16. if (pkg.target) {
  17. removeLink(pkg, next)
  18. } else {
  19. removeDir(pkg, log, next)
  20. }
  21. }
  22. function removeLink (pkg, next) {
  23. var base = isInside(pkg.path, npm.prefix) ? npm.prefix : pkg.path
  24. rimraf(pkg.path, (err) => {
  25. if (err) return next(err)
  26. vacuum(pkg.path, {base: base}, next)
  27. })
  28. }
  29. function removeDir (pkg, log, next) {
  30. var modpath = path.join(path.dirname(pkg.path), '.' + path.basename(pkg.path) + '.MODULES')
  31. move(path.join(pkg.path, 'node_modules'), modpath).then(unbuildPackage, unbuildPackage)
  32. function unbuildPackage (moveEr) {
  33. rimraf(pkg.path, moveEr ? andRemoveEmptyParents(pkg.path) : moveModulesBack)
  34. }
  35. function andRemoveEmptyParents (path) {
  36. return function (er) {
  37. if (er) return next(er)
  38. removeEmptyParents(pkg.path)
  39. }
  40. }
  41. function moveModulesBack () {
  42. fs.readdir(modpath, makeTarget)
  43. }
  44. function makeTarget (readdirEr, files) {
  45. if (readdirEr) return cleanup()
  46. if (!files.length) return cleanup()
  47. mkdirp(path.join(pkg.path, 'node_modules'), function (mkdirEr) { moveModules(mkdirEr, files) })
  48. }
  49. function moveModules (mkdirEr, files) {
  50. if (mkdirEr) return next(mkdirEr)
  51. asyncMap(files, function (file, done) {
  52. var from = path.join(modpath, file)
  53. var to = path.join(pkg.path, 'node_modules', file)
  54. // we ignore errors here, because they can legitimately happen, for instance,
  55. // bundled modules will be in both node_modules folders
  56. move(from, to).then(andIgnoreErrors(done), andIgnoreErrors(done))
  57. }, cleanup)
  58. }
  59. function cleanup () {
  60. rimraf(modpath, afterCleanup)
  61. }
  62. function afterCleanup (rimrafEr) {
  63. if (rimrafEr) log.warn('remove', rimrafEr)
  64. removeEmptyParents(path.resolve(pkg.path, '..'))
  65. }
  66. function removeEmptyParents (pkgdir) {
  67. fs.rmdir(pkgdir, function (er) {
  68. // FIXME: Make sure windows does what we want here
  69. if (er && er.code !== 'ENOENT') return next()
  70. removeEmptyParents(path.resolve(pkgdir, '..'))
  71. })
  72. }
  73. }