From 6770f34ec4cf97bedf49c6f46df4a7d424e80246 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Thu, 8 Aug 2024 09:19:49 +0100 Subject: [PATCH] Use git credential helper --- crates/bin/src/gh_token.rs | 49 +++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/bin/src/gh_token.rs b/crates/bin/src/gh_token.rs index 837f9f95..3f94a820 100644 --- a/crates/bin/src/gh_token.rs +++ b/crates/bin/src/gh_token.rs @@ -8,12 +8,15 @@ use tokio::process::Command; use zeroize::Zeroizing; pub(super) async fn get() -> io::Result>> { - let Output { status, stdout, .. } = Command::new("gh") - .args(["auth", "token"]) - .stdin(Stdio::null()) + // Prepare the input for the git credential fill command + let input = "host=github.com\nprotocol=https"; + + let Output { status, stdout, .. } = Command::new("git") + .args(["credential", "fill"]) + .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::null()) - .output() + .output_async_with_stdin(input.as_bytes()) .await?; let stdout = Zeroizing::new(stdout); @@ -25,12 +28,46 @@ pub(super) async fn get() -> io::Result>> { )); } - let s = str::from_utf8(&stdout).map_err(|err| { + // Assuming the password field is what's needed + let output_str = str::from_utf8(&stdout).map_err(|err| { io::Error::new( io::ErrorKind::InvalidData, format!("Invalid output, expected utf8: {err}"), ) })?; - Ok(Zeroizing::new(s.trim().into())) + // Extract the password from the output + let password = output_str + .lines() + .find_map(|line| { + if line.starts_with("password=") { + Some(line.trim_start_matches("password=").to_owned()) + } else { + None + } + }) + .ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "Password not found in the credential output", + ) + })?; + + Ok(Zeroizing::new(password.into())) +} + +// Helper function to execute a command with input +async fn output_async_with_stdin( + cmd: &mut Command, + input: &[u8], +) -> io::Result { + let mut child = cmd.spawn()?; + let mut stdin = child.stdin.take().expect("Failed to open stdin"); + + tokio::spawn(async move { + use tokio::io::AsyncWriteExt; + let _ = stdin.write_all(input).await; + }); + + child.wait_with_output().await }