use crate::commands::init::Config;
use glob::Pattern;
use std::{
error::Error,
fs::{self, read_dir, File},
io::{self, BufRead, Write},
path::Path,
};
pub fn repo(config: &Config) -> Result<(), Box<dyn Error>> {
println!("Creating repository in {}", config.file_path);
let path = config.file_path.clone() + "/.gor";
fs::create_dir_all(path.clone())?;
initial_vcs_files(&path)?;
existing_vcs_files(&config.file_path.clone())?;
Ok(())
}
fn initial_vcs_files(path: &String) -> Result<(), Box<dyn Error>> {
fs::create_dir_all(format!("{path}/refs/heads"))?;
fs::create_dir_all(format!("{path}/refs/tags"))?;
fs::create_dir_all(format!("{path}/objects"))?;
let mut head = File::create(format!("{path}/HEAD"))?;
let buf = b"ref: refs/heads/master\n";
head.write_all(buf)?;
let mut config = File::create(format!("{path}/config"))?;
let buf = b"[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = false\n";
config.write_all(buf)?;
let mut ignore = File::create(format!("{path}/../.gorignore"))?;
let buf = b"*.git\n*.gor\ntarget\n";
ignore.write_all(buf)?;
Ok(())
}
fn existing_vcs_files(path: &String) -> Result<(), Box<dyn Error>> {
let mut ignore_patterns = Vec::new();
if let Ok(file) = File::open(path.clone() + "/.gorignore") {
for line in io::BufReader::new(file).lines() {
if let Ok(pattern) = line {
ignore_patterns.push(Pattern::new(&format!("{}/{}", path, pattern))?);
}
}
}
let curr_path = Path::new(path);
visit_dir(curr_path, &ignore_patterns)?;
Ok(())
}
fn visit_dir(dir: &Path, ignore_patterns: &Vec<Pattern>) -> Result<(), Box<dyn Error>> {
for entry in read_dir(dir)? {
let entry = entry?;
let path = entry.path();
let match_path = Path::new(&path);
let mut flag: bool = false;
for pattern in ignore_patterns {
if pattern.matches_path(match_path) {
flag = true;
}
}
if flag {
continue;
}
if path.is_dir() {
visit_dir(&path, ignore_patterns)?;
} else {
println!("{:?}", path);
}
}
Ok(())
}