secretspec 0.20.0

A declarative interface for every secret provider.
Documentation
use std::env;
use std::fs;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio};
use tempfile::TempDir;

#[test]
fn git_credential_fill_uses_the_secretspec_helper() {
    let temp = TempDir::new().unwrap();
    let manifest = temp.path().join("secretspec.toml");
    fs::write(
        &manifest,
        r#"
[project]
name = "git-helper"
revision = "1.0"
require_reason = false

[profiles.default]
GITHUB_USERNAME = { description = "GitHub username", default = "vimjoyer", providers = ["null"] }
GITHUB_TOKEN = { description = "GitHub token", default = "token=value", providers = ["null"] }
"#,
    )
    .unwrap();

    let binary = Path::new(env!("CARGO_BIN_EXE_git-credential-secretspec"));
    let binary_directory = binary.parent().unwrap();
    let existing_path = env::var_os("PATH").unwrap_or_default();
    let path = env::join_paths(
        std::iter::once(binary_directory.to_path_buf()).chain(env::split_paths(&existing_path)),
    )
    .unwrap();
    let manifest = manifest.to_string_lossy().replace('\'', "'\\''");
    let helper = format!(
        "secretspec --url https://github.com --file '{manifest}' --username-secret GITHUB_USERNAME --password-secret GITHUB_TOKEN"
    );
    let mut child = Command::new("git")
        .args([
            "-c",
            "credential.helper=",
            "-c",
            &format!("credential.https://github.com.helper={helper}"),
            "credential",
            "fill",
        ])
        .env("HOME", temp.path())
        .env("XDG_CONFIG_HOME", temp.path().join("config"))
        .env("XDG_STATE_HOME", temp.path().join("state"))
        .env("APPDATA", temp.path().join("config"))
        .env("LOCALAPPDATA", temp.path().join("state"))
        .env("GIT_CONFIG_NOSYSTEM", "1")
        .env("GIT_TERMINAL_PROMPT", "0")
        .env("PATH", path)
        .env_remove("SECRETSPEC_FILE")
        .env_remove("SECRETSPEC_PROFILE")
        .env_remove("SECRETSPEC_PROVIDER")
        .env_remove("SECRETSPEC_REASON")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
    child
        .stdin
        .take()
        .unwrap()
        .write_all(b"protocol=https\nhost=github.com\n\n")
        .unwrap();
    let output = child.wait_with_output().unwrap();
    assert!(
        output.status.success(),
        "git credential fill failed: {}",
        String::from_utf8_lossy(&output.stderr)
    );
    let stdout = String::from_utf8(output.stdout).unwrap();
    assert!(stdout.contains("protocol=https\n"));
    assert!(stdout.contains("host=github.com\n"));
    assert!(stdout.contains("username=vimjoyer\n"));
    assert!(stdout.contains("password=token=value\n"));
}