fn clean_name()

in tough/src/target_name.rs [108:169]


fn clean_name(name: &str) -> Result<String> {
    // This causes something to panic, so we check for it early.
    ensure!(name != "..", error::UnsafeTargetNameDotDotSnafu);

    // Seems like bad things could happen if the target filename is the empty string.
    ensure!(!name.is_empty(), error::UnsafeTargetNameEmptySnafu { name });

    // If our name starts with absolute, then we need to remember this so we can restore it later.
    let name_path = PathBuf::from(name);
    let absolute = name_path.is_absolute();

    let clean = {
        let proposed = name_path
            .absolutize_from(&PathBuf::from("/"))
            .context(error::TargetNameResolveSnafu { name })?;

        // `absolutize_from` will give us a path that starts with `/`, so we remove it if the
        // original name did not start with `/`
        if absolute {
            // If `name` started with `/`, then we have nothing left to do because absolutize_from
            // returns a rooted path.
            proposed.to_path_buf()
        } else {
            let mut components = proposed.components();
            // If the original name did not start with `/`, we need to remove the leading slash
            // here because absolutize_from will return a rooted path.
            let first_component = components
                .next()
                // If this error occurs then there is a bug or behavior change in absolutize_from.
                .context(error::TargetNameComponentsEmptySnafu { name })?
                .as_os_str();

            // If the first component isn't `/` then there is a bug or behavior change in
            // absolutize_from.
            ensure!(
                first_component == "/",
                error::TargetNameRootMissingSnafu { name }
            );

            components.as_path().to_owned()
        }
    };

    let final_name = clean
        .as_os_str()
        .to_str()
        .context(error::PathUtf8Snafu { path: &clean })?
        .to_string();

    // Check again to make sure we didn't end up with an empty string.
    ensure!(
        !final_name.is_empty(),
        error::UnsafeTargetNameEmptySnafu { name }
    );

    ensure!(
        final_name != "/",
        error::UnsafeTargetNameSlashSnafu { name }
    );

    Ok(final_name)
}