Repository: eslint/eslint (js)

Issue:
When running eslint from another directory and using --ignore-path, paths are not relative to .eslintignore location
**What version of ESLint are you using?**
3.1.1

**What parser (default, Babel-ESLint, etc.) are you using?**
default

**Please show your full configuration:**
Project structure:

```
.eslintignore
.eslintrc
bar.js
src/foo.js
```

.eslintrc

```
{
    "root": true,
    "extends": "eslint:recommended"
}
```

.eslintignore

```
src/foo.js
```

**What did you do? Please include the actual source code causing the issue.**

```
$ eslint foo.js --ignore-path ../.eslintignore

C:\dev\eslint-bug\src\foo.js
  1:1  error  'test' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)
```

**What did you expect to happen?**
Expected `C:\dev\eslint-bug\src\foo.js` to be ignored 

**What actually happened? Please include the actual, raw output from ESLint.**
Errors were reported for `C:\dev\eslint-bug\src\foo.js`:

```
C:\dev\eslint-bug\src\foo.js
  1:1  error  'test' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)
```

In [Configuring ESLint](http://eslint.org/docs/user-guide/configuring) it says "Paths are relative to `.eslintignore` location or the current working directory". As a user, I would assume that if I passed in `--ignore-path` that it would ignore files as if I had called ESLint from that directory. 

I see that there have been a lot of issues opened regarding ESLint ignore and parent directories, but after eslint/eslint#5694, ignoring files in SublimeText with SublimeLinter-eslint has been broken. There is an open PR to fix an existing issue with loading .eslintignore in SublimeLinter-eslint (roadhump/SublimeLinter-eslint#145), but it doesn't work after ESLint 2.5.0.

There is an option in the CLIEngine to specify a `cwd`. If my above process is "working as intended" (or perhaps I have misinterpreted the documentation), then it would be great to be able to pass in a `--cwd`option for the command line so that the relative paths can be loaded correctly.


Pull request description:
Breaking: Resolve patterns from .eslintignore directory (fixes #6759)
**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[X] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

https://github.com/eslint/eslint/issues/6759


**What changes did you make? (Give an overview)**
These changes will cause the `ignorePath`'s directory to be used to resolve the patterns in the `ignorePath`, regardless of the `cwd`.  This matches the behavior of `.gitignore`.  I also added two tests which fail without these changes and pass with them.

**Is there anything you'd like reviewers to focus on?**
Not particularly, it's pretty straightforward I think.  @kaelzhang had already called out what needed to be done in a `TODO` comment.


Patch:
diff --git a/lib/ignored-paths.js b/lib/ignored-paths.js
index cfca7fa4f..f69e1f61f 100644
--- a/lib/ignored-paths.js
+++ b/lib/ignored-paths.js
@@ -179,7 +179,7 @@ class IgnoredPaths {
 
         let result = false;
         const absolutePath = path.resolve(this.options.cwd, filepath);
-        const relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd);
+        const relativePath = pathUtil.getRelativePath(absolutePath, this.baseDir);
 
         if ((typeof category === "undefined") || (category === "default")) {
             result = result || (this.ig.default.filter([relativePath]).length === 0);
@@ -213,15 +213,7 @@ class IgnoredPaths {
 
         const filter = ig.createFilter();
 
-        /**
-         * TODO
-         * 1.
-         * Actually, it should be `this.options.baseDir`, which is the base dir of `ignore-path`,
-         * as well as Line 177.
-         * But doing this leads to a breaking change and fails tests.
-         * Related to #6759
-         */
-        const base = this.options.cwd;
+        const base = this.baseDir;
 
         return function(absolutePath) {
             const relative = pathUtil.getRelativePath(absolutePath, base);


Test patch:
diff --git a/tests/fixtures/ignored-paths/.eslintignoreForDifferentCwd b/tests/fixtures/ignored-paths/.eslintignoreForDifferentCwd
new file mode 100644
index 000000000..ac105c765
--- /dev/null
+++ b/tests/fixtures/ignored-paths/.eslintignoreForDifferentCwd
@@ -0,0 +1,1 @@
+/undef.js
diff --git a/tests/lib/ignored-paths.js b/tests/lib/ignored-paths.js
index e5891a8da..07d96672d 100644
--- a/tests/lib/ignored-paths.js
+++ b/tests/lib/ignored-paths.js
@@ -342,6 +342,13 @@ describe("IgnoredPaths", () => {
             assert.isFalse(ignoredPaths.contains(getFixturePath("sampleignorepattern")));
 
         });
+
+        it("should resolve relative paths from the ignorePath, not cwd", () => {
+            const ignoredPaths = new IgnoredPaths({ ignore: true, ignorePath: getFixturePath(".eslintignoreForDifferentCwd"), cwd: getFixturePath("subdir") });
+
+            assert.isFalse(ignoredPaths.contains(getFixturePath("subdir/undef.js")));
+            assert.isTrue(ignoredPaths.contains(getFixturePath("undef.js")));
+        });
     });
 
     describe("initialization with ignorePath containing commented lines", () => {
@@ -631,6 +638,17 @@ describe("IgnoredPaths", () => {
             assert.isFalse(shouldIgnore(resolve(".hidden")));
             assert.isFalse(shouldIgnore(resolve(".hidden/a")));
         });
+
+        it("should use the ignorePath's directory as the base to resolve relative paths, not cwd", () => {
+            const cwd = getFixturePath("subdir");
+            const ignoredPaths = new IgnoredPaths({ ignore: true, cwd, ignorePath: getFixturePath(".eslintignoreForDifferentCwd") });
+
+            const shouldIgnore = ignoredPaths.getIgnoredFoldersGlobChecker();
+            const resolve = createResolve(cwd);
+
+            assert.isFalse(shouldIgnore(resolve("undef.js")));
+            assert.isTrue(shouldIgnore(resolve("../undef.js")));
+        });
     });
 
 });