Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

fix: Empty basePath should not be treated as cwd #120

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions src/config-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ function assertValidFilesAndIgnores(config) {
FILES_AND_IGNORES_SCHEMA.validate(validateConfig);
}

/**
* A version of `path.relative()` that does not substitute `process.cwd()`
* when it sees an empty string. This is necessary because `basePath` can
* be an empty string in `ConfigArray`. In that case, we don't want the cwd
* to be substituted.
* @param {string} from The path to calculate from.
* @param {string} to The path to calculate to.
* @returns {string} The relative path between `from` and `to`.
*/
function safePathRelative(from, to) {
return from ? path.relative(from, to) : to;
}

/**
* Wrapper around minimatch that caches minimatch patterns for
* faster matching speed over multiple file path evaluations.
Expand Down Expand Up @@ -252,7 +265,7 @@ function pathMatchesIgnores(filePath, basePath, config) {
* file path while strings are compared against the relative
* file path.
*/
const relativeFilePath = path.relative(basePath, filePath);
const relativeFilePath = safePathRelative(basePath, filePath);

return Object.keys(config).length > 1 &&
!shouldIgnorePath(config.ignores, filePath, relativeFilePath);
Expand All @@ -277,7 +290,7 @@ function pathMatches(filePath, basePath, config) {
* file path while strings are compared against the relative
* file path.
*/
const relativeFilePath = path.relative(basePath, filePath);
const relativeFilePath = safePathRelative(basePath, filePath);

// match both strings and functions
const match = pattern => {
Expand Down Expand Up @@ -661,8 +674,10 @@ export class ConfigArray extends Array {
return result;
}

// TODO: Maybe move elsewhere? Maybe combine with getConfig() logic?
const relativeFilePath = path.relative(this.basePath, filePath);
/*
* TODO: Maybe move elsewhere? Maybe combine with getConfig() logic?
*/
const relativeFilePath = safePathRelative(this.basePath, filePath);

if (shouldIgnorePath(this.ignores, filePath, relativeFilePath)) {
debug(`Ignoring ${filePath}`);
Expand Down Expand Up @@ -719,8 +734,10 @@ export class ConfigArray extends Array {
return finalConfig;
}

// TODO: Maybe move elsewhere?
const relativeFilePath = path.relative(this.basePath, filePath);
/*
* TODO: Maybe move somewhere else?
*/
const relativeFilePath = safePathRelative(this.basePath, filePath);

if (shouldIgnorePath(this.ignores, filePath, relativeFilePath)) {
debug(`Ignoring ${filePath} based on file pattern`);
Expand Down Expand Up @@ -885,8 +902,7 @@ export class ConfigArray extends Array {

assertNormalized(this);

const relativeDirectoryPath = path.relative(this.basePath, directoryPath)
.replace(/\\/g, '/');
const relativeDirectoryPath = safePathRelative(this.basePath, directoryPath).replace(/\\/g, '/');

if (relativeDirectoryPath.startsWith('..')) {
return true;
Expand Down
150 changes: 150 additions & 0 deletions tests/config-array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,93 @@ describe('ConfigArray', () => {

});

// https://github.com/eslint/eslint/issues/17669
describe('basePath is an empty string', () => {

describe('with **/*.js', () => {
beforeEach(() => {
configs = new ConfigArray([
{
files: ['**/*.js'],
defs: {
severity: 'error'
}
}
], { basePath: '', schema });

configs.normalizeSync();
});

it('should return a config when a filename matches a files pattern', () => {

const config = configs.getConfig('foo.js');
expect(config).to.deep.equal({
defs: {
severity: 'error'
}
});
});

it('should return a config when a relative path filename matches a files pattern', () => {

const config = configs.getConfig('x/foo.js');
expect(config).to.deep.equal({
defs: {
severity: 'error'
}
});
});

it('should return a config when an absolute path filename matches a files pattern', () => {

const config = configs.getConfig('/x/foo.js');
expect(config).to.deep.equal({
defs: {
severity: 'error'
}
});
});
});

describe('with x/*.js', () => {
beforeEach(() => {
configs = new ConfigArray([
{
files: ['x/*.js'],
defs: {
severity: 'error'
}
}
], { basePath: '', schema });

configs.normalizeSync();
});

it('should return undefined when a filename does not match a files pattern', () => {

const config = configs.getConfig('foo.js');
expect(config).to.be.undefined;
});

it('should return a config when a relative path filename matches a files pattern', () => {

const config = configs.getConfig('x/foo.js');
expect(config).to.deep.equal({
defs: {
severity: 'error'
}
});
});

it('should return undefined when an absolute path filename does not match a files pattern', () => {

const config = configs.getConfig('/x/foo.js');
expect(config).to.be.undefined;
});
});

});

});

describe('isIgnored()', () => {
Expand Down Expand Up @@ -1742,6 +1829,69 @@ describe('ConfigArray', () => {
expect(configs.isExplicitMatch(filename)).to.be.false;
});

// https://github.com/eslint/eslint/issues/17669
describe('basePath is an empty string', () => {

describe('with **/*.js', () => {

beforeEach(() => {
configs = new ConfigArray([
{
files: ['**/*.js'],
defs: {
severity: 'error'
}
}
], { basePath: '', schema });

configs.normalizeSync();
});

it('should return true when a filename matches a files pattern', () => {
expect(configs.isExplicitMatch('foo.js')).to.be.true;
});

it('should return true when a relative path filename matches a files pattern', () => {
expect(configs.isExplicitMatch('x/foo.js')).to.be.true;
});

it('should return true when an absolute path filename matches a files pattern', () => {
expect(configs.isExplicitMatch('/x/foo.js')).to.be.true;
});
});

});

describe('with x/*.js', () => {

beforeEach(() => {
configs = new ConfigArray([
{
files: ['x/*.js'],
defs: {
severity: 'error'
}
}
], { basePath: '', schema });

configs.normalizeSync();
});

it('should return false when a filename does not match a files pattern', () => {
expect(configs.isExplicitMatch('foo.js')).to.be.false;
});

it('should return true when a relative path filename matches a files pattern', () => {
expect(configs.isExplicitMatch('x/foo.js')).to.be.true;
});

it('should return false when an absolute path filename does not match a files pattern', () => {
expect(configs.isExplicitMatch('/x/foo.js')).to.be.false;
});

});


});

describe('files', () => {
Expand Down