heroforge-core 0.2.2

Pure Rust core library for reading and writing Fossil SCM repositories
Documentation
//! # Filesystem Interface
//!
//! This module provides a clean, high-level filesystem abstraction for Heroforge repositories.
//! It hides the complexity of SQLite-backed storage and provides a familiar filesystem-like API.
//!
//! ## Architecture Overview
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────┐
//! │                      FsInterface (sync API)                     │
//! │  - RwLock<StagingState>                                         │
//! │  - Author name (set at initialization)                          │
//! │  - All read/write operations acquire appropriate locks          │
//! └─────────────────────────────────────────────────────────────────┘
//!//!           ┌───────────────────┴───────────────────┐
//!           │                                       │
//!           ▼                                       ▼
//! ┌─────────────────────┐                 ┌─────────────────────────┐
//! │   Staging Directory │                 │    Commit Thread        │
//! │                     │                 │    (background)         │
//! │  - All writes go    │                 │                         │
//! │    here first       │                 │  - Runs every 1 minute  │
//! │  - Files < 2MB      │                 │  - Acquires write lock  │
//! │  - Frequent updates │                 │  - Blocks all I/O       │
//! │    allowed          │                 │  - Flushes to .forge DB │
//! │                     │                 │  - Clears staging dir   │
//! └─────────────────────┘                 └─────────────────────────┘
//!           │                                       │
//!           └───────────────────┬───────────────────┘
//!//!//!                     ┌─────────────────────┐
//!                     │   .forge Database   │
//!                     │      (SQLite)       │
//!                     └─────────────────────┘
//! ```
//!
//! ## Quick Start with FsInterface (Recommended)
//!
//! The `FsInterface` provides staging-based writes with automatic background commits:
//!
//! ```no_run
//! use heroforge_core::Repository;
//! use std::sync::Arc;
//!
//! fn main() -> heroforge_core::Result<()> {
//!     let repo = Arc::new(Repository::open_rw("project.forge")?);
//!     let fs = heroforge_core::fs::FsInterface::new(repo, "developer@example.com")?;
//!
//!     // Writes go to staging (fast)
//!     fs.write_file("config.json", b"{}")?;
//!
//!     // Reads check staging first, then database
//!     let content = fs.read_file("config.json")?;
//!
//!     // Partial updates use read-modify-write pattern
//!     fs.write_at("data.bin", 100, b"updated")?;
//!
//!     // Force immediate commit (normally auto-commits every 1 minute)
//!     fs.commit()?;
//!
//!     Ok(())
//! }
//! ```
//!
//! ## Legacy FileSystem API
//!
//! The original `FileSystem` API is still available for direct database operations:
//!
//! ```no_run
//! use heroforge_core::Repository;
//! use heroforge_core::fs::FileSystem;
//! use std::sync::Arc;
//!
//! fn main() -> heroforge_core::Result<()> {
//!     let repo = Arc::new(Repository::open_rw("project.forge")?);
//!     let fs = FileSystem::new(repo);
//!
//!     // Direct database operations (no staging)
//!     fs.write_file("config.json", b"{}", "developer", "Add config")?;
//!
//!     Ok(())
//! }
//! ```
//!
//! ## Staging Directory
//!
//! All write operations go to a **staging directory** first, not directly to SQLite:
//!
//! 1. **Fast writes**: Writing to filesystem is faster than SQLite transactions
//! 2. **Frequent updates**: Files can be modified many times before commit
//! 3. **Atomic commits**: All staged changes are committed together
//! 4. **Crash recovery**: Uncommitted work is recoverable from staging
//!
//! **Current Limitations:**
//! - Files larger than **2 MB** are not supported
//! - Staging directory is local to the repository
//!
//! ## Read Path (Layered Lookup)
//!
//! When reading a file, the interface checks locations in this order:
//!
//! 1. **Staging Directory** → If file exists here, return it (most recent)
//! 2. **`.forge` Database** → Query SQLite for committed version
//! 3. **Return Error** → File does not exist
//!
//! ## Auto-Commit Behavior
//!
//! - Commits happen automatically every **1 minute**
//! - During commit, an **exclusive write lock** is held
//! - All operations are blocked during commit (typically milliseconds)
//! - Forced commits happen on: branch change, tag creation, shutdown
//!
//! ## Thread Safety
//!
//! Uses `RwLock<StagingState>` for concurrent access:
//!
//! | Operation | Lock Type | Blocks |
//! |-----------|-----------|--------|
//! | `exists()` | Read | Nothing |
//! | `read_file()` | Read | Nothing |
//! | `write_file()` | Write | Other writes |
//! | `delete_file()` | Write | Other writes |
//! | **Commit** | **Exclusive** | **Everything** |
//!
//! ## Error Handling
//!
//! All operations return `FsResult<T>` which is `Result<T, FsError>`:
//!
//! ```no_run
//! # use heroforge_core::Repository;
//! # use std::sync::Arc;
//! let repo = Arc::new(Repository::open_rw("repo.forge")?);
//! let fs = heroforge_core::fs::FsInterface::new(repo, "user")?;
//!
//! match fs.read_file("missing.txt") {
//!     Ok(content) => println!("Read {} bytes", content.len()),
//!     Err(err) => eprintln!("Error: {}", err),
//! }
//! # Ok::<(), heroforge_core::FossilError>(())
//! ```

pub mod commit_thread;
pub mod errors;
pub mod find;
pub mod fs_interface;
pub mod interface;
pub mod operations;
pub mod ops;
pub mod staging;
pub mod transaction;

pub use errors::{FsError, FsResult};
pub use interface::{FileHandle, FileSystem, FileSystemStatus};
pub use operations::{
    DirectoryEntry, FileKind, FileMetadata, FilePermissions, FindResults, FsOperation,
    OperationSummary,
};
pub use transaction::{SavePoint, Transaction, TransactionMode, TransactionState};

// New staging-based interface
pub use commit_thread::{CommitConfig, CommitWorker, DEFAULT_COMMIT_INTERVAL};
pub use fs_interface::{FsInterface, FsInterfaceStatus};
pub use staging::{MAX_FILE_SIZE, StagedFile, Staging, StagingState};

// Find and high-level operations
pub use find::{
    FileEntry, FileType, Find, FindResult, Permissions, count, du, exists, find, is_dir,
    list_symlinks, stat,
};
pub use ops::{Modify, Op, Preview};

// Upload/Download (OS filesystem <-> .forge database)
pub use ops::{
    download, download_dir, download_from_branch, download_matching, upload, upload_dir,
};

/// Filesystem interface version
pub const VERSION: &str = "1.0.0";

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_version() {
        assert_eq!(VERSION, "1.0.0");
    }
}