Skip to content

Match branch patterns on UTF-8 bytes, as git branch --list does [patch] - #119

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/115-branch-pattern-bytes
Nov 4, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
fix/115-branch-pattern-bytes

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #115

What changes

The README promises that branch patterns mean what they mean to git branch --list. BranchPattern compared UTF-16 chars, but git's wildmatch compares bytes, so the two picked out different branches outside ASCII. For example, origin/? matched origin/é here but not in git, and origin/caf?? matched origin/café in git but not here.

I took the issue's first option, exact parity:

Tests

  • BranchPatternGitParityTests.EveryPattern_PicksOutTheSameBranchesAsGitBranchList (new) builds a throwaway repo with 25 remote-tracking refs, including é, café, naïve, 😀, x😀 and 日本 alongside the ASCII names from the existing tests. It runs 41 patterns through both BranchPattern and git branch -r --list. The patterns include every ASCII case already in BranchPatternTests and the issue's table. The test requires both sides to pick out the same set for every pattern and lists each disagreement.
  • BranchPatternTests.Matches_OutsideAscii_CountsUtf8BytesLikeGit covers the issue's table as unit cases.

With the old char-level matching swapped back in, the parity test reports 12 disagreeing patterns and 7 of the 9 unit cases fail. With the change, the full GitBranchStateCache.Tests suite passes (295/295, net10.0).

This branch is independent of #117 and #118, and git merge-tree shows it merges cleanly with both.


Generated by Claude Code

BranchPattern compared UTF-16 chars while git's wildmatch compares bytes,
so outside ASCII the two picked out different branches: origin/? matched
origin/é here but not in git, and origin/caf?? matched origin/café in git
but not here.

The pattern and the name are now spelled as their UTF-8 bytes, one
character per byte, before matching. Every character the matcher treats
as syntax is ASCII and every byte of a multi-byte character is above
U+007F, so ASCII behaviour, bracket expressions and POSIX classes are
unchanged.

A new parity test runs 41 patterns through both BranchPattern and
git branch -r --list over the same 25 refs and requires them to agree.

Fixes #115

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT
Loose ref files would let a case-insensitive file system on the macOS and
Windows CI legs fold origin/main and origin/Main into one ref.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT
On Windows git's object files are read-only, so Directory.Delete threw
UnauthorizedAccessException from ClassCleanup. Same handling as
RealRepositoryTests.RemoveFixture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT
@sonarqubecloud

sonarqubecloud Bot commented Nov 3, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 7678910 into main Nov 4, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/115-branch-pattern-bytes branch November 4, 2026 01:01
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.

Branch patterns ? and [...] disagree with git branch --list on non-ASCII names: origin/? matches origin/é here but not in git

2 participants