Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does not work with square brackets in folder name #60

Closed
lexey111 opened this issue Aug 8, 2014 · 21 comments
Closed

Does not work with square brackets in folder name #60

lexey111 opened this issue Aug 8, 2014 · 21 comments

Comments

@lexey111
Copy link

lexey111 commented Aug 8, 2014

Hi,
I have a problem with very basic usage:

return gulp.src(<glob>)
        .pipe(watch(function(files) {
            console.log('Processing', files)

            return files.pipe(using())
                .pipe(debug());
        }));

if folder like [name] (with square brackets) exists in the working (glob) path - no 'change' events are fired after very first one. Problem exists on MacOS and Windows.

@floatdrop
Copy link
Owner

This is strange. Here is what you can do:

return watch({glob: <glob>}, function(files) {
    console.log('Processing', files)

    return files.pipe(using())
        .pipe(debug());
});

This will catch changed events in this file.

@lexey111
Copy link
Author

Unfortunately no differences. Same result.
This is my exact code:

watch({
    glob: ['public/**/*.cshtml'],
    timeout: 0,
    verbose: false,
    emitOnGlob: false
    }, function (files, done) {
    return files
        .pipe(localizer.translateFile())
        .pipe(gulp.dest(function (file) {
            return path.dirname(file.path);
        }))
        .pipe(synchro(function () {
            localizer.finalizeAndStat();
            console.log('OK.');
            done();
        }))
    });

(I tried also to remove all the logic and left only console output and got same results as well; timeout and emit are set for internal purposes and have no influence also).

and this code works excellent while no folders [with_name_like_this] exist in paths, but if I rename any folder to have brackets in the name, it fails.

@floatdrop
Copy link
Owner

Could you test, that gaze is catching events?

var gaze = require('gaze');

gaze('public/**/*.cshtml', function(err, watcher) {
    this.on('all', function(event, filepath) {
        console.log(filepath + ' was ' + event);
    });
});

@lexey111
Copy link
Author

Yes, it catches. At least I see 'public[Web.UI][components]\framework\activity\list\list-view.cshtml was changed' with '[]' and without them.

@floatdrop
Copy link
Owner

Thanks, this could be, because gulp.src is not emitting files properly. Could you check also this:

var gulp = require('gulp');

gulp.src('public[Web.UI][components]\framework\activity\list\list-view.cshtml')
    .on('data', console.log);

It would be very helpful.

@lexey111
Copy link
Author

It rather interesting. If I use

  gulp.src("c:/tutorials/gulp_test/public/[Web.UI]/[components]/framework/activity/list/list-view.cshtml")

I see nothing. (I've tried different separators like /, , //)
But with

  gulp.src(config.cshtmls)

where

  cshtmls: ['public/**/list-view.cshtml']

it works and prints

<File "[Web.UI]\[components]\framework\activity\list\list-view.cshtml" <Buffer 40 75 73 69 6e 6...

@floatdrop
Copy link
Owner

Yeah, that's strange.

@contra could you look at this?

@lexey111
Copy link
Author

Moreover,

gulp.src('c:\\tutorials\\gulp_test\\public\\translations.cshtml')

works, but

gulp.src('c:\\tutorials\\gulp_test\\public\\[Web.UI]\\translations.cshtml')

does not (file exists, of course).

@floatdrop
Copy link
Owner

Thanks for investigating, @lexey111! - I think this issue will be moved to vinyl-fs that provides src method (or even deeper in glob-stream). As soon as it will be fixed gulp-watch will pick up those files.

@lexey111
Copy link
Author

As far as I see now, problem is in Globule glob.sync that uses Glob module, that uses Minimatch, that treats path part like [Web.UI] as regexp, but it isn't. And somewhere during the processing escape characters are lost. For single files I can use workaround -

public/?Web.UI?/

but I don't know how to do this for glob patterns :(

@floatdrop
Copy link
Owner

There is an easy way out - rename your directories 👍

@lexey111
Copy link
Author

I can't - It's not MY directories, so have to use as is.
:(

@floatdrop
Copy link
Owner

Does escaping [ with \[ helps? I think it could be patched in Minimatch.

@lexey111
Copy link
Author

No, it does not.

Current state of investigation =) shows: it is required to change minimatch.js function parse, about line 650 such way:

    case "[":
        // swallow any state-tracking char before the [
        // add this option
        if (options.skipSquareBraces) {
            continue;
        }

and translate option through all the calls to force minimatch to skip processing [brackets].

But maybe other way exists... it is too low level patch, I'm afraid.Because minimatch is used multiple times/paths in the plugin's tree, and it has to be corrected everywhere...

@yocontra
Copy link

Because [ and ] are special characters in a glob, so if you use them directly you will have problems. If you really need a workaround replace them with * for the time being, the bug lies in minimatch

Also you could try skipSquareBraces: true to src which might get passed down to minimatch

@lexey111
Copy link
Author

The problem is: I can easily patch the minimatch.js module and can even make new fork, but minimatch is used in my project 12 times via dependencies of other modules. And it have 4 different versions (1.0.0, 0.2.14, 0.3.0, 0.4.0) so I don't know how to solve this problem... and I can't control the minimatch input to replace brackets by * or ?, because on my level I use gulp-watch -> that uses gaze -> that uses globule -> that uses glob (with wildcards) -> that uses minimatch...

@yocontra
Copy link

@lexey111 Send a PR to minimatch?

@lexey111
Copy link
Author

No, I think it is not an issue of minimatch. Well, frankly speaking it is, but changes only in minimatch module can't solve the problem.

My current working solution (very stupid one, I'm afraid, but I have no time to dig deeper) is:

  1. Changes in Gaze.js, where Gaze.prototype.add = function(files, done) {
this._patterns = helper.unique.apply(null, [this._patterns, files]);
// add these lines to replace "[" in patterns by "?"
if (this.options && (this.options.skipSquareBraces === true)) {
    for (var i = 0; i < this._patterns.length; i++) {
      this._patterns[i] = this._patterns[i].replace(/\[/g, '?');
    }
}

This will replace [-bracket and we'll have valid paths.

  1. Changes in index.js of gulp-watcher:
var nfs = require('fs');

...and near if(event === 'deleted') in duplex.gaze.on('all', ...

    if (opts.gaze && (opts.gaze.skipSquareBraces === true)){
        if (event === 'changed') {
            nfs.createReadStream(filepath).on('data', function(file) {
                var vfile = new vinyl({
                    path: filepath,
                    contents: file // it is a buffer
                });
                passThrough(vfile);
            });
        }
    }
  1. Call gulp-watcher with this new option:
watch({
    glob: <glob>,
    gaze: {skipSquareBraces: true}, 
    verbose: false
...

to has pass-through for changed file (otherwise no passthrough called). It works for me although I think other ways exist =)

@lexey111
Copy link
Author

So I think 2 PRs needed:one to gaze and second one here, gulp-watch, but I'd prefer to escalate things to @floatdrop , 'cause I'm not sure my solution is the best one - especially for 2)

@yocontra
Copy link

@lexey111 minimatch should be able to escape characters though

@floatdrop
Copy link
Owner

Issue moved to minimatch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants