rgit/src/data.rs

97 lines
2.7 KiB
Rust
Raw Normal View History

2020-09-29 01:04:28 +02:00
use sha1::{Digest, Sha1};
2020-09-27 14:52:54 +02:00
use std::fs;
use std::path::Path;
2020-09-29 01:04:28 +02:00
use std::str;
2020-11-07 14:25:11 +01:00
use walkdir::WalkDir;
2020-09-27 14:52:54 +02:00
static RGIT_DIR: &'static str = ".rgit";
pub struct RefValue {
pub value: String,
pub symbolic: bool,
}
2020-09-27 14:52:54 +02:00
pub fn init() -> std::io::Result<()> {
fs::create_dir(RGIT_DIR)?;
2020-09-29 01:04:28 +02:00
fs::create_dir(format!("{}/{}", RGIT_DIR, "objects"))?;
2020-09-27 14:52:54 +02:00
Ok(())
}
2020-09-29 01:04:28 +02:00
2020-10-05 13:58:48 +02:00
pub fn hash_object(content: &Vec<u8>, _type: String) -> String {
let mut raw = format!("{}\u{0}", _type).into_bytes();
let mut data = content.clone();
raw.append(&mut data);
2020-09-29 01:04:28 +02:00
let mut hasher = Sha1::new();
2020-10-05 13:58:48 +02:00
hasher.update(&raw);
2020-09-29 01:04:28 +02:00
let digest = &hasher.finalize();
let s = format!("{:x}", digest);
2020-10-05 13:58:48 +02:00
fs::write(format!("{}/{}/{}", RGIT_DIR, "objects", s), raw.as_slice())
.expect("Failed to write object");
2020-09-29 01:04:28 +02:00
return s;
}
2020-09-29 12:08:12 +02:00
2020-10-05 13:58:48 +02:00
pub fn get_object(hash: String, expected: String) -> String {
let mut content = fs::read_to_string(format!("{}/{}/{}", RGIT_DIR, "objects", hash))
2020-09-29 12:08:12 +02:00
.expect("Could not find a matching object");
2020-10-05 13:58:48 +02:00
let index = content.find(char::from(0)).expect("object type missing");
let data = content.split_off(index + 1);
if expected != "".to_owned() {
// Compare the type
2020-10-25 19:35:47 +01:00
content.pop();
2020-10-05 13:58:48 +02:00
assert_eq!(expected, content);
}
return data;
2020-09-29 12:08:12 +02:00
}
pub fn update_ref(reference: String, value: RefValue) {
assert!(!value.symbolic);
let path = format!("{}/{}", RGIT_DIR, reference);
let mut parents = Path::new(&path).ancestors();
parents.next();
let parent = parents.next().unwrap().to_str().unwrap();
fs::create_dir_all(parent).expect("Cannot create required dirs");
fs::write(path, value.value).expect("Failed to updated HEAD");
}
2020-11-02 00:01:24 +01:00
pub fn get_ref(reference: String) -> Result<RefValue, Box<dyn std::error::Error + 'static>> {
let ref_path = format!("{}/{}", RGIT_DIR, reference);
let value = fs::read_to_string(ref_path)?;
if !value.is_empty() && value.starts_with("ref:") {
let new_ref: Vec<&str> = value.splitn(2, ":").collect();
return get_ref(new_ref[1].to_owned());
}
return Ok(RefValue {
value,
symbolic: false,
});
2020-11-02 00:01:24 +01:00
}
2020-11-07 14:25:11 +01:00
pub fn iter_refs() -> Vec<(String, RefValue)> {
let mut refs: Vec<(String, RefValue)> = vec![];
2020-11-07 14:25:11 +01:00
refs.push(("HEAD".to_owned(), get_ref("HEAD".to_owned()).unwrap()));
for entry in WalkDir::new(format!("{}/refs/", RGIT_DIR)) {
let item = entry.unwrap();
let metadata = item.metadata().unwrap();
if metadata.is_file() {
let relative_path = item.path().strip_prefix(RGIT_DIR).unwrap();
refs.push((
relative_path.to_str().unwrap().to_owned(),
get_ref(relative_path.to_str().unwrap().to_owned()).unwrap(),
));
}
}
return refs;
}