move.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. 'use strict'
  2. var fs = require('graceful-fs')
  3. var path = require('path')
  4. var chain = require('slide').chain
  5. var iferr = require('iferr')
  6. var rimraf = require('rimraf')
  7. var mkdirp = require('gentle-fs').mkdir
  8. var rmStuff = require('../../unbuild.js').rmStuff
  9. var lifecycle = require('../../utils/lifecycle.js')
  10. var move = require('../../utils/move.js')
  11. /*
  12. Move a module from one point in the node_modules tree to another.
  13. Do not disturb either the source or target location's node_modules
  14. folders.
  15. */
  16. module.exports = function (staging, pkg, log, next) {
  17. log.silly('move', pkg.fromPath, pkg.path)
  18. chain([
  19. [lifecycle, pkg.package, 'preuninstall', pkg.fromPath, { failOk: true }],
  20. [lifecycle, pkg.package, 'uninstall', pkg.fromPath, { failOk: true }],
  21. [rmStuff, pkg.package, pkg.fromPath],
  22. [lifecycle, pkg.package, 'postuninstall', pkg.fromPath, { failOk: true }],
  23. [moveModuleOnly, pkg.fromPath, pkg.path, log],
  24. [lifecycle, pkg.package, 'preinstall', pkg.path, { failOk: true }],
  25. [removeEmptyParents, path.resolve(pkg.fromPath, '..')]
  26. ], next)
  27. }
  28. function removeEmptyParents (pkgdir, next) {
  29. fs.rmdir(pkgdir, function (er) {
  30. // FIXME: Make sure windows does what we want here
  31. if (er && er.code !== 'ENOENT') return next()
  32. removeEmptyParents(path.resolve(pkgdir, '..'), next)
  33. })
  34. }
  35. function moveModuleOnly (from, to, log, done) {
  36. var fromModules = path.join(from, 'node_modules')
  37. var tempFromModules = from + '.node_modules'
  38. var toModules = path.join(to, 'node_modules')
  39. var tempToModules = to + '.node_modules'
  40. log.silly('move', 'move existing destination node_modules away', toModules)
  41. move(toModules, tempToModules).then(removeDestination(done), removeDestination(done))
  42. function removeDestination (next) {
  43. return function (er) {
  44. log.silly('move', 'remove existing destination', to)
  45. if (er) {
  46. rimraf(to, iferr(next, makeDestination(next)))
  47. } else {
  48. rimraf(to, iferr(next, makeDestination(iferr(next, moveToModulesBack(next)))))
  49. }
  50. }
  51. }
  52. function moveToModulesBack (next) {
  53. return function () {
  54. log.silly('move', 'move existing destination node_modules back', toModules)
  55. move(tempToModules, toModules).then(next, done)
  56. }
  57. }
  58. function makeDestination (next) {
  59. return function () {
  60. log.silly('move', 'make sure destination parent exists', path.resolve(to, '..'))
  61. mkdirp(path.resolve(to, '..'), iferr(done, moveNodeModules(next)))
  62. }
  63. }
  64. function moveNodeModules (next) {
  65. return function () {
  66. log.silly('move', 'move source node_modules away', fromModules)
  67. move(fromModules, tempFromModules).then(doMove(moveNodeModulesBack(next)), doMove(next))
  68. }
  69. }
  70. function doMove (next) {
  71. return function () {
  72. log.silly('move', 'move module dir to final dest', from, to)
  73. move(from, to).then(next, done)
  74. }
  75. }
  76. function moveNodeModulesBack (next) {
  77. return function () {
  78. mkdirp(from, iferr(done, function () {
  79. log.silly('move', 'put source node_modules back', fromModules)
  80. move(tempFromModules, fromModules).then(next, done)
  81. }))
  82. }
  83. }
  84. }