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

Prettier breaks when run through lint-staged on files with dollar sign ($) in the name #1397

Open
fernandocanizo opened this issue Feb 22, 2024 · 4 comments

Comments

@fernandocanizo
Copy link

Description

Yesterday I filed this issue to Prettier: File names with dollar sign ($) in the name cannot be processed by Prettier, but then I found out that the issue was only happening when running Prettier through lint-staged, if I run the npm script or the command defined in the npm script, it runs ok and doesn't complain about files with dollar sign.

So this seems to be an lint-staged issue, probably regarding the way lint-staged makes up the list of files to be fed to Prettier, but not sure, as I don't see any changes on file name on the debug log. It's correct up to the final lint-staged output, then runs Prettier and fails. But, again, if I run the same command directly instead of through lint-staged, Prettier doesn't explode.

So the issue is in the interaction of both tools.

Debug Logs

Context: there's only one change, a file renamed, no editions on the file.

$ git status
[...]
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    app/routes/old.$route.tsx -> app/routes/_auth.old.$route.tsx
[...]

Pre-commit hook:

$ cat .husky/pre-commit
npx lint-staged --debug

lint-staged configured through package.json, running an npm script called fix:styles that executes: prettier --experimental-ternaries --write .

  "lint-staged": {
    "*": [
      "pnpm fix:style",
      "eslint --quiet --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint"
    ]
  }

The command executed is git commit, which in turn launches lint-staged as per configuration

