feat(indexer): started indexer

This commit is contained in:
grimhilt 2024-09-04 22:59:02 +02:00
parent c5d7135d99
commit 188c04c62e
5 changed files with 177 additions and 21 deletions

View File

@ -1,8 +1,12 @@
use crate::config::config::Config; use crate::config::config::Config;
use crate::store::{ignorer::Ignorer, nsobject::NsObject}; use crate::store::{
ignorer::Ignorer,
indexer::Indexer,
nsobject::{self, NsObject},
};
use std::fs; use std::fs;
// use glob::glob; // use glob::glob;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
pub struct AddArgs { pub struct AddArgs {
/// List of files/dirs to add /// List of files/dirs to add
@ -18,8 +22,16 @@ pub fn exec(args: AddArgs, config: Config) {
let mut ignorer = Ignorer::new(config.get_root_unsafe()); let mut ignorer = Ignorer::new(config.get_root_unsafe());
ignorer.active_nsignore(!args.force); ignorer.active_nsignore(!args.force);
// Init indexer
let mut indexer = Indexer::new(config.get_root_unsafe());
dbg!(indexer.save());
dbg!(indexer.load());
return;
nsobject::init(config.get_root_unsafe());
if args.all { if args.all {
return add_dir(config.get_root_unsafe(), &mut ignorer); return add_dir(config.get_root_unsafe(), &mut ignorer, &mut indexer);
} }
for obj_to_add in args.files.iter() { for obj_to_add in args.files.iter() {
@ -28,12 +40,12 @@ pub fn exec(args: AddArgs, config: Config) {
if path_to_add.exists() { if path_to_add.exists() {
if path_to_add.is_dir() { if path_to_add.is_dir() {
add_dir(&path_to_add, &mut ignorer); add_dir(&path_to_add, &mut ignorer, &mut indexer);
} else { } else {
add_to_index(&path_to_add); indexer.index_file(path_to_add);
} }
} else if NsObject::from_local_path(&path_to_add).exists() { } else if NsObject::from_local_path(&path_to_add).exists() {
add_to_index(&path_to_add); indexer.index_file(path_to_add);
} else { } else {
// try globbing // try globbing
// todo!() // todo!()
@ -58,8 +70,7 @@ pub fn exec(args: AddArgs, config: Config) {
/// ///
/// # Parameters /// # Parameters
/// * `dir`: the directory to add from /// * `dir`: the directory to add from
/// * `force`: true if we should apply the nextsyncignore's rules fn add_dir(dir: &PathBuf, ignorer: &mut Ignorer, indexer: &mut Indexer) {
fn add_dir(dir: &PathBuf, ignorer: &mut Ignorer) {
let entries = match fs::read_dir(dir) { let entries = match fs::read_dir(dir) {
Ok(entries) => entries, Ok(entries) => entries,
Err(err) => { Err(err) => {
@ -84,14 +95,10 @@ fn add_dir(dir: &PathBuf, ignorer: &mut Ignorer) {
} }
if entry.path().is_dir() { if entry.path().is_dir() {
add_dir(&entry.path(), ignorer); indexer.index_dir(entry.path().clone());
add_to_index(&entry.path()); add_dir(&entry.path(), ignorer, indexer);
} else { } else {
add_to_index(&entry.path()); indexer.index_file(entry.path());
} }
} }
} }
fn add_to_index(path: &PathBuf) {
println!("{}", path.display());
}

View File

@ -1,4 +1,5 @@
pub mod ignorer; pub mod ignorer;
pub mod indexer;
pub mod nsignore; pub mod nsignore;
pub mod object;
pub mod nsobject; pub mod nsobject;
pub mod object;

117
src/store/indexer.rs Normal file
View File

@ -0,0 +1,117 @@
use crate::store::object::ObjType;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
fn get_level(previous_level: u16, path: &PathBuf) -> (u16, IndexLevel) {
let mut level = 0;
let mut path = path.clone();
while path.pop() {
level += 1;
}
let index_level = if previous_level < level {
IndexLevel::Down
} else {
IndexLevel::Up
};
(level, index_level)
}
enum IndexLevel {
Up,
Down,
}
struct IndexedObj {
obj_type: ObjType,
level: IndexLevel,
path: PathBuf,
}
pub struct Indexer {
index_file: PathBuf,
previous_level: u16,
indexed_objs: Vec<IndexedObj>,
}
impl Indexer {
pub fn new(repo_root: &PathBuf) -> Self {
let mut index_file = repo_root.clone();
index_file.push(".nextsync");
index_file.push("index");
Indexer {
index_file,
previous_level: 0,
indexed_objs: Vec::new(),
}
}
pub fn load(&self) -> io::Result<()> {
let mut file = File::open(&self.index_file)?;
let mut str = String::new();
// Skip reserved bytes
let mut byte = [0; 1];
file.read_exact(&mut byte)?;
file.seek(SeekFrom::Start(1))?;
// Read usize value
let mut usize_bytes = [0; std::mem::size_of::<usize>()];
file.read_exact(&mut usize_bytes)?;
dbg!(ObjType::try_from(byte[0]));
let usize_value = usize::from_le_bytes(usize_bytes);
// Read PathBuf as string
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
let path_str = String::from_utf8(buffer).unwrap();
let path = PathBuf::from(path_str);
println!("usize value: {}", usize_value);
println!("Path: {:?}", path);
Ok(())
}
fn index_obj(&mut self, path: PathBuf, obj_type: ObjType) {
let (level, index_level) = get_level(self.previous_level, &path);
self.previous_level = level;
self.indexed_objs.push(IndexedObj {
obj_type,
level: index_level,
path: path.clone(),
});
}
pub fn index_file(&mut self, path: PathBuf) {
self.index_obj(path, ObjType::Blob);
}
pub fn index_dir(&mut self, path: PathBuf) {
self.index_obj(path, ObjType::Tree);
}
pub fn save(&self) -> io::Result<()> {
let mut file = File::create(&self.index_file)?;
// Write reserved bytes
let variant = ObjType::Blob;
let byte: u8 = variant.into();
file.write_all(&[byte])?;
// Write usize value
let usize_value: usize = 12;
let usize_bytes = usize_value.to_le_bytes();
file.write_all(&usize_bytes)?;
// Write PathBuf as string
let path = PathBuf::from("/jodi/");
let path_str = path.to_str().unwrap();
file.write_all(path_str.as_bytes())?;
Ok(())
}
}

View File

@ -4,6 +4,12 @@ use crypto::sha1::Sha1;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::OnceLock; use std::sync::OnceLock;
pub static REPO_ROOT: OnceLock<PathBuf> = OnceLock::new();
pub fn init(repo_root: &PathBuf) {
REPO_ROOT.set(repo_root.clone());
}
type NsObjectChilds = Vec<Box<NsObject>>; type NsObjectChilds = Vec<Box<NsObject>>;
struct NsObjectPath { struct NsObjectPath {
@ -14,7 +20,12 @@ impl From<&str> for NsObjectPath {
fn from(hash: &str) -> Self { fn from(hash: &str) -> Self {
let (dir, res) = hash.split_at(2); let (dir, res) = hash.split_at(2);
let mut ns_obj_path = PathBuf::new(); let mut ns_obj_path = match REPO_ROOT.get() {
Some(path) => path.clone(),
None => {
panic!("fatal: 'REPO_ROOT' not set, you must initialize nsobject before using it!")
}
};
ns_obj_path.push(dir); ns_obj_path.push(dir);
ns_obj_path.push(res); ns_obj_path.push(res);
@ -111,11 +122,10 @@ impl NsObject {
/// of its subobjs (one line by subobj) * /// of its subobjs (one line by subobj) *
/// obj_type + hash /// obj_type + hash
pub fn save(&self) -> Result<(), ()> { pub fn save(&self) -> Result<(), ()> {
if !self.get_obj_path().exists { if !self.get_obj_path().exists() {
// delete current obj // delete current obj
// delete reference on parent // delete reference on parent
} else { } else {
} }
Ok(()) Ok(())
} }

View File

@ -12,13 +12,34 @@ pub struct ObjMetadata {
modified: Option<SystemTime>, modified: Option<SystemTime>,
} }
#[derive(PartialEq, Clone)] #[derive(PartialEq, Clone, Debug)]
#[repr(u8)]
pub enum ObjType { pub enum ObjType {
Obj, Obj,
Blob, Blob,
Tree, Tree,
} }
impl From<ObjType> for u8 {
fn from(variant: ObjType) -> Self {
variant as u8
}
}
impl TryFrom<u8> for ObjType {
type Error = String;
fn try_from(byte: u8) -> Result<Self, Self::Error> {
match byte {
0 => Ok(ObjType::Obj),
1 => Ok(ObjType::Blob),
2 => Ok(ObjType::Tree),
_ => Err(format!("Invalid byte value: {}", byte)),
}
}
}
#[derive(PartialEq, Clone)] #[derive(PartialEq, Clone)]
pub enum ObjStatus { pub enum ObjStatus {
Undefined, Undefined,