Skip to content

Inconsistent File Format Handling Between Windows and POSIX in fast-glob #425

@saoudi-h

Description

@saoudi-h

Environment

  • OS Version: windows 11
  • Node.js Version: 20.7

Actual behavior

Hello,

I'd like to report an issue that was initially raised on the Prettier repository prettier/prettier#15426, but ultimately led us to examine Fast-glob. It turns out that Prettier uses Fast-glob to resolve patterns, especially for Prettier-cli. Specifically, in my case, it's about the following command: npx prettier --write [...nextauth].ts, which seems to be a filename format accepted on all operating systems.

It appeared to me that Fast-glob uses two different patterns, one for POSIX systems and another for Windows:

See: https://github.com/mrmlnc/fast-glob/blob/28a3d61e44d5d9193ba97de4f21df6dc7725f7c0/src/utils/path.ts#L13C1-L14C94

which ends up giving two different behaviors depending on whether you are on Linux or Windows.

I don't know the full implications of this, but I know that for my example the brackets "[]" in Windows are not escaped when we call the escapePath() method

This returns on Linux

./myfolder/\[.myFile\].ts 

and on Windows.

./myfolder/[.myfile].ts 

Expected behavior

I believe that if Windows supports this naming format for these files, then Fast-glob should ensure it conforms to it.

Steps to reproduce

on windows:

  1. Create a small project:
mkdir fg-issue && cd fg-issue
npm init
npm i fast-glob
  1. Create an index.js file with the following content:
// index.js

const fg = require('fast-glob')

console.log(fg.escapePath('.[.any].any'))
  1. execute :
    pwsh or cmd:
>node index

out on windows: .[.any].any

Out on linux : .\[.any\].any

Code sample

A faster way to see the difference, although you'll have to trust me for the code I obtained from Fast-glob.
I've included only the essentials to reproduce the problem:

const path = "./any/[.any].ts";

const POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
const WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([(){}]|^!|[!+@](?=\())/g;

function escapeWindowsPath(pattern) {
    return pattern.replace(WINDOWS_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2');
}
function escapePosixPath(pattern) {
    return pattern.replace(POSIX_UNESCAPED_GLOB_SYMBOLS_RE, '\\$2');
}

console.log( "Posix : \n", escapePosixPath( path ) )
console.log( "Windows : \n", escapeWindowsPath( path ) )

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions