Skip to content

Commit

Permalink
use typed_path
Browse files Browse the repository at this point in the history
  • Loading branch information
aawsome committed Dec 29, 2024
1 parent 87e73cb commit dbc9dab
Show file tree
Hide file tree
Showing 24 changed files with 390 additions and 373 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ itertools = "0.13.0"
quick_cache = "0.6.9"
shell-words = "1.1.0"
strum = { version = "0.26.3", features = ["derive"] }
typed-path = "0.10.0"
zstd = "0.13.2"

[target.'cfg(not(windows))'.dependencies]
Expand Down
7 changes: 3 additions & 4 deletions crates/core/src/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ pub(crate) mod parent;
pub(crate) mod tree;
pub(crate) mod tree_archiver;

use std::path::{Path, PathBuf};

use chrono::Local;
use log::warn;
use pariter::{scope, IteratorExt};
use typed_path::{UnixPath, UnixPathBuf};

use crate::{
archiver::{
Expand Down Expand Up @@ -126,8 +125,8 @@ impl<'a, BE: DecryptFullBackend, I: ReadGlobalIndex> Archiver<'a, BE, I> {
pub fn archive<R>(
mut self,
src: &R,
backup_path: &Path,
as_path: Option<&PathBuf>,
backup_path: &UnixPath,
as_path: Option<&UnixPathBuf>,
skip_identical_parent: bool,
no_scan: bool,
p: &impl Progress,
Expand Down
24 changes: 8 additions & 16 deletions crates/core/src/archiver/parent.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::{
cmp::Ordering,
ffi::{OsStr, OsString},
};
use std::cmp::Ordering;

use log::warn;

Expand Down Expand Up @@ -124,20 +121,20 @@ impl Parent {
/// # Returns
///
/// The parent node with the given name, or `None` if the parent node is not found.
fn p_node(&mut self, name: &OsStr) -> Option<&Node> {
fn p_node(&mut self, name: &[u8]) -> Option<&Node> {
match &self.tree {
None => None,
Some(tree) => {
let p_nodes = &tree.nodes;
loop {
match p_nodes.get(self.node_idx) {
None => break None,
Some(p_node) => match p_node.name().as_os_str().cmp(name) {
Ordering::Less => self.node_idx += 1,
Some(p_node) => match name.cmp(&p_node.name()) {
Ordering::Greater => self.node_idx += 1,
Ordering::Equal => {
break Some(p_node);
}
Ordering::Greater => {
Ordering::Less => {
break None;
}
},
Expand All @@ -161,7 +158,7 @@ impl Parent {
/// # Note
///
/// TODO: This function does not check whether the given node is a directory.
fn is_parent(&mut self, node: &Node, name: &OsStr) -> ParentResult<&Node> {
fn is_parent(&mut self, node: &Node, name: &[u8]) -> ParentResult<&Node> {
// use new variables as the mutable borrow is used later
let ignore_ctime = self.ignore_ctime;
let ignore_inode = self.ignore_inode;
Expand Down Expand Up @@ -190,12 +187,7 @@ impl Parent {
///
/// * `be` - The backend to read from.
/// * `name` - The name of the parent node.
fn set_dir(
&mut self,
be: &impl DecryptReadBackend,
index: &impl ReadGlobalIndex,
name: &OsStr,
) {
fn set_dir(&mut self, be: &impl DecryptReadBackend, index: &impl ReadGlobalIndex, name: &[u8]) {
let tree = self.p_node(name).and_then(|p_node| {
p_node.subtree.map_or_else(
|| {
Expand Down Expand Up @@ -257,7 +249,7 @@ impl Parent {
&mut self,
be: &impl DecryptReadBackend,
index: &impl ReadGlobalIndex,
item: TreeType<O, OsString>,
item: TreeType<O, Vec<u8>>,
) -> Result<ItemWithParent<O>, TreeStackEmptyError> {
let result = match item {
TreeType::NewTree((path, node, tree)) => {
Expand Down
65 changes: 28 additions & 37 deletions crates/core/src/archiver/tree.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::{ffi::OsString, path::PathBuf};
use crate::backend::node::{Metadata, Node, NodeType};

use crate::{
backend::node::{Metadata, Node, NodeType},
blob::tree::comp_to_osstr,
};
use typed_path::{Component, UnixPathBuf};

/// `TreeIterator` turns an Iterator yielding items with paths and Nodes into an
/// Iterator which ensures that all subdirectories are visited and closed.
Expand All @@ -18,7 +15,7 @@ pub(crate) struct TreeIterator<T, I> {
/// The original Iterator.
iter: I,
/// The current path.
path: PathBuf,
path: UnixPathBuf,
/// The current item.
item: Option<T>,
}
Expand All @@ -31,7 +28,7 @@ where
let item = iter.next();
Self {
iter,
path: PathBuf::new(),
path: UnixPathBuf::new(),
item,
}
}
Expand All @@ -49,32 +46,25 @@ where
#[derive(Debug)]
pub(crate) enum TreeType<T, U> {
/// New tree to be inserted.
NewTree((PathBuf, Node, U)),
NewTree((UnixPathBuf, Node, U)),
/// A pseudo item which indicates that a tree is finished.
EndTree,
/// Original item.
Other((PathBuf, Node, T)),
Other((UnixPathBuf, Node, T)),
}

impl<I, O> Iterator for TreeIterator<(PathBuf, Node, O), I>
impl<I, O> Iterator for TreeIterator<(UnixPathBuf, Node, O), I>
where
I: Iterator<Item = (PathBuf, Node, O)>,
I: Iterator<Item = (UnixPathBuf, Node, O)>,
{
type Item = TreeType<O, OsString>;
type Item = TreeType<O, Vec<u8>>;
fn next(&mut self) -> Option<Self::Item> {
match &self.item {
None => {
if self.path.pop() {
Some(TreeType::EndTree)
} else {
// Check if we still have a path prefix open...
match self.path.components().next() {
Some(std::path::Component::Prefix(..)) => {
self.path = PathBuf::new();
Some(TreeType::EndTree)
}
_ => None,
}
None
}
}
Some((path, node, _)) => {
Expand All @@ -84,24 +74,25 @@ where
Some(TreeType::EndTree)
}
Ok(missing_dirs) => {
for comp in missing_dirs.components() {
self.path.push(comp);
// process next normal path component - other components are simply ignored
if let Some(p) = comp_to_osstr(comp).ok().flatten() {
if node.is_dir() && path == &self.path {
let (path, node, _) = self.item.take().unwrap();
self.item = self.iter.next();
let name = node.name();
return Some(TreeType::NewTree((path, node, name)));
}
// Use mode 755 for missing dirs, so they can be accessed
let meta = Metadata {
mode: Some(0o755),
..Default::default()
};
let node = Node::new_node(&p, NodeType::Dir, meta);
return Some(TreeType::NewTree((self.path.clone(), node, p)));
if let Some(p) = missing_dirs.components().next() {
self.path.push(p);
if node.is_dir() && path == &self.path {
let (path, node, _) = self.item.take().unwrap();
self.item = self.iter.next();
let name = node.name().to_vec();
return Some(TreeType::NewTree((path, node, name)));
}
// Use mode 755 for missing dirs, so they can be accessed
let meta = Metadata {
mode: Some(0o755),
..Default::default()
};
let node = Node::new_node(p.as_bytes(), NodeType::Dir, meta);
return Some(TreeType::NewTree((
self.path.clone(),
node,
p.as_bytes().to_vec(),
)));
}
// there wasn't any normal path component to process - return current item
let item = self.item.take().unwrap();
Expand Down
15 changes: 9 additions & 6 deletions crates/core/src/archiver/tree_archiver.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::path::{Path, PathBuf};

use bytesize::ByteSize;
use log::{debug, trace};
use typed_path::{UnixPath, UnixPathBuf};

use crate::{
archiver::{parent::ParentResult, tree::TreeType},
Expand Down Expand Up @@ -30,7 +29,7 @@ pub(crate) struct TreeArchiver<'a, BE: DecryptWriteBackend, I: ReadGlobalIndex>
/// The current tree.
tree: Tree,
/// The stack of trees.
stack: Vec<(PathBuf, Node, ParentResult<TreeId>, Tree)>,
stack: Vec<(UnixPathBuf, Node, ParentResult<TreeId>, Tree)>,
/// The index to read from.
index: &'a I,
/// The packer to write to.
Expand Down Expand Up @@ -129,7 +128,7 @@ impl<'a, BE: DecryptWriteBackend, I: ReadGlobalIndex> TreeArchiver<'a, BE, I> {
/// * `path` - The path of the file.
/// * `node` - The node of the file.
/// * `parent` - The parent result of the file.
fn add_file(&mut self, path: &Path, node: Node, parent: &ParentResult<()>, size: u64) {
fn add_file(&mut self, path: &UnixPath, node: Node, parent: &ParentResult<()>, size: u64) {
let filename = path.join(node.name());
match parent {
ParentResult::Matched(()) => {
Expand Down Expand Up @@ -164,7 +163,11 @@ impl<'a, BE: DecryptWriteBackend, I: ReadGlobalIndex> TreeArchiver<'a, BE, I> {
/// # Returns
///
/// The id of the tree.
fn backup_tree(&mut self, path: &Path, parent: &ParentResult<TreeId>) -> RusticResult<TreeId> {
fn backup_tree(
&mut self,
path: &UnixPath,
parent: &ParentResult<TreeId>,
) -> RusticResult<TreeId> {
let (chunk, id) = self.tree.serialize().map_err(|err| {
RusticError::with_source(
ErrorKind::Internal,
Expand Down Expand Up @@ -224,7 +227,7 @@ impl<'a, BE: DecryptWriteBackend, I: ReadGlobalIndex> TreeArchiver<'a, BE, I> {
parent_tree: Option<TreeId>,
) -> RusticResult<(TreeId, SnapshotSummary)> {
let parent = parent_tree.map_or(ParentResult::NotFound, ParentResult::Matched);
let id = self.backup_tree(&PathBuf::new(), &parent)?;
let id = self.backup_tree(UnixPath::new(&[]), &parent)?;
let stats = self.tree_packer.finalize()?;
stats.apply(&mut self.summary, BlobType::Tree);

Expand Down
14 changes: 8 additions & 6 deletions crates/core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use log::trace;
use mockall::mock;

use serde_derive::{Deserialize, Serialize};
use typed_path::UnixPathBuf;

use crate::{
backend::node::{Metadata, Node, NodeType},
Expand All @@ -31,8 +32,8 @@ use crate::{
#[derive(thiserror::Error, Debug, displaydoc::Display)]
#[non_exhaustive]
pub enum BackendErrorKind {
/// Path is not allowed: `{0:?}`
PathNotAllowed(PathBuf),
/// Path is not allowed: `{0}`
PathNotAllowed(String),
}

pub(crate) type BackendResult<T> = Result<T, BackendErrorKind>;
Expand Down Expand Up @@ -416,7 +417,7 @@ impl std::fmt::Debug for dyn WriteBackend {
#[derive(Debug, Clone)]
pub struct ReadSourceEntry<O> {
/// The path of the entry.
pub path: PathBuf,
pub path: UnixPathBuf,

/// The node information of the entry.
pub node: Node,
Expand All @@ -426,10 +427,11 @@ pub struct ReadSourceEntry<O> {
}

impl<O> ReadSourceEntry<O> {
fn from_path(path: PathBuf, open: Option<O>) -> BackendResult<Self> {
fn from_path(path: UnixPathBuf, open: Option<O>) -> BackendResult<Self> {
let node = Node::new_node(
path.file_name()
.ok_or_else(|| BackendErrorKind::PathNotAllowed(path.clone()))?,
path.file_name().ok_or_else(|| {
BackendErrorKind::PathNotAllowed(path.to_string_lossy().to_string())
})?,
NodeType::File,
Metadata::default(),
);
Expand Down
9 changes: 5 additions & 4 deletions crates/core/src/backend/childstdout.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{
iter::{once, Once},
path::PathBuf,
process::{Child, ChildStdout, Command, Stdio},
sync::Mutex,
};

use typed_path::UnixPathBuf;

use crate::{
backend::{ReadSource, ReadSourceEntry},
error::{ErrorKind, RusticError, RusticResult},
Expand All @@ -15,7 +16,7 @@ use crate::{
#[derive(Debug)]
pub struct ChildStdoutSource {
/// The path of the stdin entry.
path: PathBuf,
path: UnixPathBuf,
/// The child process
///
/// # Note
Expand All @@ -30,14 +31,14 @@ pub struct ChildStdoutSource {

impl ChildStdoutSource {
/// Creates a new `ChildSource`.
pub fn new(cmd: &CommandInput, path: PathBuf) -> RusticResult<Self> {
pub fn new(cmd: &CommandInput, path: UnixPathBuf) -> RusticResult<Self> {
let process = Command::new(cmd.command())
.args(cmd.args())
.stdout(Stdio::piped())
.spawn()
.map_err(|err| CommandInputErrorKind::ProcessExecutionFailed {
command: cmd.clone(),
path: path.clone(),
path: path.to_string_lossy().to_string(),
source: err,
});

Expand Down
Loading

0 comments on commit dbc9dab

Please sign in to comment.