Path component validation
Grit centralizes Git’s path-component rules in grit_lib::path_validate. Use it before writing tree entries, populating the index, or checking out files so NTFS/HFS spellings and .git aliases cannot slip through.
Protection options
ProtectOptions mirrors core.protectNTFS (default true) and core.protectHFS (default true on macOS, false elsewhere). Load them from a merged ConfigSet:
use grit_lib::config::ConfigSet;
use grit_lib::path_validate::ProtectOptions;
let opts = ProtectOptions::from_config(&config);
Object fsck always enables both flags via ProtectOptions::fsck.
Validating components and paths
validate_component checks a single tree/index segment (no / inside). Pass the Git mode and a PathValidationKind. Worktree population and checkout use Worktree. On Windows with core.protectNTFS (default), each segment is checked with Git’s is_valid_win32_path rules: forbidden characters (:*?"<>| and controls), trailing spaces or periods (except . and ..), DOS device names (CON, AUX, COM1, …), plus NTFS drive prefixes and backslash-.git spellings. Symlink names reject .gitmodules on worktree; object fsck uses Fsck (all four symlink dot-files):
use grit_lib::path_validate::{validate_component, EntryMode, PathValidationKind, ProtectOptions};
let opts = ProtectOptions::fsck();
validate_component(b"src", EntryMode::new(0o100644), opts, PathValidationKind::Worktree)?;
Fsck checks all symlink dot-files (.gitmodules, .gitattributes, .gitignore, .mailmap):
use grit_lib::path_validate::{validate_component, EntryMode, PathValidationKind, ProtectOptions};
let opts = ProtectOptions::fsck();
validate_component(
b".gitignore",
EntryMode::new(0o120000),
opts,
PathValidationKind::Fsck,
)?;
.git aliases
With core.protectNTFS on, every platform rejects the NTFS spellings of .git for both kinds, because a repository checked out on Linux may later be used from Windows. These are .git and its 8.3 short name git~1 in any case, each optionally followed by spaces and periods (which NTFS strips) or by a : stream suffix. Examples are .git., GIT~1., git~1 and .git::$INDEX_ALLOCATION. A \-separated segment that spells .git, such as .git\config, is rejected too. System git refuses the same names on Linux, so a hostile tree cannot plant a second .git directory through either implementation.
validate_path splits on / and validates each segment. audit_tree_entry_name returns a bitmask-style summary for fsck-style reporting when several rules fire on one name.
Errors
PathComponentError is a typed, non-exhaustive enum (empty, ., .., slash/NUL, ASCII and platform .git aliases, NTFS backslash/drive/stream spellings, NTFS illegal characters, trailing space/period, reserved DOS device names, and symlinked dot-files). Checkout and index population return Error::InvalidPathComponent with the full path and reason. User-facing add/mv path arguments use the same typed error; legacy Error::InvalidPath remains for empty or escaping paths.
Related
- Tree object fsck uses the same rules via
grit-libmaintenance APIs. - Index population, checkout, restore, and
grit addstaging run these validators internally withProtectOptions::from_config. Code that writes its own tree or index entries callsvalidate_pathorvalidate_componentdirectly.