turtlemay / gulp-mem

Gulp in-memory destination with filesystem api and server middleware.
14 stars 3 forks source link

cannot write to subdirectories in-memory #3

Closed geekflyer closed 7 years ago

geekflyer commented 7 years ago

@turtlemay

let's say I have the following folder structure:

and the following gulp task:

gulp.src('src/**/*')
.pipe(gulpMem.dest('./'))

This will fail with the following error:

16:56:57] Using gulpfile ~/dev/gulp-mem/examples/gulp-webserver-example/gulpfile.js
[16:56:57] Starting 'default'...
[16:56:57] Writing file "/build/file1.js" to memory.
[16:56:57] Writing file "/build/subdir/file2.js" to memory.

/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/memory-fs/lib/MemoryFileSystem.js:207
                        throw new MemoryFileSystemError(errors.code.ENOENT, _path);
                        ^
Error: no such file or directory
    at MemoryFileSystem.writeFileSync (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/memory-fs/lib/MemoryFileSystem.js:207:10)
    at DestroyableTransform.through2.obj [as _transform] (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/gulp-mem/index.js:49:19)
    at DestroyableTransform.Transform._read (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:159:10)
    at DestroyableTransform.Transform._write (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/through2/node_modules/readable-stream/lib/_stream_transform.js:147:83)
    at doWrite (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:345:64)
    at writeOrBuffer (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:334:5)
    at DestroyableTransform.Writable.write (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/through2/node_modules/readable-stream/lib/_stream_writable.js:271:11)
    at write (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:623:24)
    at flow (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:632:7)
    at DestroyableTransform.pipeOnReadable (/Users/d061084/dev/gulp-mem/examples/gulp-webserver-example/node_modules/vinyl-fs/node_modules/readable-stream/lib/_stream_readable.js:664:5)

This because gulp-mem does not handle / create subdirectories properly before attempting to write a file into it.

The root cause is basically here: https://github.com/turtlemay/gulp-mem/blob/master/index.js#L40-L44

The if branch to create an in memory directory is only reached when file.isBuffer() === true. However a directory is never a buffer, so effectively gulp-mem will never ever create a subdirectory and the branch is basically currently unreachable code. Even if the if-condition is fixed I think you should not rely on vinyl directories being passed at all to the plugin (some plugins which generate completely new files in virtual subdirectories don't create the corresponding folders as vinyl file). Instead you should just automatically create the subdirectories for every file, by calling fs.mkdirpSync before every file is being written. This will be closer to how gulp.dest behaves against a real file system.

geekflyer commented 7 years ago

I also just checked the implementation of gulp.dest / vfs.dest and indeed they're calling mkdirp before every file write. There is a function prepareWrite that is called before every single vinyl file is written and inside that prepareWrite is a mkdirp: https://github.com/gulpjs/vinyl-fs/blob/master/lib/prepare-write.js#L52

turtlemay commented 7 years ago

Thanks! Fixed directory handling in cdcca64393873db20f3c1f45e5b10345fd1f3f40 and a07f24c90e54ec7e20ff19268c278d30e3d46db5 (no longer relying on vinyl directories).