feat(indexer): started indexer
This commit is contained in:
parent
c5d7135d99
commit
188c04c62e
@ -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());
|
|
||||||
}
|
|
||||||
|
@ -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
117
src/store/indexer.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
@ -107,15 +118,14 @@ impl NsObject {
|
|||||||
/// first line consists of all size fixed datas (obj_type, size, modified)
|
/// first line consists of all size fixed datas (obj_type, size, modified)
|
||||||
/// next lines are the size variable datas
|
/// next lines are the size variable datas
|
||||||
///
|
///
|
||||||
/// * if it is a Tree obj after an empty line there will be the definition
|
/// * if it is a Tree obj after an empty line there will be the definition
|
||||||
/// 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(())
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user