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 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. A repo transport path accepts the suffix whatever its case, 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 the server it is dialing.

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

Entire-Checkpoint: 01M3SM7D59ZJGE3CBT8BABWQ7Q

Checkpoints

Standardize Repository Name Validation Logic

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