shepherd-cli 6.6.1

The canonical shepherd command-line interface over the per-project registry, run artifacts, and sprint pipeline.
//! One spelling of an absolute path for the carrier grammar.
//!
//! The grammar accepts forward-slash separated absolute paths. Windows hands
//! back other spellings -- most often the verbatim `\\?\C:\...` form that
//! `fs::canonicalize` produces -- so exactly one function owns the respelling
//! and every producer of a carrier path calls it.

use std::path::{Component, Path, Prefix};

/// Render `path` in the carrier grammar's portable spelling.
///
/// A drive prefix (`C:\...`, or the verbatim `\\?\C:\...` that
/// `fs::canonicalize` returns) is rendered as `C:/...`. Swapping separators
/// alone would leave `//?/C:/...`, whose two leading empty components the
/// grammar rejects as an unbounded path, so a correctly canonicalized package
/// was refused.
///
/// Every other prefix kind -- UNC, verbatim UNC, device namespace -- keeps its
/// original spelling and is still refused downstream. The grammar does not
/// model network shares, and silently reshaping one would invent authority the
/// caller never proved. A drive-relative path (`C:tmp`, no root) is left alone
/// for the same reason: it is not absolute, and rooting it here would answer a
/// question the caller never asked.
///
/// The prefix is classified through [`Prefix`] rather than by matching a `//?/`
/// string, so a path is never re-parsed out of its own rendering.
pub fn portable_absolute_path(path: &Path) -> String {
    let mut components = path.components();
    let Some(Component::Prefix(prefix)) = components.clone().next() else {
        // No prefix component: the platform already separates with `/`, and a
        // backslash here is an ordinary filename character, not a separator.
        return path.display().to_string();
    };
    let disk = match prefix.kind() {
        Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => letter,
        _ => return verbatim_spelling(path),
    };
    components.next();
    if components.clone().next() != Some(Component::RootDir) {
        return verbatim_spelling(path);
    }
    components.next();

    let mut rendered = String::with_capacity(path.as_os_str().len());
    rendered.push(char::from(disk));
    rendered.push(':');
    rendered.push('/');
    for (index, component) in components.enumerate() {
        if index > 0 {
            rendered.push('/');
        }
        rendered.push_str(&component.as_os_str().to_string_lossy());
    }
    rendered
}

/// Preserve a prefix the grammar does not model, in a spelling the downstream
/// check can still reject on sight.
fn verbatim_spelling(path: &Path) -> String {
    path.to_string_lossy().replace('\\', "/")
}

#[cfg(test)]
mod tests {
    use super::portable_absolute_path;
    use std::path::Path;

    #[cfg(unix)]
    #[test]
    fn unix_absolute_path_is_already_portable() {
        assert_eq!(portable_absolute_path(Path::new("/a/b/c.md")), "/a/b/c.md");
    }

    #[cfg(unix)]
    #[test]
    fn unix_backslash_is_a_filename_character_not_a_separator() {
        assert_eq!(portable_absolute_path(Path::new(r"/a/b\c")), r"/a/b\c");
    }

    #[cfg(windows)]
    #[test]
    fn verbatim_disk_prefix_is_unwrapped() {
        assert_eq!(
            portable_absolute_path(Path::new(r"\\?\C:\a\b\c.md")),
            "C:/a/b/c.md"
        );
    }

    #[cfg(windows)]
    #[test]
    fn plain_disk_prefix_keeps_its_drive_and_swaps_separators() {
        assert_eq!(
            portable_absolute_path(Path::new(r"C:\a\b\c.md")),
            "C:/a/b/c.md"
        );
    }

    #[cfg(windows)]
    #[test]
    fn drive_root_alone_renders_as_the_root() {
        assert_eq!(portable_absolute_path(Path::new(r"C:\")), "C:/");
    }

    #[cfg(windows)]
    #[test]
    fn verbatim_unc_keeps_its_prefix_so_the_grammar_still_refuses_it() {
        assert_eq!(
            portable_absolute_path(Path::new(r"\\?\UNC\server\share\a")),
            "//?/UNC/server/share/a"
        );
    }

    #[cfg(windows)]
    #[test]
    fn unc_keeps_its_authority_so_the_grammar_still_refuses_it() {
        assert_eq!(
            portable_absolute_path(Path::new(r"\\server\share\a")),
            "//server/share/a"
        );
    }

    #[cfg(windows)]
    #[test]
    fn drive_relative_path_is_not_rooted_here() {
        assert_eq!(portable_absolute_path(Path::new(r"C:tmp")), "C:tmp");
    }
}