Skip to content

chore: pin line endings to LF and renormalize#49

Merged
tablackburn merged 3 commits into
mainfrom
chore/normalize-line-endings-to-lf
May 10, 2026
Merged

chore: pin line endings to LF and renormalize#49
tablackburn merged 3 commits into
mainfrom
chore/normalize-line-endings-to-lf

Conversation

@tablackburn
Copy link
Copy Markdown
Owner

Summary

The previous `.gitattributes` rule (`* -crlf`) only disabled CRLF conversion at checkout — files kept whatever endings they had on commit, leaving the index mixed. With Windows clones using `core.autocrlf=true` and tooling that writes LF (most editors and AI agents), this surfaces as `LF will be replaced by CRLF the next time Git touches it` warnings on every commit.

This PR pins everything to LF in both the repo and the working tree, then renormalizes the existing mixed content.

Commit structure

# Commit Effect
1 `chore: pin line endings to LF via .gitattributes` Replaces `* -crlf` with `* text=auto eol=lf`
2 `chore: renormalize line endings to LF` `git add --renormalize .` — 210 files / ~48k lines, content byte-identical
3 `chore: add .git-blame-ignore-revs for the renormalize commit` Skips commit 2 in `git blame`

⚠️ For contributors with open branches

This is the largest of the renormalize PRs in the `tablackburn/*` sweep — 210 files. Every CRLF text file in the repo gets converted. Branches based on pre-renormalize `main` will hit merge conflicts on every CRLF-in-HEAD file.

There are currently five local-only feature branches (`bugfix/ci-lint-cache-conditional-install`, `ci/integration-test-timeouts`, `feature/transient-dns-no-data-retry`, `feature/update-server-token`, `fix/disable-scriptanalyzer-macos`) that will need rebasing onto post-merge `main`:

```
git fetch origin
git checkout your-branch
git rebase origin/main
```

If conflicts only differ in line endings, `git checkout --theirs ` (then re-stage) is the fastest resolution. Git's renormalize-aware merge handles most of it automatically when both sides have the new attributes.

Local-clone setup

Once merged, configure git to honor the blame-ignore file:

```
git config blame.ignoreRevsFile .git-blame-ignore-revs
```

GitHub's web blame view uses it automatically.

Context

Part of a sweep across `tablackburn/*` non-fork repos.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 6, 2026 23:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Important

Review skipped

Too many files!

This PR contains 212 files, which is 62 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 57e82832-a6bf-4c6d-87a3-5430d03f25b6

📥 Commits

Reviewing files that changed from the base of the PR and between cc3d14e and 601876d.

