Skip to main content

normalize_path

Function normalize_path 

Source
pub fn normalize_path(path: impl AsRef<Path>) -> String
Expand description

Normalize a path for source-tree identity and matching.

All backslashes are converted to forward slashes, Unicode is normalized to NFC (composed form), ./.. segments are folded, and the Windows verbatim prefix (\\?\) is stripped. This is a lexical normalization only — it does not touch the filesystem.

§Unicode NFC normalization (#1823)

macOS (HFS+/APFS) and git may represent the same path in different Unicode normalization forms (NFC composed vs NFD decomposed). Without NFC normalization, files.sort(); files.dedup() in the inventory treats NFC and NFD forms of the same path as distinct, and finding→entry matching (normalize_path(finding_path) == normalize_path(entry_path)) produces false positives/false negatives split across platforms — a real unwrap() finding goes unreceipted on macOS but matched on Linux. Normalizing to NFC inside this function ensures all downstream matching, fingerprinting, and identity keying sees one canonical Unicode form.

§Windows absolute paths (#1821)

normalize_path handles three Windows absolute shapes:

  • Verbatim prefix (\\?\C:\... or \\?\UNC\server\share\...): stripped so the path degrades to its non-verbatim form (C:/... or //server/share/...). This is the case that silently produced wrong identity keys because the \\?\ prefix survived as path segments.
  • Drive letters (C:\...): preserved as C:/.... The drive letter is a meaningful absolute-path identity component, not a repo-relative segment, and several callers (e.g. migrate evidence diagnostics) pass absolute roots through this function. Stripping it would corrupt those identities.
  • UNC roots (\\server\share\...): preserved as //server/share/.... Two leading slashes fold to a single Unix-style absolute root (/) during the segment walk, so //server/share/foo/server/share/foo.

The scanner resolves finding paths against the source-tree root before calling this function, so repo-relative paths are the normal input.