Skip to content
Clone
030e59e
90 lines 2.7 KB Rust
use std::path::Path;
use crate::Error;
use crate::remote::types::RemoteAuth;
pub fn run(repo_path: &Path, args: &[&str]) -> Result<String, Error> {
let out = duct::cmd("git", args)
.env("GIT_DIR", repo_path)
.env("GIT_TERMINAL_PROMPT", "0")
.read()
.map_err(|e| Error::Other(format!("git command failed: {e}")))?;
Ok(out)
}
pub fn run_bytes(repo_path: &Path, args: &[&str]) -> Result<Vec<u8>, Error> {
let out = duct::cmd("git", args)
.env("GIT_DIR", repo_path)
.env("GIT_TERMINAL_PROMPT", "0")
.stdout_capture()
.stderr_capture()
.run()
.map_err(|e| Error::Other(format!("git command failed: {e}")))?;
if !out.status.success() {
return Err(Error::Other(format!(
"git command failed: {}",
String::from_utf8_lossy(&out.stderr)
)));
}
Ok(out.stdout)
}
pub fn run_status(repo_path: &Path, args: &[&str]) -> Result<bool, Error> {
let output = duct::cmd("git", args)
.env("GIT_DIR", repo_path)
.env("GIT_TERMINAL_PROMPT", "0")
.run()
.map_err(|e| Error::Other(format!("git command failed: {e}")))?;
Ok(output.status.success())
}
pub fn run_remote(repo_path: &Path, args: &[&str], auth: &RemoteAuth) -> Result<String, Error> {
let mut cmd = duct::cmd("git", args)
.env("GIT_DIR", repo_path)
.env("GIT_TERMINAL_PROMPT", "0");
let mut askpass = None;
match auth {
RemoteAuth::None | RemoteAuth::SshKey(_) => {}
RemoteAuth::Token(token) => {
let helper = write_askpass_helper(token)?;
let helper_path = helper.path.clone();
cmd = cmd
.env("GIT_ASKPASS", &helper_path)
.env("GIT_TERMINAL_PROMPT", "0");
askpass = Some(helper);
}
}
let out = cmd
.read()
.map_err(|e| Error::Other(format!("git command failed: {e}")))?;
if let Some(h) = askpass.as_mut() {
let _ = std::fs::remove_file(&h.path);
}
Ok(out)
}
struct AskPassHelper {
path: std::path::PathBuf,
}
impl Drop for AskPassHelper {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.path);
}
}
fn write_askpass_helper(token: &str) -> Result<AskPassHelper, Error> {
let dir = std::env::temp_dir();
let path = dir.join(format!("git-askpass-{}.sh", std::process::id()));
let script = format!(
"#!/bin/sh\nprintf '%s\\n' '{}'\n",
token.replace('\'', "'\\''")
);
std::fs::write(&path, script).map_err(|e| Error::Io(e.to_string()))?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let _ = std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o700));
}
Ok(AskPassHelper { path })
}