fs_tree/
lib.rs

1//! [`FsTree`] is a path [Trie] with an API focused on filesystem operations.
2//!
3//! # Clarifications:
4//!
5//! 1. _Unix_ only.
6//! 2. This crate was transfered after `0.1.3`, and changed its purpose.
7//! 3. This crate refers to _"filesystem tree"_ as the result you get from recursively traversing files:
8//!     - If you try traversing a single file, you get a single node.
9//!     - If you try traversing a directories, you might get a large subtree (of nodes).
10//!     - This is agnostic to the underlying filesystem (nothing to do with `ext4` or `btrfs`).
11//! 4. Check [Trie] if you both haven't met yet.
12//!
13//! # Tree Layout:
14//!
15//! A `FsTree` is a node with three possible file types:
16//!
17//! ```
18//! use std::{collections::BTreeMap, path::PathBuf};
19//!
20//! pub enum FsTree {
21//!     Regular,
22//!     Directory(TrieMap), // Recursive part
23//!     Symlink(PathBuf),
24//! }
25//! //                                     ↓↓
26//! pub type TrieMap = BTreeMap<PathBuf, FsTree>; // Recursive part
27//! ```
28//!
29//! The root of the `FsTree` is **unnamed** (no filename/path), the "edges" to children are the
30//! relative paths.
31//!
32//! # Pitfall warning:
33//!
34//! Like `std` functions, functions in this crate follow symlinks (and symlink chains), so you'll
35//! never get a [`FsTree::Symlink(_)`] in your tree! If you want symlink-awareness, use the function
36//! version with the `symlink` prefix ([`FsTree::read_at`] vs [`FsTree::symlink_read_at`]).
37//!
38//! # Ways to construct a [`FsTree`]:
39//!
40//! 1. Read node/tree from path. ([`FsTree::symlink_read_at`])
41//! 2. Declare a `FsTree` literal. ([`tree!`])
42//! 3. Insert each node in an empty folder. ([`FsTree::new_dir`] + [`FsTree::insert`])
43//! 4. Parse from path text segments. ([`FsTree::from_path_text`])
44//!
45//! # What you can do with a [`FsTree`]:
46//!
47//! 1. Traverse, query, and modify it.
48//! 2. Merge with another tree. ([`FsTree::merge`])
49//! 3. Write it to disk. ([`FsTree::write_at`])
50//! 4. Try loading a structural copy of it from a path. ([`FsTree::read_structure_at`])
51//! 5. (TODO) Compare with another `FsTree`, generating a DiffTree.
52//! 6. (TODO) Add entry API.
53//!
54//! ## Iterators:
55//!
56//! See docs in the [`iter` module].
57//!
58//! # Alternatives:
59//! - Crate [`walkdir`](https://docs.rs/walkdir) - Better if you just need to iterate on
60//!   filesystem trees.
61//! - Crate [`file_type_enum`](https://docs.rs/file_type_enum) - If you want a shallow type enum.
62//! - Crate [`build-fs-tree`](https://crates.io/crates/build-fs-tree) - If you need to create a
63//!   filesystem tree from a YAML file.
64//!     - The closest we got is creating a tree literal with [`tree!`](crate::tree), and writing
65//!       with [`FsTree::write_at`].
66//!
67//! [Trie]: https://en.wikipedia.org/wiki/Trie
68//! [`FsTree::Symlink(_)`]: https://docs.rs/fs-tree/latest/fs_tree/enum.FsTree.html#variant.Symlink
69//! [`iter` module]: crate::iter
70
71#![warn(missing_docs)]
72// Emits false-positives on macros.
73#![allow(clippy::vec_init_then_push)]
74
75/// [`FsTree`] iterators.
76pub mod iter;
77
78pub use self::{
79    error::{Error, Result},
80    fs_tree::{FsTree, TrieMap},
81};
82
83mod error;
84mod fs_tree;
85mod macros;
86pub(crate) mod utils;