diff --git a/src/phoenix/fslib.js b/src/phoenix/fslib.js index 1e7b674bde..3669069b90 100644 --- a/src/phoenix/fslib.js +++ b/src/phoenix/fslib.js @@ -123,6 +123,12 @@ const fileSystemLib = { } return filerShell.rm(path, { recursive: true }, cb); }, + copyFile: function (src, dst, callback) { + if(Mounts.isMountSubPath(src) && Mounts.isMountSubPath(dst)) { + return NativeFS.copyFile(src, dst, callback); + } + throw new Errors.ENOSYS('Phoenix fs copy on filer or across filer and native not yet supported'); + }, showSaveDialog: function () { throw new Errors.ENOSYS('Phoenix fs showSaveDialog function not yet supported.'); }, diff --git a/src/phoenix/fslib_mounts.js b/src/phoenix/fslib_mounts.js index 4853dd8905..97af5bda60 100644 --- a/src/phoenix/fslib_mounts.js +++ b/src/phoenix/fslib_mounts.js @@ -271,6 +271,18 @@ function getHandleFromPath(normalisedPath, callback) { }); } +async function getHandleFromPathIfPresent(normalisedPath) { + return new Promise(resolve => { + getHandleFromPath(normalisedPath, (err, handle) =>{ + if(err) { + resolve(null); + } else { + resolve(handle); + } + }); + }); +} + function getMountPoints() { return MountPointsStore.getMountPoints(); } @@ -287,7 +299,8 @@ const Mounts = { isMountSubPath, getHandleFromPath, getMountPoints, - refreshMountPoints + refreshMountPoints, + getHandleFromPathIfPresent }; export default Mounts; diff --git a/src/phoenix/fslib_native.js b/src/phoenix/fslib_native.js index e0ce3c6c54..882ad17530 100644 --- a/src/phoenix/fslib_native.js +++ b/src/phoenix/fslib_native.js @@ -216,6 +216,54 @@ async function unlink(path, callback) { }); } +async function _getDestinationFileHandle(dst, srcFileName) { + return new Promise(async (resolve, reject) => { + dst = window.path.normalize(dst); + let dirPath= window.path.dirname(dst); + let dstFileName= window.path.basename(dst); + let dstHandle = await Mounts.getHandleFromPathIfPresent(dst); + let dstParentHandle = await Mounts.getHandleFromPathIfPresent(dirPath); + if (dstHandle && dstHandle.kind === Constants.KIND_FILE) { + reject(new Errors.EEXIST(`Copy file destination already exists: ${dst}`)); + } else if (dstHandle && dstHandle.kind === Constants.KIND_DIRECTORY) { + const fileHandle = await dstHandle.getFileHandle(srcFileName, {create: true}); + resolve(fileHandle); + } else if (!dstHandle && dstParentHandle && dstParentHandle.kind === Constants.KIND_DIRECTORY) { + const fileHandle = await dstParentHandle.getFileHandle(dstFileName, {create: true}); + resolve(fileHandle); + } else { + reject(new Errors.ENOENT(`Copy destination doesnt exist: ${dst}`)); + } + }); +} + +async function _copyFile(srcFileHandle, dst, srcFileName, callback) { + try { + let dstHandle = await _getDestinationFileHandle(dst, srcFileName); + const srcFile = await srcFileHandle.getFile(); + const srcStream = await srcFile.stream(); + const writable = await dstHandle.createWritable(); + await srcStream.pipeTo(writable); + callback(); + } catch (e) { + callback(e); + } +} + +async function copyFile(src, dst, callback) { + let srcFile = window.path.normalize(src); + let srcFileName= window.path.basename(srcFile); + Mounts.getHandleFromPath(srcFile, async (err, srcHandle) => { + if(err){ + callback(err); + } else if (srcHandle.kind === Constants.KIND_DIRECTORY) { + callback(new Errors.EISDIR(`Copy file cannot copy directory: ${srcFile}`)); + } else { + _copyFile(srcHandle, dst, srcFileName, callback); + } + }); +} + function mountNativeFolder(...args) { Mounts.mountNativeFolder(...args); } @@ -232,7 +280,8 @@ const NativeFS = { stat, readFile, writeFile, - unlink + unlink, + copyFile }; export default NativeFS; diff --git a/test/SpecRunner.html b/test/SpecRunner.html index d2c659c675..17c3c6d394 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -36,8 +36,11 @@ + + +