📒 Files selected for processing (212)
  • .git-blame-ignore-revs
  • .gitattributes
  • .github/workflows/CI.yaml
  • .github/workflows/PublishModuleToPowerShellGallery.yaml
  • .gitignore
  • .vscode/extensions.json
  • .vscode/settings.json
  • .vscode/tasks.json
  • AGENTS.md
  • CHANGELOG.md
  • Initialize-SecretVault.ps1
  • PSScriptAnalyzerSettings.psd1
  • PlexAutomationToolkit/PlexAutomationToolkit.psm1
  • PlexAutomationToolkit/Private/ConvertFrom-PatCompleterInput.ps1
  • PlexAutomationToolkit/Private/ConvertTo-PsCustomObjectFromHashtable.ps1
  • PlexAutomationToolkit/Private/Get-PatAuthenticationHeader.ps1
  • PlexAutomationToolkit/Private/Get-PatClientIdentifier.ps1
  • PlexAutomationToolkit/Private/Get-PatCompleterResult.ps1
  • PlexAutomationToolkit/Private/Get-PatConfigurationPath.ps1
  • PlexAutomationToolkit/Private/Get-PatMediaPath.ps1
  • PlexAutomationToolkit/Private/Get-PatSafeFilename.ps1
  • PlexAutomationToolkit/Private/Get-PatSecretManagementAvailable.ps1
  • PlexAutomationToolkit/Private/Get-PatServerConfiguration.ps1
  • PlexAutomationToolkit/Private/Get-PatServerConnection.ps1
  • PlexAutomationToolkit/Private/Get-PatServerIdentity.ps1
  • PlexAutomationToolkit/Private/Get-PatServerToken.ps1
  • PlexAutomationToolkit/Private/Invoke-PatApi.ps1
  • PlexAutomationToolkit/Private/Invoke-PatFileDownload.ps1
  • PlexAutomationToolkit/Private/Invoke-PatPinAuthentication.ps1
  • PlexAutomationToolkit/Private/Join-PatUri.ps1
  • PlexAutomationToolkit/Private/New-PatCompletionResult.ps1
  • PlexAutomationToolkit/Private/New-PatPin.ps1
  • PlexAutomationToolkit/Private/Register-PatArgumentCompleter.ps1
  • PlexAutomationToolkit/Private/Remove-PatServerToken.ps1
  • PlexAutomationToolkit/Private/Resolve-PatServerContext.ps1
  • PlexAutomationToolkit/Private/Select-PatServerUri.ps1
  • PlexAutomationToolkit/Private/Set-PatServerConfiguration.ps1
  • PlexAutomationToolkit/Private/Set-PatServerToken.ps1
  • PlexAutomationToolkit/Private/Test-PatServerReachable.ps1
  • PlexAutomationToolkit/Private/Test-PatServerUri.ps1
  • PlexAutomationToolkit/Private/Wait-PatPinAuthorization.ps1
  • PlexAutomationToolkit/Public/Add-PatCollectionItem.ps1
  • PlexAutomationToolkit/Public/Add-PatPlaylistItem.ps1
  • PlexAutomationToolkit/Public/Add-PatServer.ps1
  • PlexAutomationToolkit/Public/Clear-PatDefaultServer.ps1
  • PlexAutomationToolkit/Public/Compare-PatLibraryContent.ps1
  • PlexAutomationToolkit/Public/Compare-PatWatchStatus.ps1
  • PlexAutomationToolkit/Public/Connect-PatAccount.ps1
  • PlexAutomationToolkit/Public/Get-PatActivity.ps1
  • PlexAutomationToolkit/Public/Get-PatCollection.ps1
  • PlexAutomationToolkit/Public/Get-PatLibrary.ps1
  • PlexAutomationToolkit/Public/Get-PatLibraryChildItem.ps1
  • PlexAutomationToolkit/Public/Get-PatLibraryItem.ps1
  • PlexAutomationToolkit/Public/Get-PatLibraryPath.ps1
  • PlexAutomationToolkit/Public/Get-PatMediaInfo.ps1
  • PlexAutomationToolkit/Public/Get-PatPlaylist.ps1
  • PlexAutomationToolkit/Public/Get-PatServer.ps1
  • PlexAutomationToolkit/Public/Get-PatSession.ps1
  • PlexAutomationToolkit/Public/Get-PatStoredServer.ps1
  • PlexAutomationToolkit/Public/Get-PatSyncPlan.ps1
  • PlexAutomationToolkit/Public/Get-PatToken.ps1
  • PlexAutomationToolkit/Public/Import-PatServerToken.ps1
  • PlexAutomationToolkit/Public/New-PatCollection.ps1
  • PlexAutomationToolkit/Public/New-PatPlaylist.ps1
  • PlexAutomationToolkit/Public/Remove-PatCollection.ps1
  • PlexAutomationToolkit/Public/Remove-PatCollectionItem.ps1
  • PlexAutomationToolkit/Public/Remove-PatPlaylist.ps1
  • PlexAutomationToolkit/Public/Remove-PatPlaylistItem.ps1
  • PlexAutomationToolkit/Public/Remove-PatServer.ps1
  • PlexAutomationToolkit/Public/Search-PatMedia.ps1
  • PlexAutomationToolkit/Public/Set-PatDefaultServer.ps1
  • PlexAutomationToolkit/Public/Stop-PatSession.ps1
  • PlexAutomationToolkit/Public/Sync-PatMedia.ps1
  • PlexAutomationToolkit/Public/Sync-PatWatchStatus.ps1
  • PlexAutomationToolkit/Public/Test-PatLibraryPath.ps1
  • PlexAutomationToolkit/Public/Update-PatLibrary.ps1
  • PlexAutomationToolkit/Public/Update-PatServerToken.ps1
  • PlexAutomationToolkit/Public/Wait-PatLibraryScan.ps1
  • PlexAutomationToolkit/en-US/about_PlexAutomationToolkit.help.txt
  • build.depend.psd1
  • build.ps1
  • build.psake.ps1
  • codecov.yml
  • custom.psake.ps1
  • docs/en-US/Add-PatCollectionItem.md
  • docs/en-US/Add-PatPlaylistItem.md
  • docs/en-US/Add-PatServer.md
  • docs/en-US/Clear-PatDefaultServer.md
  • docs/en-US/Compare-PatLibraryContent.md
  • docs/en-US/Compare-PatWatchStatus.md
  • docs/en-US/Connect-PatAccount.md
  • docs/en-US/Get-PatActivity.md
  • docs/en-US/Get-PatCollection.md
  • docs/en-US/Get-PatLibrary.md
  • docs/en-US/Get-PatLibraryChildItem.md
  • docs/en-US/Get-PatLibraryItem.md
  • docs/en-US/Get-PatLibraryPath.md
  • docs/en-US/Get-PatMediaInfo.md
  • docs/en-US/Get-PatPlaylist.md
  • docs/en-US/Get-PatServer.md
  • docs/en-US/Get-PatSession.md
  • docs/en-US/Get-PatStoredServer.md
  • docs/en-US/Get-PatSyncPlan.md
  • docs/en-US/Get-PatToken.md
  • docs/en-US/Import-PatServerToken.md
  • docs/en-US/New-PatCollection.md
  • docs/en-US/New-PatPlaylist.md
  • docs/en-US/Remove-PatCollection.md
  • docs/en-US/Remove-PatCollectionItem.md
  • docs/en-US/Remove-PatPlaylist.md
  • docs/en-US/Remove-PatPlaylistItem.md
  • docs/en-US/Remove-PatServer.md
  • docs/en-US/Search-PatMedia.md
  • docs/en-US/Set-PatDefaultServer.md
  • docs/en-US/Stop-PatSession.md
  • docs/en-US/Sync-PatMedia.md
  • docs/en-US/Sync-PatWatchStatus.md
  • docs/en-US/Test-PatLibraryPath.md
  • docs/en-US/Test-PatServer.md
  • docs/en-US/Update-PatLibrary.md
  • docs/en-US/Update-PatServerToken.md
  • docs/en-US/Wait-PatLibraryScan.md
  • instructions/agent-workflow.instructions.md
  • instructions/contributing.instructions.md
  • instructions/git-workflow.instructions.md
  • instructions/github-cli.instructions.md
  • instructions/markdown.instructions.md
  • instructions/powershell.instructions.md
  • instructions/readme.instructions.md
  • instructions/releases.instructions.md
  • instructions/repository-specific.instructions.md
  • instructions/shorthand.instructions.md
  • instructions/testing.instructions.md
  • instructions/update.instructions.md
  • local.secrets.template.json
  • requirements.psd1
  • tests/Integration/IntegrationTestHelpers.psm1
  • tests/Integration/Public/Collection.Integration.tests.ps1
  • tests/Integration/Public/LibraryOperations.Integration.tests.ps1
  • tests/Integration/Public/LibraryQueries.Integration.tests.ps1
  • tests/Integration/Public/MediaSync.Integration.tests.ps1
  • tests/Integration/Public/Playlist.Integration.tests.ps1
  • tests/Integration/Public/ServerManagement.Integration.tests.ps1
  • tests/Integration/Public/Sessions.Integration.tests.ps1
  • tests/Integration/README.md
  • tests/ScriptAnalyzerSettings.psd1
  • tests/Unit/Private/ConvertFrom-PatCompleterInput.tests.ps1
  • tests/Unit/Private/ConvertTo-PsCustomObjectFromHashtable.tests.ps1
  • tests/Unit/Private/Get-PatAuthenticationHeader.tests.ps1
  • tests/Unit/Private/Get-PatClientIdentifier.tests.ps1
  • tests/Unit/Private/Get-PatCompleterResult.tests.ps1
  • tests/Unit/Private/Get-PatConfigurationPath.tests.ps1
  • tests/Unit/Private/Get-PatMediaPath.tests.ps1
  • tests/Unit/Private/Get-PatSafeFilename.tests.ps1
  • tests/Unit/Private/Get-PatSecretManagementAvailable.tests.ps1
  • tests/Unit/Private/Get-PatServerConfiguration.tests.ps1
  • tests/Unit/Private/Get-PatServerConnection.tests.ps1
  • tests/Unit/Private/Get-PatServerIdentity.tests.ps1
  • tests/Unit/Private/Get-PatServerToken.tests.ps1
  • tests/Unit/Private/Invoke-PatApi.tests.ps1
  • tests/Unit/Private/Invoke-PatFileDownload.tests.ps1
  • tests/Unit/Private/Invoke-PatPinAuthentication.tests.ps1
  • tests/Unit/Private/Join-PatUri.tests.ps1
  • tests/Unit/Private/New-PatCompletionResult.tests.ps1
  • tests/Unit/Private/New-PatPin.tests.ps1
  • tests/Unit/Private/Register-PatArgumentCompleter.tests.ps1
  • tests/Unit/Private/Remove-PatServerToken.tests.ps1
  • tests/Unit/Private/Resolve-PatServerContext.tests.ps1
  • tests/Unit/Private/Select-PatServerUri.tests.ps1
  • tests/Unit/Private/Set-PatServerConfiguration.tests.ps1
  • tests/Unit/Private/Set-PatServerToken.tests.ps1
  • tests/Unit/Private/Test-PatServerReachable.tests.ps1
  • tests/Unit/Private/Test-PatServerUri.tests.ps1
  • tests/Unit/Private/Wait-PatPinAuthorization.tests.ps1
  • tests/Unit/Public/Add-PatCollectionItem.tests.ps1
  • tests/Unit/Public/Add-PatPlaylistItem.tests.ps1
  • tests/Unit/Public/Add-PatServer.tests.ps1
  • tests/Unit/Public/Clear-PatDefaultServer.tests.ps1
  • tests/Unit/Public/Compare-PatLibraryContent.tests.ps1
  • tests/Unit/Public/Compare-PatWatchStatus.tests.ps1
  • tests/Unit/Public/Connect-PatAccount.tests.ps1
  • tests/Unit/Public/Get-PatActivity.tests.ps1
  • tests/Unit/Public/Get-PatCollection.tests.ps1
  • tests/Unit/Public/Get-PatLibrary.tests.ps1
  • tests/Unit/Public/Get-PatLibraryChildItem.tests.ps1
  • tests/Unit/Public/Get-PatLibraryItem.tests.ps1
  • tests/Unit/Public/Get-PatLibraryPath.tests.ps1
  • tests/Unit/Public/Get-PatMediaInfo.tests.ps1
  • tests/Unit/Public/Get-PatPlaylist.tests.ps1
  • tests/Unit/Public/Get-PatServer.tests.ps1
  • tests/Unit/Public/Get-PatSession.tests.ps1
  • tests/Unit/Public/Get-PatStoredServer.tests.ps1
  • tests/Unit/Public/Get-PatSyncPlan.tests.ps1
  • tests/Unit/Public/Get-PatToken.tests.ps1
  • tests/Unit/Public/Import-PatServerToken.tests.ps1
  • tests/Unit/Public/New-PatCollection.tests.ps1
  • tests/Unit/Public/New-PatPlaylist.tests.ps1
  • tests/Unit/Public/Remove-PatCollection.tests.ps1
  • tests/Unit/Public/Remove-PatCollectionItem.tests.ps1
  • tests/Unit/Public/Remove-PatPlaylist.tests.ps1
  • tests/Unit/Public/Remove-PatPlaylistItem.tests.ps1
  • tests/Unit/Public/Remove-PatServer.tests.ps1
  • tests/Unit/Public/Search-PatMedia.tests.ps1
  • tests/Unit/Public/Set-PatDefaultServer.tests.ps1
  • tests/Unit/Public/Stop-PatSession.tests.ps1
  • tests/Unit/Public/Sync-PatMedia.tests.ps1
  • tests/Unit/Public/Sync-PatWatchStatus.tests.ps1
  • tests/Unit/Public/Test-PatLibraryPath.tests.ps1
  • tests/Unit/Public/Update-PatLibrary.tests.ps1
  • tests/Unit/Public/Update-PatServerToken.tests.ps1
  • tests/Unit/Public/Wait-PatLibraryScan.tests.ps1
  • tests/local.settings.example.ps1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/normalize-line-endings-to-lf

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

