162 lines
3.5 KiB
Rust
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())
|
|
}
|
|
}
|