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

Fix: ignored-paths for Windows path (fixes #10687) #10691

Merged
merged 8 commits into from
Aug 2, 2018
Merged

Conversation

mysticatea
Copy link
Member

What is the purpose of this pull request? (put an "X" next to item)

[X] Bug fix: fixes #10687

What changes did you make? (Give an overview)

This PR fixes some problems of ignored-paths on Windows.

  1. Fixes that the Windows path separator is mixed into patterns.
  2. Fixes that it doesn't handle CRLF line separators correctly in .eslintignore files.

Is there anything you'd like reviewers to focus on?

I'm not sure why Appvoyer didn't find this...

@mysticatea mysticatea added bug ESLint is working incorrectly core Relates to ESLint's core APIs and features accepted There is consensus among the team that this change meets the criteria for inclusion labels Jul 28, 2018
? relativePathToOldBaseDir.replace(/\\/g, "/")
: relativePathToOldBaseDir;

return `${prefix}/${relativePathPrefix}${globWithoutPrefix}`;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found relativePathToOldBaseDir can be ../../../foo/bar, is this a problem?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it might be. I had assumed that one of this.ignoreFileDir and this.options.cwd would be the parent of the other. If this.ignoreFileDir and this.options.cwd are in different directories, maybe this.getBaseDir() should return a common ancestor.

@@ -94,7 +94,11 @@ function relativize(globPattern, relativePathToOldBaseDir) {
const globWithoutPrefix = globPattern.replace(/^!/, "");

if (globWithoutPrefix.startsWith("/")) {
return `${prefix}/${relativePathToOldBaseDir}${globWithoutPrefix}`;
const relativePathPrefix = (typeof process !== "undefined" && process.platform === "win32")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be:

const relativePathPrefix = relativePathToOldBaseDir.replace(
    new RegExp(`\\${path.sep}`, "g"),
    "/"
);

That would avoid the need to depend on process.

@mysticatea mysticatea force-pushed the issue10687 branch 2 times, most recently from 35e5724 to 82b83c4 Compare July 28, 2018 06:23
@mysticatea
Copy link
Member Author

I updated this PR.

Copy link
Member

@platinumazure platinumazure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With some of the logic we're doing to handle filesystem-specific quirks, should we add debug() calls for some of the transformations (showing before vs after)?

Otherwise LGTM.

@mysticatea
Copy link
Member Author

I added some debug()s.

Copy link
Member

@platinumazure platinumazure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Copy link
Member

@not-an-aardvark not-an-aardvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple more comments, but this mostly looks good.

this._baseDir = a.length < b.length ? a : b;

// Set the common ancestor.
for (let i = 0; i < a.length && i < b.length; ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work to split on path.sep rather than iterating over each character?

const cwd = path.resolve(this.options.cwd);
const ignoreFileDir = path.resolve(this.ignoreFileDir);

if (cwd === ignoreFileDir) {
    this._baseDir = cwd;
} else {
    const cwdParts = cwd.split(path.sep);
    const ignoreFileDirParts = ignoreFileDir.split(path.sep);

    const longerParts = cwdParts.length > ignoreFileDirParts.length
        ? cwdParts
        : ignoreFileDirParts;

    this._baseDir = longerParts.slice(
        0,
        longerParts.findIndex((_, index) => cwdParts[index] !== ignoreFileDirParts[index])
    );
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I wrote that code as being careful to use only one traverse on the path strings. Indeed, though it's O(n) as is...


assert.strictEqual(ignoredPaths.getBaseDir(), path.resolve(ignoreFilePath, "../../.."));
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add tests for an ignore file with \r\n? (Git would convert the linebreaks to \n when the repository is cloned, so it would probably be necessary to create the file at runtime.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it.


assert.strictEqual(ignoredPaths.getBaseDir(), path.resolve(ignoreFilePath, "../../.."));
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add tests for ignoredPaths.contains when ignoreFilePath and cwd are siblings? It would be useful to make sure that the default ignore patterns (e.g. node_modules) and custom ignore patterns both work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably I added it.


assert.strictEqual(ignoredPaths.getBaseDir(), path.resolve(ignoreFilePath, "../../.."));
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it feasible to add a test for when the baseDir is only a windows drive letter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The base directory was only a Windows drive letter on Appvoyer environments.
But I'm not sure if we can write such a test safely or not, because of permissions. On my PC, the base directory has often became the home directory of my login user because the temporary directory for tests is in ~\AppData\Local\Temp.

Copy link
Member

@not-an-aardvark not-an-aardvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@mysticatea mysticatea merged commit 5c5d64d into master Aug 2, 2018
@mysticatea mysticatea deleted the issue10687 branch August 2, 2018 05:56
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Jan 30, 2019
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Jan 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly core Relates to ESLint's core APIs and features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Some tests about .eslintignore file are failing on Windows
3 participants