nextsync/src/store/structs.rs

162 lines
3.5 KiB
Rust

use crate::utils::{path, tests};
use crypto::{digest::Digest, sha1::Sha1};
use std::env;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
static REPO_ROOT: OnceLock<PathBuf> = OnceLock::new();
pub fn init(repo_root: &PathBuf) {
if tests::is_var_setup() {
env::set_var("REPO_ROOT_DEV", path::to_string(repo_root));
}
if REPO_ROOT.get().is_none() {
let _ = REPO_ROOT.set(repo_root.clone());
}
}
pub fn get_repo_root() -> PathBuf {
if tests::is_var_setup() {
return env::var("REPO_ROOT_DEV")
.expect("REPO_ROOT_DEV is not set")
.into();
}
match REPO_ROOT.get() {
Some(path) => path.clone(),
None => {
panic!("fatal: 'REPO_ROOT' not set, you must initialize nsobject before using it!")
}
}
}
#[derive(Debug, Clone)]
pub struct ObjPath {
path: PathBuf,
abs: OnceLock<PathBuf>,
}
impl ObjPath {
pub fn abs(&self) -> &PathBuf {
self.abs.get_or_init(|| {
let mut path = get_repo_root();
path.push(self.path.clone());
path
})
}
}
impl PartialEq for ObjPath {
fn eq(&self, other: &Self) -> bool {
if self.abs.get().is_some() && other.abs.get().is_some() {
self.abs() == other.abs()
} else {
self.path == other.path
}
}
}
impl Deref for ObjPath {
type Target = PathBuf;
fn deref(&self) -> &PathBuf {
&self.path
}
}
impl DerefMut for ObjPath {
fn deref_mut(&mut self) -> &mut PathBuf {
&mut self.path
}
}
impl AsRef<Path> for ObjPath {
fn as_ref(&self) -> &Path {
&self.path
}
}
pub fn to_obj_path(path: &PathBuf) -> ObjPath {
ObjPath {
path: path.clone(),
abs: OnceLock::new(),
}
}
impl Into<ObjPath> for &PathBuf {
fn into(self) -> ObjPath {
ObjPath {
path: path::to_repo_relative(self),
abs: OnceLock::from(self.clone()),
}
}
}
impl Into<ObjPath> for PathBuf {
fn into(self) -> ObjPath {
ObjPath {
path: path::to_repo_relative(&self),
abs: OnceLock::from(self.clone()),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct NsObjPath {
path: PathBuf,
}
impl Deref for NsObjPath {
type Target = PathBuf;
fn deref(&self) -> &PathBuf {
&self.path
}
}
impl DerefMut for NsObjPath {
fn deref_mut(&mut self) -> &mut PathBuf {
&mut self.path
}
}
impl AsRef<Path> for NsObjPath {
fn as_ref(&self) -> &Path {
&self.path
}
}
impl From<&str> for NsObjPath {
fn from(hash: &str) -> Self {
let (dir, res) = hash.split_at(2);
let mut ns_obj_path = get_repo_root();
ns_obj_path.push(".nextsync");
ns_obj_path.push("objects");
ns_obj_path.push(dir);
ns_obj_path.push(res);
NsObjPath { path: ns_obj_path }
}
}
impl From<&ObjPath> for NsObjPath {
fn from(obj_path: &ObjPath) -> Self {
// NsObjPath of root is the HEAD file
if path::get_level(obj_path) == 0 {
let mut path = get_repo_root();
path.push(".nextsync");
path.push("HEAD");
return NsObjPath { path };
}
let mut hasher = Sha1::new();
hasher.input_str(
obj_path
.to_str()
.expect("Cannot contains non UTF-8 char in path"),
);
NsObjPath::from(hasher.result_str().as_str())
}
}