use std::io::{BufRead, BufReader, Read};
use std::path::{Path, PathBuf};
use std::process::Command;
mod cache;
mod error;
mod git;
mod git_cmd;
mod parser;
mod pathdiff;
mod status;
use cache::Cache;
use error::ToGitnuError;
use git_cmd::GitCommand;
pub use error::GitnuError;
pub use parser::parse;
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
pub const MAX_CACHE_SIZE: usize = 20;
#[derive(Debug)]
pub struct App {
git_command: Option<GitCommand>,
cmd: Command,
cache: Vec<String>,
file_prefix: PathBuf,
}
impl App {
pub fn new(cwd: PathBuf) -> App {
let mut cmd = Command::new("git");
if atty::is(atty::Stream::Stdout) {
cmd.args(["-c", "color.ui=always"]);
}
cmd.current_dir(&cwd);
App {
git_command: None,
cache: Vec::with_capacity(MAX_CACHE_SIZE),
cmd,
file_prefix: PathBuf::new(),
}
}
pub fn cwd(&self) -> &Path {
self.cmd.get_current_dir().unwrap()
}
pub fn set_git_command(&mut self, git_command: GitCommand) {
self.git_command = Some(git_command);
}
pub fn arg<S: AsRef<std::ffi::OsStr>>(&mut self, arg: S) {
self.cmd.arg(arg);
}
pub fn git_command(&self) -> Option<&GitCommand> {
self.git_command.as_ref()
}
#[cfg(test)]
pub fn cmd(&self) -> &Command {
&self.cmd
}
pub fn run(&mut self) -> Result<(), GitnuError> {
if std::env::var("GITNU_DEBUG").is_ok() {
eprintln!("\x1b[0;30m{}\x1b[0m", self.preview());
}
use GitCommand as G;
match self.git_command {
Some(G::Status(is_normal)) => status::status(self, is_normal),
Some(G::Version) => {
let result = self.cmd.status().gitnu_err().map(|_| ());
println!("gitnu version {}", VERSION.unwrap_or("unknown"));
result
}
_ => self.cmd.status().gitnu_err().map(|_| ()),
}
}
pub fn preview(&self) -> String {
let mut preview = String::from("git");
self.cmd.get_args().filter_map(|v| v.to_str()).for_each(|arg| {
preview.push(' ');
preview.push_str(arg)
});
preview.replace(" -c color.ui=always", "")
}
}
fn lines<R: Read>(src: R) -> impl Iterator<Item = String> {
BufReader::new(src).lines().filter_map(|v| v.ok())
}
#[cfg(test)]
mod tests;