Browse Source

TreeWalker WIP.

deprecated_bsvfs
Simon Boyé 3 years ago
parent
commit
956d2d337c
  1. 3
      cas-core/src/error.rs
  2. 8
      cas-core/src/object_id.rs
  3. 2
      libbsv/.gitignore
  4. 2
      libbsv/src/lib.rs
  5. 4
      libbsv/src/tree_item.rs
  6. 206
      libbsv/src/tree_walker.rs

3
cas-core/src/error.rs

@ -84,6 +84,9 @@ pub enum Error {
#[error("io error: {0}")] #[error("io error: {0}")]
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
#[error("non-unicode file name: '{0}'")]
NonUnicodeFileName(String),
#[error("{0}")] #[error("{0}")]
UnknownError(String), UnknownError(String),
} }

8
cas-core/src/object_id.rs

@ -57,6 +57,14 @@ impl FromStr for ObjectId {
} }
} }
impl Default for ObjectId {
fn default() -> Self {
return Self {
id: Arc::new(vec![]),
}
}
}
impl fmt::Display for ObjectId { impl fmt::Display for ObjectId {
fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
write_hex(f, self.id.as_slice()) write_hex(f, self.id.as_slice())

2
libbsv/.gitignore

@ -1,2 +0,0 @@
/target
Cargo.lock

2
libbsv/src/lib.rs

@ -23,7 +23,7 @@ extern crate cas_core;
mod permissions; mod permissions;
mod tree_item; mod tree_item;
// mod tree_walker; mod tree_walker;
// mod config; // mod config;
mod path_map; mod path_map;
mod ignore; mod ignore;

4
libbsv/src/tree_item.rs

@ -51,12 +51,12 @@ pub struct TreeItem {
} }
impl TreeItem { impl TreeItem {
pub fn from_metadata(name: &str, metadata: &std::fs::Metadata, oid: ObjectId) -> Result<Self> { pub fn from_metadata(name: String, metadata: &std::fs::Metadata, oid: ObjectId) -> Result<Self> {
let otype = otype_from_metadata(metadata)?; let otype = otype_from_metadata(metadata)?;
let permissions = Permissions::from_metadata(metadata)?; let permissions = Permissions::from_metadata(metadata)?;
Ok(Self { Ok(Self {
name: name.to_string(), name: name,
otype, otype,
size: metadata.len(), size: metadata.len(),
created: metadata.created().unwrap_or(UNIX_EPOCH), created: metadata.created().unwrap_or(UNIX_EPOCH),

206
libbsv/src/tree_walker.rs

@ -14,130 +14,118 @@
// along with cdb. If not, see <https://www.gnu.org/licenses/>. // along with cdb. If not, see <https://www.gnu.org/licenses/>.
use std::path::Utf8Path; use std::iter::Peekable;
// use std::fs::Metadata; use std::fs::{DirEntry, Metadata, ReadDir, read_dir};
use std::fs::{DirEntry, ReadDir, read_dir}; use std::vec::IntoIter;
use cas_core::{err, Error, Result}; use camino::{Utf8Path, Utf8PathBuf};
// use crate::{PathPair, Repository, TreeItem}; use cas_core::{err, Error, ObjectId, Result};
use crate::{PathPair, Repository, TreeItem};
#[derive(Debug)]
pub struct RecursiveDirIterator { #[derive(Debug, Clone, Copy, PartialEq, Eq)]
dir_iterators: Vec<ReadDir>, pub enum Action {
Add,
Update,
Remove,
Skip,
Ignore,
} }
impl RecursiveDirIterator { pub struct TreeWalker {
pub fn new<P: AsRef<Utf8Path>>(root_dir: P) -> Result<RecursiveDirIterator> { dir_it: Peekable<IntoIter<Result<TreeItem>>>,
Ok(RecursiveDirIterator { prev_tree_it: Peekable<IntoIter<TreeItem>>,
dir_iterators: vec![read_dir(root_dir)?], }
})
}
pub fn pop_dir(&mut self) -> Result<()> {
match self.dir_iterators.pop() { impl TreeWalker {
Some(_) => Ok(()), pub fn new<P: AsRef<Utf8Path>>(path: P, prev_tree: Vec<TreeItem>) -> Result<Self> {
None => err!("cannot pop directory: iterator reached the end"), let dir_entries = read_dir(path.as_ref().to_path_buf())?
} .map(|res| res.map_err(|err| err.into()))
.collect::<Result<Vec<_>>>()?;
let mut dir_items: Vec<_> = dir_entries.into_iter()
.map(|dir_entry| {
let file_name = dir_entry
.file_name()
.into_string()
// .or_else(|os_string| err!("non-unicode file name '{}'", os_string.to_string_lossy()))?;
.or_else(|os_string| Err(Error::NonUnicodeFileName(os_string.to_string_lossy().into())))?;
let metadata = dir_entry.metadata()?;
Ok(TreeItem::from_metadata(
file_name,
&metadata,
ObjectId::default()
)?
)
})
.collect();
dir_items.sort_unstable_by_key(|result| {
match result {
Ok(entry) => entry.name.clone(),
Err(_) => String::default(),
}
});
Ok(Self {
dir_it: dir_items.into_iter().peekable(),
prev_tree_it: prev_tree.into_iter().peekable(),
})
} }
} }
impl Iterator for RecursiveDirIterator { impl Iterator for TreeWalker {
type Item = Result<DirEntry>; type Item = Result<(Action, TreeItem)>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(top_it) = self.dir_iterators.last_mut() { match (self.dir_it.peek(), self.prev_tree_it.peek()) {
let next = top_it.next(); (Some(Err(_)), _) => {
if let Some(item) = next { Some(Err(self.dir_it.next().unwrap().unwrap_err()))
let item = item.and_then(|dir_entry| {
if let Ok(file_type) = dir_entry.file_type() {
if file_type.is_dir() {
self.dir_iterators.push(read_dir(dir_entry.path())?)
}
}
Ok(dir_entry)
});
return Some(item.map_err(Into::into));
}
else {
self.dir_iterators.pop();
} }
(Some(Ok(curr_item)), Some(prev_item)) => {
if curr_item.name == prev_item.name {
let action =
if curr_item.modified != prev_item.modified {
Action::Update
}
else {
Action::Skip
};
self.prev_tree_it.next();
Some(Ok((action, self.dir_it.next().unwrap().unwrap())))
}
else if curr_item.name < prev_item.name {
Some(Ok((Action::Add, self.dir_it.next().unwrap().unwrap())))
}
else {
Some(Ok((Action::Remove, self.prev_tree_it.next().unwrap())))
}
},
(Some(_), None) => {
Some(Ok((Action::Add, self.dir_it.next().unwrap().unwrap())))
},
(None, Some(_)) => {
Some(Ok((Action::Remove, self.prev_tree_it.next().unwrap())))
},
(None, None) => None,
} }
None
} }
} }
// pub trait FsWalker { #[cfg(test)]
// fn visit(&self) mod tests {
// } use super::*;
#[test]
// #[derive(Debug, Clone, Copy, PartialEq, Eq)] fn test_tree_walker() {
// pub enum Action { for item in TreeWalker::new("/home/draklaw/tmp", vec![]).unwrap() {
// Default, match item {
// Add, Ok((action, tree_item)) => println!("{:?} {:?}", action, tree_item.name),
// Update, Err(err) => println!("error while iterating directory: {}", err),
// Remove, }
// Skip, }
// Ignore, }
// } }
// #[derive()]
// pub struct TreeWalker<'repo> {
// repository: &'repo Repository,
// rules: Vec<Box<dyn Fn(&Utf8Path, Option<&TreeItem>) -> Result<Action>>>,
// default_action: Action,
// reporters: Vec<Box<dyn Fn(&Utf8Path, Action, Option<&ObjectId>) -> Result<()>>>,
// }
// impl<'repo> TreeWalker<'repo> {
// pub fn process<P: AsRef<Utf8Path>>(&self, physic_path: P) -> Result<Option<ObjectId>>
// {
// let physic_path_ref = physic_path.as_ref();
// let metadata = std::fs::symlink_metadata(physic_path_ref)
// .or_else(|err| err!("failed to read {}: {}", physic_path_ref, err))?;
// let path_pair = match self.repository.path_pair_from_physic_path(physic_path)? {
// Some(path_pair) => path_pair,
// None => return Ok(None),
// };
// let maybe_tree = self.repository
// .oid_from_logic_path(&path_pair.logic)
// .ok()
// .map(|oid| self.repository.read_tree(&oid))
// .transpose()?
// .flatten();
// self.process_impl(&path_pair, &metadata, &maybe_tree)
// .map(|oid| Some(oid))
// }
// fn process_impl(&self, path_pair: &PathPair, metadata: &Metadata, maybe_tree: &Option<Vec<TreeItem>>) -> Result<ObjectId> {
// err!("not implemented")
// }
// fn eval_rules(&self, path: &Utf8Path, maybe_item: Option<&TreeItem>) -> Result<Action> {
// self.rules.iter()
// .map(|rule|
// rule(path, maybe_item)
// )
// .skip_while(|action_result|
// *action_result == Ok(Action::Default)
// )
// .nth(0)
// .unwrap_or(Ok(self.default_action))
// }
// fn report(&self, path: &Utf8Path, action: Action, maybe_oid: Option<&ObjectId>) -> Result<()> {
// for reporter in &self.reporters {
// reporter(path, action, maybe_oid)?
// }
// Ok(())
// }
// }

Loading…
Cancel
Save