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 @@
+
+
+