use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
use std::process::Command;
use std::process::Stdio;
use crate::error::GitError;
pub fn run_command(
working_dir: &Path,
command: &str,
) -> Result<(), GitError>
{
let child = Command::new("bash")
.current_dir(working_dir)
.args(["-c", &format!("git {command}")])
.stdout(Stdio::piped())
.spawn()?;
let Some(stdout) = child.stdout
else
{
return Err(GitError::Stdout);
};
let lines = BufReader::new(stdout).lines();
for line in lines.map_while(Result::ok)
{
println!("{line}");
}
Ok(())
}
pub fn clone<P, S>(
working_dir: P,
remote_repository: S,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S: AsRef<str>,
{
let inner = |working_dir: &Path, remote_repository: &str| {
run_command(
working_dir,
&format!("clone {remote_repository} ."),
)
};
inner(
working_dir.as_ref(),
remote_repository.as_ref(),
)
}
pub fn clone_branch<P, S1, S2>(
working_dir: P,
remote_repository: S1,
branch: S2,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S1: AsRef<str>,
S2: AsRef<str>,
{
let inner = |working_dir: &Path, remote_repository: &str, branch: &str| {
run_command(
working_dir,
&format!("clone --branch {branch} {remote_repository} ."),
)
};
inner(
working_dir.as_ref(),
remote_repository.as_ref(),
branch.as_ref(),
)
}
pub fn checkout<P, S>(
working_dir: P,
branch: S,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S: AsRef<str>,
{
let inner = |working_dir: &Path, branch: &str| {
run_command(
working_dir,
&format!("checkout -b {branch}"),
)
};
inner(
working_dir.as_ref(),
branch.as_ref(),
)
}
pub fn config<P, S1, S2>(
working_dir: P,
user_name: S1,
user_email: S2,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S1: AsRef<str>,
S2: AsRef<str>,
{
let inner = |working_dir: &Path, user_name: &str, user_email: &str| {
run_command(
working_dir,
&format!("config user.name \"{user_name}\""),
)?;
run_command(
working_dir,
&format!("config user.email \"{user_email}\""),
)?;
run_command(
working_dir,
"config push.autoSetupRemote \"true\"",
)?;
Ok(())
};
inner(
working_dir.as_ref(),
user_name.as_ref(),
user_email.as_ref(),
)
}
pub fn add_all<P>(working_dir: P) -> Result<(), GitError>
where
P: AsRef<Path>,
{
let inner = |working_dir: &Path| {
run_command(
working_dir,
"add .",
)
};
inner(working_dir.as_ref())
}
pub fn commit<P, S>(
working_dir: P,
message: S,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S: AsRef<str>,
{
let inner = |working_dir: &Path, message: &str| {
run_command(
working_dir,
&format!("commit -m \"{message}\""),
)
};
inner(
working_dir.as_ref(),
message.as_ref(),
)
}
pub fn push<P>(working_dir: P) -> Result<(), GitError>
where
P: AsRef<Path>,
{
let inner = |working_dir: &Path| {
run_command(
working_dir,
"push",
)
};
inner(working_dir.as_ref())
}
pub fn add_commit_and_push<P, S>(
working_dir: P,
message: S,
) -> Result<(), GitError>
where
P: AsRef<Path>,
S: AsRef<str>,
{
let inner = |working_dir: &Path, message: &str| {
add_all(working_dir)?;
commit(
working_dir,
message,
)?;
push(working_dir)?;
Ok(())
};
inner(
working_dir.as_ref(),
message.as_ref(),
)
}