| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | 'use strict'const fs = require('graceful-fs')const path = require('path')const copySync = require('../copy-sync').copySyncconst removeSync = require('../remove').removeSyncconst mkdirpSync = require('../mkdirs').mkdirsSyncconst buffer = require('../util/buffer')function moveSync (src, dest, options) {  options = options || {}  const overwrite = options.overwrite || options.clobber || false  src = path.resolve(src)  dest = path.resolve(dest)  if (src === dest) return fs.accessSync(src)  if (isSrcSubdir(src, dest)) throw new Error(`Cannot move '${src}' into itself '${dest}'.`)  mkdirpSync(path.dirname(dest))  tryRenameSync()  function tryRenameSync () {    if (overwrite) {      try {        return fs.renameSync(src, dest)      } catch (err) {        if (err.code === 'ENOTEMPTY' || err.code === 'EEXIST' || err.code === 'EPERM') {          removeSync(dest)          options.overwrite = false // just overwriteed it, no need to do it again          return moveSync(src, dest, options)        }        if (err.code !== 'EXDEV') throw err        return moveSyncAcrossDevice(src, dest, overwrite)      }    } else {      try {        fs.linkSync(src, dest)        return fs.unlinkSync(src)      } catch (err) {        if (err.code === 'EXDEV' || err.code === 'EISDIR' || err.code === 'EPERM' || err.code === 'ENOTSUP') {          return moveSyncAcrossDevice(src, dest, overwrite)        }        throw err      }    }  }}function moveSyncAcrossDevice (src, dest, overwrite) {  const stat = fs.statSync(src)  if (stat.isDirectory()) {    return moveDirSyncAcrossDevice(src, dest, overwrite)  } else {    return moveFileSyncAcrossDevice(src, dest, overwrite)  }}function moveFileSyncAcrossDevice (src, dest, overwrite) {  const BUF_LENGTH = 64 * 1024  const _buff = buffer(BUF_LENGTH)  const flags = overwrite ? 'w' : 'wx'  const fdr = fs.openSync(src, 'r')  const stat = fs.fstatSync(fdr)  const fdw = fs.openSync(dest, flags, stat.mode)  let pos = 0  while (pos < stat.size) {    const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)    fs.writeSync(fdw, _buff, 0, bytesRead)    pos += bytesRead  }  fs.closeSync(fdr)  fs.closeSync(fdw)  return fs.unlinkSync(src)}function moveDirSyncAcrossDevice (src, dest, overwrite) {  const options = {    overwrite: false  }  if (overwrite) {    removeSync(dest)    tryCopySync()  } else {    tryCopySync()  }  function tryCopySync () {    copySync(src, dest, options)    return removeSync(src)  }}// return true if dest is a subdir of src, otherwise false.// extract dest base dir and check if that is the same as src basenamefunction isSrcSubdir (src, dest) {  try {    return fs.statSync(src).isDirectory() &&           src !== dest &&           dest.indexOf(src) > -1 &&           dest.split(path.dirname(src) + path.sep)[1].split(path.sep)[0] === path.basename(src)  } catch (e) {    return false  }}module.exports = {  moveSync}
 |