diff --git a/Cargo.lock b/Cargo.lock index 08e54ae..118f406 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,12 @@ dependencies = [ "libc", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.77" @@ -180,6 +186,7 @@ name = "rgit" version = "0.1.0" dependencies = [ "clap", + "lazy_static", "sha-1", "tempfile", "walkdir", diff --git a/Cargo.toml b/Cargo.toml index ec66057..8dc4759 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ clap = "2.33.3" sha-1 = "0.9.1" walkdir = "2" tempfile = "3.1.0" +lazy_static = "1.4.0" diff --git a/src/data.rs b/src/data.rs index 6d674f4..dd28775 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,23 +1,53 @@ +use lazy_static::lazy_static; use sha1::{Digest, Sha1}; use std::fs; use std::path::Path; use std::str; +use std::sync::Mutex; use walkdir::WalkDir; -static RGIT_DIR: &'static str = ".rgit"; +static BASE_RGIT_DIR: &'static str = ".rgit"; + +lazy_static! { + static ref RGIT_DIR: Mutex = Mutex::new(BASE_RGIT_DIR.to_owned()); + static ref OLD_DIR: Mutex = Mutex::new("".to_owned()); +} pub struct RefValue { pub value: String, pub symbolic: bool, } +// The below two methods are not the same thing as a "context manager" +// I might need to replace it later with a better alternative. +pub fn set_rgit_dir(path: &str) { + let mut dir = RGIT_DIR.lock().unwrap(); + let mut old_dir = OLD_DIR.lock().unwrap(); + + *old_dir = dir.to_string(); + *dir = format!("{}/.rgit", path); +} + +pub fn reset_rgit_dir() { + let mut dir = RGIT_DIR.lock().unwrap(); + let mut old_dir = OLD_DIR.lock().unwrap(); + if old_dir.to_string() == "" { + *dir = BASE_RGIT_DIR.to_string().clone(); + } else { + *dir = old_dir.to_string(); + *old_dir = "".to_string(); + } +} + pub fn init() -> std::io::Result<()> { - fs::create_dir(RGIT_DIR)?; - fs::create_dir(format!("{}/{}", RGIT_DIR, "objects"))?; + let dir = RGIT_DIR.lock().unwrap().to_owned(); + fs::create_dir(dir.clone())?; + fs::create_dir(format!("{}/{}", dir, "objects"))?; Ok(()) } pub fn hash_object(content: &Vec, _type: String) -> String { + let dir = RGIT_DIR.lock().unwrap().to_owned(); let mut raw = format!("{}\u{0}", _type).into_bytes(); let mut data = content.clone(); raw.append(&mut data); @@ -27,14 +57,15 @@ pub fn hash_object(content: &Vec, _type: String) -> String { let digest = &hasher.finalize(); let s = format!("{:x}", digest); - fs::write(format!("{}/{}/{}", RGIT_DIR, "objects", s), raw.as_slice()) + fs::write(format!("{}/{}/{}", dir, "objects", s), raw.as_slice()) .expect("Failed to write object"); return s; } pub fn get_object(hash: String, expected: String) -> String { - let mut content = fs::read_to_string(format!("{}/{}/{}", RGIT_DIR, "objects", hash)) + let dir = RGIT_DIR.lock().unwrap().to_owned(); + let mut content = fs::read_to_string(format!("{}/{}/{}", dir, "objects", hash)) .expect("Could not find a matching object"); let index = content.find(char::from(0)).expect("object type missing"); @@ -50,6 +81,7 @@ pub fn get_object(hash: String, expected: String) -> String { } pub fn update_ref(mut reference: String, value: RefValue, deref: bool) { + let dir = RGIT_DIR.lock().unwrap().to_owned(); reference = get_ref_internal(reference, deref).0; let content: String; @@ -60,7 +92,7 @@ pub fn update_ref(mut reference: String, value: RefValue, deref: bool) { content = value.value; } - let path = format!("{}/{}", RGIT_DIR, reference); + let path = format!("{}/{}", dir, reference); let mut parents = Path::new(&path).ancestors(); parents.next(); @@ -74,11 +106,13 @@ pub fn get_ref(reference: String, deref: bool) -> RefValue { } pub fn delete_ref(reference: String, deref: bool) { + let dir = RGIT_DIR.lock().unwrap().to_owned(); let ref_to_del = get_ref_internal(reference, deref).0; - fs::remove_file(format!("{}/{}", RGIT_DIR, ref_to_del)).unwrap(); + fs::remove_file(format!("{}/{}", dir, ref_to_del)).unwrap(); } pub fn iter_refs(prefix: &str, deref: bool) -> Vec<(String, RefValue)> { + let dir = RGIT_DIR.lock().unwrap().to_owned(); let mut refs: Vec<(String, RefValue)> = vec![]; refs.push(("HEAD".to_owned(), get_ref("HEAD".to_owned(), deref))); @@ -87,12 +121,12 @@ pub fn iter_refs(prefix: &str, deref: bool) -> Vec<(String, RefValue)> { get_ref("MERGE_HEAD".to_owned(), deref), )); - for entry in WalkDir::new(format!("{}/refs/", RGIT_DIR)) { + for entry in WalkDir::new(format!("{}/refs/", dir.clone())) { let item = entry.unwrap(); let metadata = item.metadata().unwrap(); if metadata.is_file() { - let relative_path = item.path().strip_prefix(RGIT_DIR).unwrap(); + let relative_path = item.path().strip_prefix(dir.clone()).unwrap(); refs.push(( relative_path.to_str().unwrap().to_owned(), get_ref(relative_path.to_str().unwrap().to_owned(), deref), @@ -110,7 +144,8 @@ pub fn iter_refs(prefix: &str, deref: bool) -> Vec<(String, RefValue)> { } pub fn get_ref_internal(reference: String, deref: bool) -> (String, RefValue) { - let ref_path = format!("{}/{}", RGIT_DIR, reference); + let dir = RGIT_DIR.lock().unwrap().to_owned(); + let ref_path = format!("{}/{}", dir, reference); let mut value = fs::read_to_string(ref_path).unwrap_or("".to_owned()); let symbolic = !value.is_empty() && value.starts_with("ref:"); diff --git a/src/main.rs b/src/main.rs index 6b2ffb6..04d421c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,6 +94,7 @@ fn main() { ) .get_matches(); + data::set_rgit_dir("."); match matches.subcommand_name() { Some("init") => init(), Some("hash-object") => hash_object(matches), @@ -114,6 +115,7 @@ fn main() { Some("merge-base") => merge_base(matches), _ => println!("unknown sub command"), } + data::reset_rgit_dir(); } fn init() {