add refs to blob
This commit is contained in:
parent
16dbd25168
commit
4b12edbe5c
@ -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(_) => (),
|
||||||
|
@ -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 {
|
||||||
|
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user