$ git commit
  lint-staged:bin Running `lint-staged@15.2.2` on Node.js v20.11.0 (linux) +0ms
  lint-staged:bin Options parsed from command-line: {
  allowEmpty: false,
  concurrent: true,
  configPath: undefined,
  cwd: undefined,
  debug: true,
  diff: undefined,
  diffFilter: undefined,
  maxArgLength: undefined,
  quiet: false,
  relative: false,
  shell: false,
  stash: true,
  hidePartiallyStaged: true,
  verbose: false
} +1ms
  lint-staged:validateOptions Validating options... +0ms
  lint-staged:validateOptions Validated options! +0ms
  lint-staged Unset GIT_LITERAL_PATHSPECS (was `undefined`) +0ms
  lint-staged:runAll Running all linter scripts... +0ms
  lint-staged:runAll Using working directory `/home/flc/my/smc/nexus2/third-nexus-client` +0ms
  lint-staged:resolveGitRepo Resolving git repo from `/home/flc/my/smc/nexus2/third-nexus-client` +0ms
  lint-staged:resolveGitRepo Unset GIT_DIR (was `undefined`) +0ms
  lint-staged:resolveGitRepo Unset GIT_WORK_TREE (was `undefined`) +0ms
  lint-staged:execGit Running git command [ 'rev-parse', '--show-prefix' ] +0ms
  lint-staged:resolveGitRepo Resolved git directory to be `/home/flc/my/smc/nexus2/third-nexus-client` +10ms
  lint-staged:resolveGitRepo Resolved git config directory to be `/home/flc/my/smc/nexus2/third-nexus-client/.git` +0ms
  lint-staged:execGit Running git command [ 'log', '-1' ] +10ms
  lint-staged:execGit Running git command [ 'diff', '--name-only', '-z', '--diff-filter=ACMR', '--staged' ] +4ms
  lint-staged:runAll Loaded list of staged files in git:
  lint-staged:runAll [
  lint-staged:runAll   '/home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old.$route.tsx'
  lint-staged:runAll ] +18ms
  lint-staged:searchConfigs Searching for configuration files... +0ms
  lint-staged:execGit Running git command [ 'ls-files', '-z', '--full-name', '-t' ] +4ms
  lint-staged:execGit Running git command [
  'ls-files',
  '-z',
  '--full-name',
  '-t',
  '--others',
  '--exclude-standard'
] +2ms
  lint-staged:searchConfigs Found possible config files: [ '/home/flc/my/smc/nexus2/third-nexus-client/package.json' ] +6ms
  lint-staged:loadConfig Loading configuration from `/home/flc/my/smc/nexus2/third-nexus-client/package.json`... +0ms
  lint-staged:loadConfig Successfully loaded config from `/home/flc/my/smc/nexus2/third-nexus-client/package.json`:
  lint-staged:loadConfig {
  lint-staged:loadConfig   '*': [
  lint-staged:loadConfig     'pnpm fix:style',
  lint-staged:loadConfig     'eslint --quiet --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint'
  lint-staged:loadConfig   ]
  lint-staged:loadConfig } +1ms
  lint-staged:validateConfig Validating config from `/home/flc/my/smc/nexus2/third-nexus-client/package.json`... +0ms
  lint-staged:validateConfig Validated config from `/home/flc/my/smc/nexus2/third-nexus-client/package.json`: +0ms
  lint-staged:validateConfig {
  lint-staged:validateConfig   '*': [
  lint-staged:validateConfig     'pnpm fix:style',
  lint-staged:validateConfig     'eslint --quiet --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint'
  lint-staged:validateConfig   ]
  lint-staged:validateConfig } +0ms
  lint-staged:searchConfigs Found 1 config files +1ms
  lint-staged:groupFilesByConfig Grouping 1 files by 1 configurations +0ms
  lint-staged:chunkFiles Resolved an argument string length of 74 characters from 1 files +0ms
  lint-staged:chunkFiles Creating 1 chunks for maxArgLength of 65536 +0ms
  lint-staged:generateTasks Generating linter tasks +0ms
  lint-staged:generateTasks Generated task:
  lint-staged:generateTasks {
  lint-staged:generateTasks   pattern: '*',
  lint-staged:generateTasks   commands: [
  lint-staged:generateTasks     'pnpm fix:style',
  lint-staged:generateTasks     'eslint --quiet --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint'
  lint-staged:generateTasks   ],
  lint-staged:generateTasks   fileList: [
  lint-staged:generateTasks     '/home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old.$route.tsx'
  lint-staged:generateTasks   ]
  lint-staged:generateTasks } +1ms
  lint-staged:makeCmdTasks Creating listr tasks for commands [ 'pnpm fix:style', 'eslint --quiet --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint' ] +0ms
  lint-staged:resolveTaskFn cmd: pnpm +0ms
  lint-staged:resolveTaskFn args: [ 'fix:style' ] +0ms
  lint-staged:resolveTaskFn execaOptions: {
  cwd: '/home/flc/my/smc/nexus2/third-nexus-client',
  preferLocal: true,
  reject: false,
  shell: false,
  stdin: 'ignore'
} +0ms
  lint-staged:resolveTaskFn cmd: eslint +0ms
  lint-staged:resolveTaskFn args: [
  '--quiet',
  '--ignore-path',
  '.gitignore',
  '--cache',
  '--cache-location',
  './node_modules/.cache/eslint'
] +0ms
  lint-staged:resolveTaskFn execaOptions: {
  cwd: '/home/flc/my/smc/nexus2/third-nexus-client',
  preferLocal: true,
  reject: false,
  shell: false,
  stdin: 'ignore'
} +0ms
  lint-staged:chunkFiles Resolved an argument string length of 74 characters from 1 files +3ms
  lint-staged:chunkFiles Creating 1 chunks for maxArgLength of 65536 +0ms
[STARTED] Preparing lint-staged...
  lint-staged:GitWorkflow Backing up original state... +0ms
  lint-staged:GitWorkflow Getting partially staged files... +0ms
  lint-staged:execGit Running git command [ 'status', '-z' ] +12ms
  lint-staged:GitWorkflow Found partially staged files: [] +4ms
  lint-staged:GitWorkflow Backing up merge state... +0ms
  lint-staged:file Reading file `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_HEAD` +0ms
  lint-staged:file Reading file `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_MODE` +0ms
  lint-staged:file Reading file `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_MSG` +1ms
  lint-staged:file File `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_HEAD` doesn't exist, ignoring... +0ms
  lint-staged:file File `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_MODE` doesn't exist, ignoring... +0ms
  lint-staged:file File `/home/flc/my/smc/nexus2/third-nexus-client/.git/MERGE_MSG` doesn't exist, ignoring... +0ms
  lint-staged:GitWorkflow Done backing up merge state! +1ms
  lint-staged:GitWorkflow Getting deleted files... +0ms
  lint-staged:execGit Running git command [ 'ls-files', '--deleted' ] +5ms
  lint-staged:GitWorkflow Found deleted files: [] +4ms
  lint-staged:execGit Running git command [ 'stash', 'create' ] +4ms
  lint-staged:execGit Running git command [
  'stash',
  'store',
  '--quiet',
  '--message',
  'lint-staged automatic backup',
  'dc950b03d74ae67873a376206296dbeee478c47d'
] +9ms
  lint-staged:GitWorkflow Done backing up original state! +12ms
