Skip to content

fix: normalize generated hook line endings#175

Open
alirezanet wants to merge 1 commit into
masterfrom
fix/normalize-hook-line-endings
Open

fix: normalize generated hook line endings#175
alirezanet wants to merge 1 commit into
masterfrom
fix/normalize-hook-line-endings

Conversation

@alirezanet

Copy link
Copy Markdown
Owner

Summary

  • normalize generated shell hook content to LF line endings
  • apply normalization when writing .husky/_/husky.sh and hook files created by set/add
  • add regression tests for CRLF and standalone CR normalization

Test Plan

  • dotnet test tests/HuskyTest/HuskyTest.csproj -v minimal
  • sg docker -c 'dotnet test Husky.sln -v minimal'

Context

This prevents CRLF shebangs in generated hook scripts from breaking execution on Linux/WSL with errors like: fatal: cannot exec '.husky/pre-commit': No such file or directory

@what-the-diff

what-the-diff Bot commented Apr 30, 2026

Copy link
Copy Markdown

PR Summary

  • Standardized Line Endings in CreateResources Methods
    Updated the CreateResources and CreateResourcesAsync methods to normalize line endings. This change helps ensure consistency in line endings for the content read from a specific script, when writing the file either synchronously or asynchronously.

  • Line Endings Normalization in CreateHook Method
    The CreateHook method now normalizes line endings for the content read from the hook template and its combined content before writing. This change ensures that the hook content script is always consistent, improving compatibility across different platforms.

  • New Line Endings Normalization Helper Method
    A new function, NormalizeShellScriptLineEndings, has been added to replace Windows-style line endings with Unix-style ones. It simplifies line ending standardization throughout the codebase, enhancing cross-platform compatibility.

  • Test Suite for Line Endings Normalization
    The new LineEndingTests test suite verifies the behavior of the NormalizeShellScriptLineEndings method. It provides assurance that the new function handles diverse line ending styles as expected, aiding in stable and reliable software operation.

@alirezanet alirezanet force-pushed the fix/normalize-hook-line-endings branch 2 times, most recently from 3c7f634 to f615626 Compare April 30, 2026 10:33
@alirezanet alirezanet requested a review from Copilot April 30, 2026 10:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses cross-platform shell hook execution issues by ensuring Husky-generated hook scripts use LF line endings, preventing CRLF shebangs from breaking on Linux/WSL.

Changes:

  • Added ShellScriptLineEndings.Normalize utility to convert CRLF/CR to LF.
  • Applied normalization when generating .husky/_/husky.sh and hooks created via set, and added .husky/.gitattributes to enforce LF checkouts.
  • Added regression tests covering CRLF and standalone CR normalization, plus install behavior for .gitattributes.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Husky/Utils/ShellScriptLineEndings.cs Introduces LF normalization helper for shell script content.
src/Husky/Cli/SetCommand.cs Normalizes generated hook file content before writing.
src/Husky/Cli/InstallCommand.cs Normalizes husky.sh template and creates .husky/.gitattributes to enforce LF.
tests/HuskyTest/Utils/LineEndingTests.cs Adds unit tests for CRLF and CR-to-LF normalization.
tests/HuskyTest/Cli/InstallCommandTests.cs Adds coverage for .gitattributes creation/non-overwrite during install.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +46
var content = ShellScriptLineEndings.Normalize(await sr.ReadToEndAsync());
var hookContent = ShellScriptLineEndings.Normalize($"{content}\n{Command}\n");
await _fileSystem.File.WriteAllTextAsync(hookPath, hookContent);

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

set now normalizes the initially generated hook content, but add can still append Command containing \r/CRLF (see AddCommand.AppendAllTextAsync(...)), reintroducing CR characters into an existing hook script and breaking execution on Linux. Normalize the appended content (or read/normalize/rewrite the whole file) in the add flow as well so hooks remain LF-only after subsequent add operations.

Copilot uses AI. Check for mistakes.
Comment thread src/Husky/Cli/InstallCommand.cs Outdated
Comment on lines +131 to +135
// Keep Husky hook scripts LF-only even when users have core.autocrlf enabled.
var gitAttributesPath = Path.Combine(path, GIT_ATTRIBUTES_FILE_NAME);
if (!_fileSystem.File.Exists(gitAttributesPath))
_fileSystem.File.WriteAllText(gitAttributesPath, GIT_ATTRIBUTES_CONTENT);

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

Line-ending normalization + .gitattributes creation is duplicated between CreateResources and CreateResourcesAsync, and CreateResources appears unused in this file (only CreateResourcesAsync is called). This increases the risk of these two paths diverging over time; consider removing the dead sync method or extracting shared logic into a single helper used by the actual execution path.

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants