repo refs: the .git suffix is reserved in every case

Commit

hiddeco6d ago

The CLI spelled one rule five ways -- a HasSuffix in repo create, three TrimSuffix calls across the ref parsers, and a ToLower-wrapped one in the mirror-URL parse -- all case-sensitive, each with its own list of examples. Three of them were wrong, and each one's tests passed.

repo create refused "test.git" with a message naming the spelling to use, and let "test.GIT" through to the server, which rejects it for carrying uppercase: a true statement about a different problem, leaving the suffix rule to be discovered on a second attempt.

parseMirrorCloneURL ran ToLower(TrimSuffix(x)). "CLI.GIT" missed the case-sensitive cut and folded to "cli.git" -- a spelling stored mirrors never carry, so the EqualFold match below it could not find a mirror that plainly exists.

The ref parsers disagreed with the server they dial. coreclaims. TrimRepoPathGitSuffix cuts with EqualFold precisely so a ".GIT" audience does not 404 a repo the data plane resolves, so git clone entire://.../et/acme/widgets.GIT succeeds while entire repo clone /et/acme/widgets.GIT reported no such repo.

One helper now answers the question. Canonical git draws this line by purpose, not by taste: case-sensitive when it is merely guessing a local directory name from a URL (strncmp in git_url_basename), and aggressively case-insensitive -- plus HFS ignorable codepoints and NTFS short names -- when asking whether a path IS the reserved .git (is_hfs_dotgit, is_ntfs_dotgit). Both of the CLI's uses are the latter. gitremote's comment cited strip_suffix_mem as grounds for matching git's case sensitivity; that is the wrong half of git's rule for a function whose answer has to agree with Entire's data plane.

Also send the name that was checked. repo create validated TrimSpace(args[0]) and put the raw args[0] on the wire, which only ever worked because the server trims too.

The fixture tables are shared by every call site's tests, so none can pass behind a narrower list again. They cover the case variants, whitespace at both ends, single-cut semantics, the near-misses git pins in its own tests (gitops, .gitignore), and multi-byte final runes.

Refs COR-1892

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Entire-Checkpoint: 01M3SFMEW0FV7A3FB8EVW29YSF

Checkpoints

Multi-Root Config Path Agent Support

Claude CodeOpus 5.[1m]
View session
Checkpoint 1

Standardize Repository Name Validation Logic

Claude CodeOpus 5.[1m]
View session
Checkpoint 1