[COMPLETED] Preparing lint-staged...
[STARTED] Running tasks for staged files...
[STARTED] package.json — 1 file
[STARTED] * — 1 file
[STARTED] pnpm fix:style
[FAILED] pnpm fix:style [FAILED]
[FAILED] pnpm fix:style [FAILED]
[COMPLETED] Running tasks for staged files...
[STARTED] Applying modifications from tasks...
[SKIPPED] Skipped because of errors from tasks.
[STARTED] Reverting to original state because of errors...
  lint-staged:GitWorkflow Restoring original state... +2s
  lint-staged:execGit Running git command [ 'reset', '--hard', 'HEAD' ] +2s
  lint-staged:execGit Running git command [ 'stash', 'list' ] +4ms
  lint-staged:execGit Running git command [ 'stash', 'apply', '--quiet', '--index', '0' ] +5ms
  lint-staged:GitWorkflow Restoring merge state... +22ms
  lint-staged:GitWorkflow Done restoring merge state! +0ms
  lint-staged:file Removing file `/home/flc/my/smc/nexus2/third-nexus-client/.git/lint-staged_unstaged.patch` +2s
  lint-staged:file File `/home/flc/my/smc/nexus2/third-nexus-client/.git/lint-staged_unstaged.patch` doesn't exist, ignoring... +1ms
  lint-staged:GitWorkflow Done restoring original state! +1ms
[COMPLETED] Reverting to original state because of errors...
[STARTED] Cleaning up temporary files...
  lint-staged:GitWorkflow Dropping backup stash... +0ms
  lint-staged:execGit Running git command [ 'stash', 'list' ] +14ms
  lint-staged:execGit Running git command [ 'stash', 'drop', '--quiet', '0' ] +5ms
  lint-staged:GitWorkflow Done dropping backup stash! +9ms
[COMPLETED] Cleaning up temporary files...

✖ pnpm fix:style:
[error] No files matching the pattern were found: "/home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old..tsx".

> third-nexus-client@ fix:style /home/flc/my/smc/nexus2/third-nexus-client
> prettier --experimental-ternaries --write . "/home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old.$route.tsx"

.eslintrc.cjs 47ms (unchanged)
[... snipped remaining unchanged files list ]

Environment

  • OS: Linux
$ uname -a
Linux bytor 6.7.0-0-MANJARO #1 SMP PREEMPT_DYNAMIC Mon Jan  8 02:04:09 UTC 2024 x86_64 GNU/Linux
  • Node.js:
$ node --version
v20.11.0
  • lint-staged: 15.2.2
  • prettier: 3.2.5
@iiroj
Copy link
Member

iiroj commented Feb 22, 2024

This issue is probably related to an old-running problem of lint-staged not escaping the filenames correctly.

Looking at your logs it seems something eats the $route part on the way, but it could be internal to execa as well, since it's not intentional by lint-staged.

@iiroj
Copy link
Member

iiroj commented Feb 23, 2024

Testing for myself, at least ESLint has no problems with a file like test.$param.js through lint-staged.

Is this an issue with pnpm?

@iiroj
Copy link
Member

iiroj commented Feb 23, 2024

Based on your logs, does thss command work normally for you without lint-staged in the mix, but just running it directly:

pnpm fix:style /home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old.$route.tsx

Also to nitpick your configuration, it says your command is this:

prettier --experimental-ternaries --write .

Since it includes the ., prettier will always run for all files instead of just the staged file. The purpose of lint-staged is to pass the staged file as an argument to your script, so in this case the full script would be:

prettier --experimental-ternaries --write . /home/flc/my/smc/nexus2/third-nexus-client/app/routes/_auth.old.$route.tsx

@zemd
Copy link

zemd commented Mar 4, 2024

having the same issue but with ( character. as a quick fix would be great if lint-staged could wrap each file name with quotes by default or using some kind configuration option like --wrap-with-quotes but meanwhile the only fix would be using .js with escaping manually:

// ...
 "*": (filenames) => {
    return [`prettier --ignore-unknown --write ${filenames.map((file) => `'${file}'`).join(" ")}`];
  },
// ...

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

No branches or pull requests

3 participants