Skip to content

Commit

Permalink
Merge pull request #93 from papb/fix-move-exdev
Browse files Browse the repository at this point in the history
Make `jetpack.move` work cross-device
  • Loading branch information
szwacz authored Jul 19, 2020
2 parents e1a2517 + a37c218 commit 27ac63a
Showing 1 changed file with 36 additions and 29 deletions.
65 changes: 36 additions & 29 deletions lib/move.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const pathUtil = require("path");
const fs = require("./utils/fs");
const validate = require("./utils/validate");
const copy = require("./copy");
const dir = require("./dir");
const exists = require("./exists");
const remove = require("./remove");
Expand Down Expand Up @@ -44,30 +45,33 @@ const moveSync = (from, to, options) => {
throw generateDestinationExistsError(to);
}

// We now have permission to overwrite, since either `opts.overwrite` is true
// or the destination does not exist (in which overwriting is irrelevant).

try {
// If destination is a file, `fs.renameSync` will overwrite it.
fs.renameSync(from, to);
} catch (err) {
if (
(err.code === "EISDIR" || err.code === "EPERM") &&
opts.overwrite === true
) {
// Looks like the destination path is a directory,
// and we have permission for overwriting, so can remove it.
if (err.code === "EISDIR" || err.code === "EPERM") {
// Looks like the destination path is a directory in the same device,
// so we can remove it and call `fs.renameSync` again.
remove.sync(to);
// Retry the attempt
fs.renameSync(from, to);
} else if (err.code === "EXDEV") {
// The destination path is in another device.
copy.sync(from, to, { overwrite: true });
remove.sync(from);
} else if (err.code === "ENOENT") {
// Ok, source or destination path doesn't exist.
// Must do more investigation.
// This can be caused by either the source not existing or one or more folders
// in the destination path not existing.
if (!exists.sync(from)) {
throw generateSourceDoesntExistError(from);
}
if (!exists.sync(to)) {
// Some parent directory doesn't exist. Create it.
dir.createSync(pathUtil.dirname(to));
// Retry the attempt
fs.renameSync(from, to);
}

// One or more directories in the destination path don't exist.
dir.createSync(pathUtil.dirname(to));
// Retry the attempt
fs.renameSync(from, to);
} else {
// We can't make sense of this error. Rethrow it.
throw err;
Expand Down Expand Up @@ -104,32 +108,35 @@ const moveAsync = (from, to, options) => {
if (destinationExists !== false && opts.overwrite !== true) {
reject(generateDestinationExistsError(to));
} else {
// We now have permission to overwrite, since either `opts.overwrite` is true
// or the destination does not exist (in which overwriting is irrelevant).
// If destination is a file, `fs.rename` will overwrite it.
fs.rename(from, to)
.then(resolve)
.catch(err => {
if (
(err.code === "EISDIR" || err.code === "EPERM") &&
opts.overwrite === true
) {
// Looks like the destination path is a directory,
// and we have permission for overwriting, so can remove it.
if (err.code === "EISDIR" || err.code === "EPERM") {
// Looks like the destination path is a directory in the same device,
// so we can remove it and call `fs.rename` again.
remove
.async(to)
.then(() => {
// Retry the attempt
return fs.rename(from, to);
})
.then(resolve)
.catch(reject);
.then(() => fs.rename(from, to))
.then(resolve, reject);
} else if (err.code === "EXDEV") {
// The destination path is in another device.
copy
.async(from, to, { overwrite: true })
.then(() => remove.async(from))
.then(resolve, reject);
} else if (err.code === "ENOENT") {
// Ok, source or destination path doesn't exist.
// Must do more investigation.
// This can be caused by either the source not existing or one or more folders
// in the destination path not existing.
exists
.async(from)
.then(srcExists => {
if (!srcExists) {
reject(generateSourceDoesntExistError(from));
} else {
// One or more directories in the destination path don't exist.
ensureDestinationPathExistsAsync(to)
.then(() => {
// Retry the attempt
Expand Down

0 comments on commit 27ac63a

Please sign in to comment.