add refs to blob

This commit is contained in:
grimhilt 2023-08-11 18:21:00 +02:00
parent 16dbd25168
commit 4b12edbe5c
3 changed files with 119 additions and 42 deletions

View File

@ -38,6 +38,13 @@ pub fn init() {
}; };
path.pop(); path.pop();
path.push("refs");
match builder.create(path.clone()) {
Ok(()) => (),
Err(_) => println!("Error: cannot create refs"),
};
path.pop();
path.push("HEAD"); path.push("HEAD");
match File::create(path.clone()) { match File::create(path.clone()) {
Ok(_) => (), Ok(_) => (),

View File

@ -7,16 +7,17 @@ use std::time::SystemTime;
use std::fs; use std::fs;
use crypto::sha1::Sha1; use crypto::sha1::Sha1;
use crypto::digest::Digest; use crypto::digest::Digest;
use crate::utils::path; use crate::utils::{path, read};
use crate::store::head; use crate::store::head;
use crate::store::object::{update_dates, add_node, create_obj, rm_node}; use crate::store::object::{update_dates, add_node, rm_node};
pub struct Blob { pub struct Blob {
r_path: PathBuf, r_path: PathBuf, // relative path
a_path: PathBuf, a_path: PathBuf, // absolute path
hash: String, hash: String, // hash of relative path
obj_p: PathBuf, file_hash: Option<String>,
data: Vec<String>, obj_p: PathBuf, // path of the object file
data: Vec<String>, // content of the blob
} }
impl Blob { impl Blob {
@ -38,6 +39,7 @@ impl Blob {
r_path, r_path,
a_path, a_path,
hash, hash,
file_hash: None,
obj_p, obj_p,
data: vec![], data: vec![],
} }
@ -53,10 +55,93 @@ impl Blob {
(line, file_name) (line, file_name)
} }
fn get_file_hash(&self) -> String { fn get_file_hash(&mut self) -> String {
if self.file_hash.is_none() {
let bytes = std::fs::read(self.a_path.clone()).unwrap(); let bytes = std::fs::read(self.a_path.clone()).unwrap();
let hash = md5::compute(&bytes); let hash = md5::compute(&bytes);
format!("{:x}", hash) self.file_hash = Some(format!("{:x}", hash))
}
self.file_hash.clone().unwrap()
}
fn create_blob_ref(&mut self, file_name: String, ts_remote: &str) -> io::Result<()> {
let metadata = fs::metadata(self.a_path.clone())?;
let secs = metadata
.modified()
.unwrap()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
let mut content = file_name.clone();
content.push_str(" ");
content.push_str(ts_remote);
content.push_str(" ");
content.push_str(&metadata.len().to_string());
content.push_str(" ");
content.push_str(&secs.to_string());
content.push_str(" ");
content.push_str(&self.get_file_hash());
content.push_str(" ");
let binding = self.obj_p.clone();
let child = binding.file_name();
self.obj_p.pop();
if !self.obj_p.clone().exists() {
fs::create_dir_all(self.obj_p.clone())?;
}
self.obj_p.push(child.unwrap().to_str().unwrap());
let mut file = OpenOptions::new()
.create_new(true)
.write(true)
.open(self.obj_p.clone())?;
writeln!(file, "{}", &content)?;
Ok(())
}
fn get_file_ref(&mut self) -> PathBuf {
let mut refs_p = path::refs();
let file_hash = self.get_file_hash().clone();
let (dir, res) = file_hash.split_at(2);
refs_p.push(dir);
if !refs_p.exists() {
fs::create_dir_all(refs_p.clone());
}
refs_p.push(res);
refs_p
}
// create a file in .nextsync/refs with the hash of this blob that
// redirect to the relative path
fn create_hash_ref(&mut self) -> io::Result<()> {
let refs_p = self.get_file_ref();
let mut file = OpenOptions::new()
.create(true)
.write(true)
.open(refs_p)?;
// todo deal with duplicate content
writeln!(file, "{}", self.r_path.clone().to_str().unwrap())?;
Ok(())
}
pub fn get_all_identical_blobs(&mut self) -> Vec<String> {
let refs_p = self.get_file_ref();
let mut blobs: Vec<String> = vec![];
if let Ok(lines) = read::read_lines(refs_p) {
for line in lines {
if let Ok(l) = line {
blobs.push(l.clone());
}
}
}
blobs
} }
pub fn create(&mut self, ts_remote: &str, up_parent: bool) -> io::Result<()> { pub fn create(&mut self, ts_remote: &str, up_parent: bool) -> io::Result<()> {
@ -69,42 +154,19 @@ impl Blob {
add_node(self.r_path.parent().unwrap(), &line)?; add_node(self.r_path.parent().unwrap(), &line)?;
} }
// create blob object if let Err(err) = self.create_blob_ref(file_name.clone(), ts_remote.clone()) {
let metadata = fs::metadata(self.a_path.clone())?; eprintln!("err: saving blob ref of {}: {}", self.obj_p.clone().display(), err);
}
let mut content = file_name.clone(); if let Err(err) = self.create_hash_ref() {
content.push_str(" "); eprintln!("err: saving hash ref of {}: {}", self.obj_p.clone().display(), err);
content.push_str(ts_remote); }
content.push_str(" ");
content.push_str(&metadata.len().to_string());
content.push_str(" ");
let secs = metadata
.modified()
.unwrap()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs();
content.push_str(&secs.to_string());
content.push_str(" ");
content.push_str(&self.get_file_hash());
content.push_str(" ");
// create ref of object
let binding = self.obj_p.clone();
let child = binding.file_name();
self.obj_p.pop();
self.obj_p.push(child.unwrap().to_str().unwrap());
let mut file = OpenOptions::new()
.create_new(true)
.write(true)
.open(self.obj_p.clone())?;
writeln!(file, "{}", &content)?;
// update date for all parent // update date for all parent
if up_parent { if up_parent {
update_dates(self.r_path.clone(), ts_remote)?; update_dates(self.r_path.clone(), ts_remote)?;
} }
Ok(()) Ok(())
} }
@ -169,7 +231,8 @@ impl Blob {
fn has_same_hash(&mut self) -> bool { fn has_same_hash(&mut self) -> bool {
self.read_data(); self.read_data();
if self.data.len() < 5 { return false; } if self.data.len() < 5 { return false; }
self.data[4] == self.get_file_hash() let file_hash = self.get_file_hash().clone();
self.data[4] == file_hash
} }
pub fn has_change(&mut self) -> bool { pub fn has_change(&mut self) -> bool {

View File

@ -117,6 +117,13 @@ pub fn objects() -> PathBuf {
path path
} }
pub fn refs() -> PathBuf {
let mut path = repo_root();
path.push(".nextsync");
path.push("refs");
path
}
pub fn nextsyncignore() -> Option<PathBuf> { pub fn nextsyncignore() -> Option<PathBuf> {
let mut path = repo_root(); let mut path = repo_root();
path.push(".nextsyncignore"); path.push(".nextsyncignore");