Skip to content

Commit a723b18

Browse files
committed
feat: fs.copy and tests
1 parent 1c0cb8b commit a723b18

7 files changed

Lines changed: 170 additions & 18 deletions

File tree

dist/virtualfs.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/virtualfs.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"test": "open-cli http://127.0.0.1:8080/test/index.html",
1919
"build-sw": "parcel build src/virtualfs.js --detailed-report",
2020
"build-nonopt": "parcel build src/virtualfs.js --detailed-report --no-optimize",
21-
"build": "npm run eslint && npm run build-sw",
21+
"build": "npm run eslint && npm run build-sw && echo '\\e[34m!!!please run build:dev if you are trying to debug!!!\\033[0m'",
2222
"build:dev": "npm run eslint && npm run build-nonopt",
2323
"predev": "npm run build",
2424
"serve": "http-server . -p 8080 -c-1",

src/filerlib_copy.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ async function _stat(path) {
3939
});
4040
}
4141

42-
async function _mrdirIfNotPresent(path) {
42+
async function _mkdirIfNotPresent(path) {
4343
return new Promise(async (resolve, reject) => {
4444
fs.mkdir(path, async (err) => {
4545
err && err.code !== ERROR_CODES.EEXIST?
@@ -112,7 +112,7 @@ async function _copyTree(src, dst) {
112112
if(srcStat.isFile()){
113113
await _copyFileContents(entryPath, dstPath);
114114
} else { //dir
115-
await _mrdirIfNotPresent(dstPath);
115+
await _mkdirIfNotPresent(dstPath);
116116
await _copyTree(entryPath, dstPath);
117117
}
118118
}
@@ -123,9 +123,16 @@ async function _copyFolder(srcFolder, dst) {
123123
if(dstStat && dstStat.isFile()){
124124
throw new Errors.EEXIST(`Destination file already exists: ${dst}`);
125125
} else if(dstStat && dstStat.isDirectory()){
126-
await _copyTree(srcFolder, dst);
126+
let destSubFolderPath= `${dst}/${globalObject.path.basename(srcFolder)}`;
127+
dstStat = await _stat(destSubFolderPath);
128+
if(dstStat){
129+
throw new Errors.EEXIST(`Destination folder already exists: ${destSubFolderPath}`);
130+
}
131+
await _mkdirIfNotPresent(destSubFolderPath);
132+
await _copyTree(srcFolder, destSubFolderPath);
127133
} else {
128-
throw new Errors.ENONET(`Destination folder does not exist: ${dst}`);
134+
await _mkdirIfNotPresent(dst);
135+
await _copyTree(srcFolder, dst);
129136
}
130137
}
131138

@@ -148,10 +155,10 @@ async function copy(src, dst, callback) {
148155
}
149156
}
150157

151-
function filerCopy(src, dst, cb) {
158+
function globalCopy(src, dst, cb) {
152159
copy(globalObject.path.normalize(src), globalObject.path.normalize(dst), cb);
153160
}
154161

155162
module.exports ={
156-
filerCopy
163+
globalCopy
157164
};

src/fslib.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const {NativeFS} = require('./fslib_native');
2626
const {Constants} = require('./constants');
2727
const {Mounts} = require('./fslib_mounts');
2828
const {FsWatch} = require('./fslib_watch');
29-
const {filerCopy} = require('./filerlib_copy.js');
29+
const {globalCopy} = require('./filerlib_copy.js');
3030

3131
let filerLib = null;
3232
let filerShell = null;
@@ -78,6 +78,11 @@ function _getFirstFunctionIndex(argsArray) {
7878
return -1;
7979
}
8080

81+
function _isSubPathOf(dir, subDir) {
82+
const relative = filerLib.path.relative(dir, subDir);
83+
return relative && !relative.startsWith('..') && !filerLib.path.isAbsolute(relative);
84+
}
85+
8186
const fileSystemLib = {
8287
mountNativeFolder: async function (...args) {
8388
return NativeFS.mountNativeFolder(...args);
@@ -178,7 +183,8 @@ const fileSystemLib = {
178183
}
179184

180185
if(Mounts.isMountPath(path)) {
181-
throw new Errors.EPERM('Mount root directory cannot be deleted.');
186+
callbackInterceptor(new Errors.EPERM('Mount root directory cannot be deleted.'));
187+
return ;
182188
} else if(Mounts.isMountSubPath(path)) {
183189
return NativeFS.unlink(path, callbackInterceptor);
184190
}
@@ -198,13 +204,17 @@ const fileSystemLib = {
198204
cb(...args);
199205
}
200206
}
201-
207+
if (_isSubPathOf(src, dst)){
208+
callbackInterceptor(new Errors.EINVAL(`Error copying: ${dst} cannot be a subpath of ${src}`));
209+
return ;
210+
}
211+
// we have two implementation here even though the globalCopy fn is capable of copying anywhere. Native has its
212+
// own impl to prevent large number of file node io in fs access impl.
202213
if(Mounts.isMountSubPath(src) && Mounts.isMountSubPath(dst)) {
203214
return NativeFS.copy(src, dst, callbackInterceptor);
204-
} else if(!Mounts.isMountSubPath(src) && !Mounts.isMountSubPath(dst)) {
205-
return filerCopy(src, dst, callbackInterceptor);
215+
} else {
216+
return globalCopy(src, dst, callbackInterceptor);
206217
}
207-
throw new Errors.ENOSYS('Phoenix fs copy across filer and native not yet supported');
208218
},
209219
showSaveDialog: function () {
210220
throw new Errors.ENOSYS('Phoenix fs showSaveDialog function not yet supported.');

src/fslib_watch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function _triggerEvent(path, eventType) {
103103
path = pathLib.normalize(path);
104104
let event = {
105105
event: eventType,
106-
parentDirPath: `${pathLib.dirname(path)}/`,
106+
parentDirPath: pathLib.normalize(`${pathLib.dirname(path)}/`),
107107
entryName: pathLib.basename(path),
108108
path: path
109109
};

test/test.browser.js

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('Browser main tests', function () {
2727
expect(Filer.fs.name).to.equal('local');
2828
});
2929

30-
it('Should load Phoenix fs in browser',async function () {
30+
it('Should load clean Phoenix fs in browser',async function () {
3131
expect(fs).to.exist;
3232
expect(fs.name).to.equal('phoenixFS');
3333
// setup test folders
@@ -56,7 +56,7 @@ describe('Browser main tests', function () {
5656
cleanSuccess = true;
5757
});
5858
await waitForTrue(()=>{return cleanSuccess;},10000);
59-
});
59+
}, 10000);
6060

6161
it('Should phoenix native write in browser', async function () {
6262
let writeSuccess = false;
@@ -184,4 +184,139 @@ describe('Browser main tests', function () {
184184
await waitForTrue(()=>{return failed;},1000);
185185
expect(failed).to.be.true;
186186
});
187+
188+
function _createFolder(path) {
189+
return new Promise((resolve, reject)=>{
190+
fs.mkdir(path, 777, (err)=>{
191+
if(err){
192+
reject(err);
193+
} else {
194+
resolve();
195+
}
196+
});
197+
});
198+
}
199+
function _createFile(path) {
200+
return new Promise((resolve, reject)=>{
201+
fs.writeFile(path, 'hello World', 'utf8', (err)=>{
202+
if(!err){
203+
resolve();
204+
} else {
205+
reject();
206+
}
207+
});
208+
});
209+
}
210+
211+
function _shouldExist(path) {
212+
return new Promise((resolve)=>{
213+
fs.stat(path, (err)=>{
214+
if(err){
215+
resolve(false);
216+
} else {
217+
resolve(true);
218+
}
219+
});
220+
});
221+
}
222+
223+
async function _createTestFolderInBasePath(path, folderName) {
224+
await _createFolder(`${path}/${folderName}`);
225+
await _createFile(`${path}/${folderName}/a.txt`);
226+
await _createFile(`${path}/${folderName}/b.txt`);
227+
await _createFolder(`${path}/${folderName}/y`);
228+
await _createFolder(`${path}/${folderName}/z`);
229+
await _createFile(`${path}/${folderName}/y/c.txt`);
230+
}
231+
232+
async function _verifyCopyFolder(srcPath, dstPath, expectedPath) {
233+
let success = false;
234+
fs.copy(srcPath, dstPath, (err)=>{
235+
if(!err){
236+
success = true;
237+
}
238+
});
239+
await waitForTrue(()=>{return success;},1000);
240+
expect(success).to.be.true;
241+
expectedPath = expectedPath || dstPath;
242+
expect(await _shouldExist(`${expectedPath}/a.txt`)).to.be.true;
243+
expect(await _shouldExist(`${expectedPath}/y`)).to.be.true;
244+
expect(await _shouldExist(`${expectedPath}/y/c.txt`)).to.be.true;
245+
}
246+
247+
it('Should phoenix copy fail if dst is a subpath of src', async function () {
248+
let errored = false;
249+
fs.copy('/a', '/a/b', (err)=>{
250+
if(err){
251+
errored = true;
252+
}
253+
});
254+
await waitForTrue(()=>{return errored;},1000);
255+
expect(errored).to.be.true;
256+
});
257+
258+
it('Should phoenix copy folder from mount to filer path', async function () {
259+
await _createTestFolderInBasePath(window.mountTestPath, 'testDir2');
260+
let srcPath = `${window.mountTestPath}/testDir2`;
261+
let dstPath = `${window.virtualTestPath}/testDir2`;
262+
await _verifyCopyFolder(srcPath, dstPath);
263+
});
264+
265+
it('Should phoenix copy overwrite folder from mount to filer path if already exist', async function () {
266+
await _createTestFolderInBasePath(window.mountTestPath, 'testDir3');
267+
let srcPath = `${window.mountTestPath}/testDir3`;
268+
let dstPath = `${window.virtualTestPath}/testDir3`;
269+
let expectedPath = `${window.virtualTestPath}/testDir3/testDir3`;
270+
await _createFolder(dstPath);
271+
await _verifyCopyFolder(srcPath, dstPath, expectedPath);
272+
});
273+
274+
it('Should phoenix copy folder from filer to mount path', async function () {
275+
await _createTestFolderInBasePath(window.virtualTestPath, 'testDir4');
276+
let srcPath = `${window.virtualTestPath}/testDir4`;
277+
let dstPath = `${window.mountTestPath}/testDir4`;
278+
await _verifyCopyFolder(srcPath, dstPath);
279+
});
280+
281+
it('Should phoenix copy overwrite folder from filer to mount path if already exist', async function () {
282+
await _createTestFolderInBasePath(window.virtualTestPath, 'testDir5');
283+
let srcPath = `${window.virtualTestPath}/testDir5`;
284+
let dstPath = `${window.mountTestPath}/testDir5`;
285+
let expectedPath = `${window.mountTestPath}/testDir5/testDir5`;
286+
await _createFolder(dstPath);
287+
await _verifyCopyFolder(srcPath, dstPath, expectedPath);
288+
});
289+
290+
it('Should phoenix copy folder from filer to filer path', async function () {
291+
await _createTestFolderInBasePath(window.virtualTestPath, 'testDir6');
292+
let srcPath = `${window.virtualTestPath}/testDir6`;
293+
let dstPath = `${window.virtualTestPath}/testDir6.5`;
294+
await _verifyCopyFolder(srcPath, dstPath);
295+
});
296+
297+
it('Should phoenix copy overwrite folder from filer to filer path if already exist', async function () {
298+
await _createTestFolderInBasePath(window.virtualTestPath, 'testDir7');
299+
let srcPath = `${window.virtualTestPath}/testDir7`;
300+
let dstPath = `${window.virtualTestPath}/testDir7.5`;
301+
let expectedPath = `${window.virtualTestPath}/testDir7.5/testDir7`;
302+
await _createFolder(dstPath);
303+
await _verifyCopyFolder(srcPath, dstPath, expectedPath);
304+
});
305+
306+
it('Should phoenix copy folder from mount to mount path', async function () {
307+
await _createTestFolderInBasePath(window.mountTestPath, 'testDir8');
308+
let srcPath = `${window.mountTestPath}/testDir8`;
309+
let dstPath = `${window.mountTestPath}/testDir8.5`;
310+
await _verifyCopyFolder(srcPath, dstPath);
311+
});
312+
313+
it('Should phoenix copy as sub-folder from mount to mount if dest path already exist', async function () {
314+
await _createTestFolderInBasePath(window.mountTestPath, 'testDir9');
315+
let srcPath = `${window.mountTestPath}/testDir9`;
316+
let dstPath = `${window.mountTestPath}/testDir9.5`;
317+
let expectedPath = `${window.mountTestPath}/testDir9.5/testDir9`;
318+
await _createFolder(dstPath);
319+
await _verifyCopyFolder(srcPath, dstPath, expectedPath);
320+
});
321+
187322
});

0 commit comments

Comments
 (0)