63 lines
1.4 KiB
JavaScript
63 lines
1.4 KiB
JavaScript
|
/* jslint node: true */
|
||
|
'use strict';
|
||
|
|
||
|
// ENiGMA½
|
||
|
|
||
|
// deps
|
||
|
const fse = require('fs-extra');
|
||
|
const paths = require('path');
|
||
|
const async = require('async');
|
||
|
|
||
|
exports.moveFileWithCollisionHandling = moveFileWithCollisionHandling;
|
||
|
exports.pathWithTerminatingSeparator = pathWithTerminatingSeparator;
|
||
|
|
||
|
//
|
||
|
// Move |src| -> |dst| renaming to file(1).ext, file(2).ext, etc.
|
||
|
// in the case of collisions.
|
||
|
//
|
||
|
function moveFileWithCollisionHandling(src, dst, cb) {
|
||
|
const dstPath = paths.dirname(dst);
|
||
|
const dstFileExt = paths.extname(dst);
|
||
|
const dstFileSuffix = paths.basename(dst, dstFileExt);
|
||
|
|
||
|
let renameIndex = 0;
|
||
|
let movedOk = false;
|
||
|
let tryDstPath;
|
||
|
|
||
|
async.until(
|
||
|
() => movedOk, // until moved OK
|
||
|
(cb) => {
|
||
|
if(0 === renameIndex) {
|
||
|
// try originally supplied path first
|
||
|
tryDstPath = dst;
|
||
|
} else {
|
||
|
tryDstPath = paths.join(dstPath, `${dstFileSuffix}(${renameIndex})${dstFileExt}`);
|
||
|
}
|
||
|
|
||
|
fse.move(src, tryDstPath, err => {
|
||
|
if(err) {
|
||
|
if('EEXIST' === err.code) {
|
||
|
renameIndex += 1;
|
||
|
return cb(null); // keep trying
|
||
|
}
|
||
|
|
||
|
return cb(err);
|
||
|
}
|
||
|
|
||
|
movedOk = true;
|
||
|
return cb(null, tryDstPath);
|
||
|
});
|
||
|
},
|
||
|
(err, finalPath) => {
|
||
|
return cb(err, finalPath);
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function pathWithTerminatingSeparator(path) {
|
||
|
if(path && paths.sep !== path.charAt(path.length - 1)) {
|
||
|
path = path + paths.sep;
|
||
|
}
|
||
|
return path;
|
||
|
}
|