tablackburn and others added 3 commits May 10, 2026 01:33
The previous `* -crlf` rule only disabled CRLF conversion at checkout
(files kept whatever endings they had on commit) but didn't coerce a
single convention, leaving the index mixed: some files LF, others
CRLF. With Windows clones using core.autocrlf=true and tooling that
writes LF (most editors and AI agents), this surfaces as "LF will be
replaced by CRLF the next time Git touches it" warnings on every
commit.

Pin everything to LF in both the repo and the working tree. PowerShell
on Windows handles LF fine.

This commit only changes .gitattributes; the bulk renormalize lands in
the next commit (so it can be added to .git-blame-ignore-revs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mechanical follow-up to the .gitattributes pin in the previous commit.
git add --renormalize . converts all CRLF text files in the index to
LF; content is byte-identical, only line endings change.

Touches 210 files. Added to .git-blame-ignore-revs in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
git blame and the GitHub web UI both honor .git-blame-ignore-revs at
the repo root. The previous commit was pure line-ending churn (no
content change), so blaming through it is noise — this entry redirects
blame to the actual content author.

Local clones need a one-time:
    git config blame.ignoreRevsFile .git-blame-ignore-revs
GitHub picks it up automatically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tablackburn tablackburn force-pushed the chore/normalize-line-endings-to-lf branch from 13d213b to 601876d Compare May 10, 2026 05:34
@tablackburn tablackburn merged commit 1bc364b into main May 10, 2026
14 of 15 checks passed
@tablackburn tablackburn deleted the chore/normalize-line-endings-to-lf branch May 10, 2026 06:05
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