move.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. 'use strict'
  2. const fs = require('../fs')
  3. const path = require('path')
  4. const { copy } = require('../copy')
  5. const { remove } = require('../remove')
  6. const { mkdirp } = require('../mkdirs')
  7. const { pathExists } = require('../path-exists')
  8. const stat = require('../util/stat')
  9. async function move (src, dest, opts = {}) {
  10. const overwrite = opts.overwrite || opts.clobber || false
  11. const { srcStat, isChangingCase = false } = await stat.checkPaths(src, dest, 'move', opts)
  12. await stat.checkParentPaths(src, srcStat, dest, 'move')
  13. // If the parent of dest is not root, make sure it exists before proceeding
  14. const destParent = path.dirname(dest)
  15. const parsedParentPath = path.parse(destParent)
  16. if (parsedParentPath.root !== destParent) {
  17. await mkdirp(destParent)
  18. }
  19. return doRename(src, dest, overwrite, isChangingCase)
  20. }
  21. async function doRename (src, dest, overwrite, isChangingCase) {
  22. if (!isChangingCase) {
  23. if (overwrite) {
  24. await remove(dest)
  25. } else if (await pathExists(dest)) {
  26. throw new Error('dest already exists.')
  27. }
  28. }
  29. try {
  30. // Try w/ rename first, and try copy + remove if EXDEV
  31. await fs.rename(src, dest)
  32. } catch (err) {
  33. if (err.code !== 'EXDEV') {
  34. throw err
  35. }
  36. await moveAcrossDevice(src, dest, overwrite)
  37. }
  38. }
  39. async function moveAcrossDevice (src, dest, overwrite) {
  40. const opts = {
  41. overwrite,
  42. errorOnExist: true,
  43. preserveTimestamps: true
  44. }
  45. await copy(src, dest, opts)
  46. return remove(src)
  47. }
  48. module.exports = move