Skip to content

Status()/Diff()/Patch() throw for the whole repo when any path contains <, > or |, or is longer than 256 characters (legal on Linux/macOS) #131

Description

@matt-edmondson

What's wrong

Every path git reports goes through GitParseValues.ToRelativeFilePath. That covers 5 call sites in GitStatusParser, 3 in GitDiffParser and 3 in GitPatchParser, and each converts the path with RelativeFilePath.TryCreate from ktsu.Semantics.Paths.

That validation applies Windows-only rules:

  • Characters: <, > and | are rejected. Checking ASCII 1–127 shows these three are the only characters rejected.
  • Length: any path of 257 or more characters is rejected (256: True, 257: False).

Linux and macOS allow all of these characters, and git handles long paths without trouble (Linux PATH_MAX is 4096). When one path fails validation, the parser throws, and the whole verb fails.

Failure scenarios

A. Create x|y.txt in a repository (a valid filename on Linux/macOS), then call repo.Status():

GitParseException: git reported a path that cannot be represented as a relative file path: 'x|y.txt'.

After committing the file and then modifying it, Diff() and Patch() fail the same way.

B. Stage a file whose repository-relative path is 274 characters long, for example dir/ repeated 30 times followed by 150 ys and .txt. Status() throws the same GitParseException. Deep Java and JavaScript source trees reach this length.

In both cases one such file anywhere in the working tree makes Status() unusable for the entire repository. It does not just drop that one entry.

Suggested fix / acceptance criteria

  • Preferred: carry repository paths in a git-specific semantic type that forbids only what git forbids: NUL, absolute paths, and .. escapes. Reserve the OS-specific RelativeFilePath validation for the point where a caller actually touches the local file system.
  • Alternative: fix ktsu.Semantics.Paths upstream so that it does not apply Windows reserved-character and MAX_PATH rules on POSIX.
  • Tests: add tests showing that Status(), Diff() and Patch() return entries for x|y.txt, a<b>.txt and a path longer than 260 characters on non-Windows platforms.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions