step fifty five: allow git directory to change

This commit is contained in:
Gonçalo Valério 2020-12-01 20:33:10 +00:00
parent ca176b8a3b
commit 027bad5d5f
4 changed files with 55 additions and 10 deletions

7
Cargo.lock generated
View File

@ -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",

View File

@ -11,3 +11,4 @@ clap = "2.33.3"
sha-1 = "0.9.1"
walkdir = "2"
tempfile = "3.1.0"
lazy_static = "1.4.0"

View File

@ -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<String> = Mutex::new(BASE_RGIT_DIR.to_owned());
static ref OLD_DIR: Mutex<String> = 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<u8>, _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<u8>, _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:");

View File

@ -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() {