use tokio::process::Command;
use crate::call::not_run;
use crate::errors::GitCallError;
const REDACTED: &str = "[REDACTED]";
pub async fn run(command: &mut Command, secrets: &[&str]) -> Result<(), GitCallError> {
let output = command
.output()
.await
.map_err(|source| not_run("clone", source))?;
if output.status.success() {
return Ok(());
}
Err(GitCallError::Refused {
command: "clone",
status: output.status,
stderr: hide(&String::from_utf8_lossy(&output.stderr), secrets),
})
}
#[must_use]
pub fn hide(said: &str, secrets: &[&str]) -> String {
secrets
.iter()
.filter(|secret| !secret.is_empty())
.fold(said.to_owned(), |text, secret| {
text.replace(secret, REDACTED)
})
}
#[cfg(test)]
mod tests {
use tokio::process::Command;
use super::run;
use crate::errors::GitCallError;
fn shell(script: &str) -> Command {
let mut command = Command::new("sh");
command.args(["-c", script]);
command
}
fn refusal(outcome: Result<(), GitCallError>) -> (Option<i32>, String) {
match outcome {
Err(GitCallError::Refused { status, stderr, .. }) => (status.code(), stderr),
other => panic!("{other:?}"),
}
}
#[tokio::test]
async fn a_clone_that_worked_says_nothing() {
assert!(run(&mut shell("exit 0"), &[]).await.is_ok());
}
#[tokio::test]
async fn a_clone_that_failed_carries_what_it_printed_whole() {
let outcome = run(
&mut shell("echo 'fatal: no such repository' >&2; exit 128"),
&[],
)
.await;
assert_eq!(
refusal(outcome),
(Some(128), "fatal: no such repository\n".to_owned())
);
}
#[tokio::test]
async fn a_clone_that_printed_nothing_carries_its_status() {
let outcome = run(&mut shell("exit 3"), &[]).await;
assert_eq!(refusal(outcome), (Some(3), String::new()));
}
#[tokio::test]
async fn a_secret_the_server_answered_is_taken_out() {
let outcome = run(
&mut shell("echo 'remote: rejected s3cr3t' >&2; exit 128"),
&["s3cr3t"],
)
.await;
assert_eq!(refusal(outcome).1, "remote: rejected [REDACTED]\n");
}
#[tokio::test]
async fn a_credential_that_is_empty_leaves_the_message_alone() {
let outcome = run(
&mut shell("echo 'fatal: no such repository' >&2; exit 128"),
&[""],
)
.await;
assert_eq!(refusal(outcome).1, "fatal: no such repository\n");
}
}