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

Rewrite paths for globby to use forward slash #5386

Merged
merged 6 commits into from Jul 14, 2021
Merged

Rewrite paths for globby to use forward slash #5386

merged 6 commits into from Jul 14, 2021

Conversation

tbowmo
Copy link
Contributor

@tbowmo tbowmo commented Jul 7, 2021

Fixes windows paths for globby, by replacing backward slash with forward slashes

Closes #5122

No, it's self-explanatory.

if (fs.existsSync(absolutePath)) {
// This path points to a file. Return an escaped path to avoid globbing
return fastGlob.escapePath(entry);
}

// Flip backward slash to forward slash (windows compatability)

Choose a reason for hiding this comment

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

Runaway comment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed it..

@@ -175,11 +175,14 @@ module.exports = function (options) {
const cwd = _.get(globbyOptions, 'cwd', process.cwd());
const absolutePath = !path.isAbsolute(entry) ? path.join(cwd, entry) : path.normalize(entry);

entry = entry.replace(/\\(?![[\]()])/g, '/');

Choose a reason for hiding this comment

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

Perhaps you can add a unit test on this behaviour, to make sure it doesn't break in the future

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added unit test for windows style backslash in paths

Copy link

@woutervanvliet woutervanvliet left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

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

@tbowmo Thanks for creating this PR. Could you consider the following suggestions, please?

  • Can you change the base branch to v14?
    We have pushed many commits for the next version 14.0.0. (see Release 14.0.0 #5205)

  • According to the FAQ on fast-glob, which is a base package of globby, it seems better to me to use normalize-path because it is well-tested. What do you think?

    📖 Use the normalize-path or the unixify package to convert Windows-style path to a Unix-style path.

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

@ybiquitous I'll move the changes to the v14 branch instead.. And also have a look at normalize-path.. It was a quick solution that was made in the first place (that is working..)

@tbowmo tbowmo changed the base branch from master to v14 July 12, 2021 13:03
@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

@ybiquitous I tried to use normalize-path, as suggested. (just replaced the regex that I added in standalone.js, with the following:

---		entry = entry = entry.replace(/\\(?![[\]()])/g, '/');
+++		entry = normalize(entry);

And added the required dependencies.. However, this breaks one of the tests:
● standalone globbing › mixed globs and paths with special chars › manual escaping
No files matching the pattern "/home/thomas/gits/stylelint/lib/tests/fixtures/globs/got/[braces/] and /(spaces/)/*.+(s|c)ss" were found.

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

btw. what is the timeframe for releasing v14? (I think @woutervanvliet is eager to get this fix into "production" as the current behavior is breaking a couple of developers machines, as they insist running windows only)

@ybiquitous
Copy link
Member

@tbowmo Sorry for the late reply. My answers are as below.


#5386 (comment)

I think we should convert back-slashes (\) to forward-slashes (/) only when actual file paths are specified (not globs) because:

So hers is my suggestion code, fixing also the test case:

diff --git a/lib/__tests__/standalone-globs.test.js b/lib/__tests__/standalone-globs.test.js
index 8254794d..ed28cd79 100644
--- a/lib/__tests__/standalone-globs.test.js
+++ b/lib/__tests__/standalone-globs.test.js
@@ -113,8 +113,11 @@ describe('standalone globbing', () => {
 	});
 
 	describe('windows path style with backslash', () => {
+		// The tests fail on non-windows environments.
+		if (process.platform !== 'win32') { return }
+
 		it('should handle normal backslash in glob pattern', async () => {
-			const cssGlob = `${fixturesPath}\\with spaces\\*.+(s|c)ss`;
+			const cssGlob = path.win32.join(fixturesPath, "globs", "with spaces", "styles.css");
 
 			const { results } = await standalone({
 				files: cssGlob,
diff --git a/lib/standalone.js b/lib/standalone.js
index 385d7b33..87b672b1 100644
--- a/lib/standalone.js
+++ b/lib/standalone.js
@@ -19,6 +19,7 @@ const { default: ignore } = require('ignore');
 const DEFAULT_IGNORE_FILENAME = '.stylelintignore';
 const FILE_NOT_FOUND_ERROR_CODE = 'ENOENT';
 const ALWAYS_IGNORED_GLOBS = ['**/node_modules/**'];
+const normalizePath = require('normalize-path');
 const writeFileAtomic = require('write-file-atomic');
 
 /** @typedef {import('stylelint').StylelintStandaloneOptions} StylelintStandaloneOptions */
@@ -174,11 +175,9 @@ module.exports = function (options) {
 		const cwd = (globbyOptions && globbyOptions.cwd) || process.cwd();
 		const absolutePath = !path.isAbsolute(entry) ? path.join(cwd, entry) : path.normalize(entry);
 
-		entry = entry.replace(/\\(?![[\]()])/g, '/');
-
 		if (fs.existsSync(absolutePath)) {
 			// This path points to a file. Return an escaped path to avoid globbing
-			return fastGlob.escapePath(entry);
+			return fastGlob.escapePath(normalizePath(entry));
 		}
 
 		return entry;
  • Run normalizePath() only when specified paths exists on a file system
  • Run the test only for a windows environment

#5386 (comment)

As you see the v14.0.0 issue, we have a lot of tasks to release v14.0.0. So I cannot promise the release date, unfortunately. 😞

Perhaps, I think there are the following workarounds for this problem:

  • Use your forked version based on this PR’s change, such as "stylelint": "your-github-orb/stylelint#fix-win-path-problem"
  • Specify unix-like paths, such as c:/dev/myfile.scss instead of c:\dev\myfile.scss

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

I'm not that big a fan of making conditions for when tests are run.. If the majority of devs are using unix like systems, then we never will run the tests for windows platform, unless you run the tests in the CI pipeline somehow, and then we can break the functionality for windows (like it is right now with the latest 13.x release)

I'll re-think testing for the windows paths when I get a bit more headroom (@woutervanvliet you usually have a couple of hints as well ;))

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

The above changes needs to be tested on a windows only system (no wsl), which I do not have access to at the moment (work pc is shutdown for 3 weeks of summer holidays)

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 12, 2021

I fired up a win10 in virtualbox, for a quick spin of the tests, which unfortunately fails (on the windows path tests).. So I'll look into making a more permanent test setup on my tinkering machine, while debugging / testing this windows issue..

@ybiquitous
Copy link
Member

Yes, I also agree that we should avoid environment-specific tests if possible.

@tbowmo
Copy link
Contributor Author

tbowmo commented Jul 13, 2021

Looked into it, I did the changes requested by @ybiquitous but that also fails when running the tests on windows! The extra test that I wrote, fails as the following bit of code:

	fileList = fileList.map((entry) => {
		const cwd = (globbyOptions && globbyOptions.cwd) || process.cwd();
		const absolutePath = !path.isAbsolute(entry) ? path.join(cwd, entry) : path.normalize(entry);

		if (fs.existsSync(absolutePath)) {
			// This path points to a file. Return an escaped path to avoid globbing
			return fastGlob.escapePath(normalizePath(entry));
		}

		return entry;
	});

will not enter the if clause, as f.existsSync(absolutePath) returns false.

Thereby it doesn't rewrite the entry through normalizePath.

I then rewrote it, so I always throw entry through normalize path, like:

	fileList = fileList.map((entry) => {
		const cwd = (globbyOptions && globbyOptions.cwd) || process.cwd();
		const absolutePath = !path.isAbsolute(entry) ? path.join(cwd, entry) : path.normalize(entry);

		entry = normalizePath(entry);

		if (fs.existsSync(absolutePath)) {
			// This path points to a file. Return an escaped path to avoid globbing
			return fastGlob.escapePath(entry);
		}

		return entry;
	});

but that also fails tests on windows ?!?!?

I then reverted to just use the regular expression as in my initial PR, and then it passes.. That test is passing on both windows and linux hosts.

@ybiquitous
Copy link
Member

ybiquitous commented Jul 14, 2021

@tbowmo Sorry, my suggestion code (test file path) is bad. globs is needless. 🙇🏼

-const cssGlob = path.win32.join(fixturesPath, 'globs', 'with spaces', 'styles.css');
+const cssGlob = path.win32.join(fixturesPath, 'with spaces', 'styles.css');

EDITED: I think fs.existsSync(absolutePath) should return true.

Copy link
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

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

Thank you for fixing the test failure (a65f668)!

lib/__tests__/standalone-globs.test.js Outdated Show resolved Hide resolved
Copy link
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

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

Thanks! LGTM 👍🏼

Copy link
Member

@jeddy3 jeddy3 left a comment

Choose a reason for hiding this comment

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

Thank you!

@jeddy3 jeddy3 merged commit 336cf15 into stylelint:v14 Jul 14, 2021
@jeddy3
Copy link
Member

jeddy3 commented Jul 14, 2021

v14 changelog entry added:

  • Fixed: "No files matching the pattern" when using backslash paths on Windows (#5386).

if (fs.existsSync(absolutePath)) {
// This path points to a file. Return an escaped path to avoid globbing
return fastGlob.escapePath(entry);
return fastGlob.escapePath(normalizePath(entry));

Choose a reason for hiding this comment

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

This only works when path is absolute, if applying a pattern like "**/*.scss" that is not absolute, it still fails.
I tried to run with
entry = entry.replace(/\(?![[]()])/g, '/');

it works, I have not read all comments what was the reason to remove it.

Choose a reason for hiding this comment

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

entry = normalizePath(entry) needs to be before if (fs.existsSync(absolutePath)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@VikasAgarwal1984 this is an old (merged) pr, so if you think something needs changes, you should create a new pr for the changes.

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

Successfully merging this pull request may close these issues.

"No files matching the pattern" when using Windows
5 participants