sindresorhus / gulp-filter

Filter files in a `vinyl` stream
MIT License
315 stars 37 forks source link

Fixed code to use the correct relative path wrt the current working directory. #59

Closed cb1kenobi closed 8 years ago

cb1kenobi commented 8 years ago

gulp-filter uses file.relative to match the pattern, however file.relative is not always relative to the current working directory.

When you do gulp.src('*.js'), then all files appear to be relative to the current directory. However, if you do gulp.src('test/**/*.js'), then all of the files are actually relative to the test directory. The relative path is derived from the base path which is resolved via glob2base. Somewhere something isn’t taking into account the current working directory.

Other gulp plugins such as gulp-debug have observed this same issue. So the solution is to correctly resolve the relative path with respect to the current working directory, not the base path.

Before this fix, every file would have src and test absent from the file.relative path.

gulp.src(['src/**/*.js', 'test/**/*.js'])
    .pipe(...) // do stuff to both src and test files
    .pipe(filter('test/**/*.js')) // no matches :(
    .pipe(...); // do stuff to only test files
gulp.src(['src/**/*.js', 'test/**/*.js'])
    .pipe(...) // do stuff to both src and test files
    .pipe(filter('**/*.js')) // matches every .js file, but I only wanted test files :(
    .pipe(...); // do stuff to only test files

With this fix, you can properly filter patterns such as:

gulp.src(['src/**/*.js', 'test/**/*.js'])
    .pipe(...) // do stuff to both src and test files
    .pipe(filter('test/**/*.js'))
    .pipe(...); // do stuff to only test files
sindresorhus commented 8 years ago

Agreed. The whole thing with file.relative and file.base in gulp IMHO pretty flawed.

jimmytheneutrino commented 8 years ago

I disagree. The path relative to the base path is a natural concept in gulp. I rely on the former behaviour, when I do something in some subdirectory (or even multiple subdirectories). When the base is removed, it leaves me with the only important information of path. I do not want to prefix my filters, e.g., filter(conf.subdir1 + '**', '!' + conf.subdir1 + '*.html') filter(conf.subdir2 + '**', '!' + conf.subdir2 + '*.html') I just want to apply a simple filter against an already resolved set of paths: filter('**', '!*.html')

IMHO, 1) this behaviour should at least be configurable, 2) for backward-compatibility, the previous behaviour should be default.