# heroforge
A pure Rust client library for reading and writing [Fossil SCM](https://fossil-scm.org/) repositories.
[](https://crates.io/crates/heroforge)
[](https://docs.rs/heroforge)
[](LICENSE)
## Overview
`heroforge` provides a complete API for interacting with Fossil repositories programmatically, without requiring the Fossil CLI to be installed. It supports both reading from existing repositories and creating new ones from scratch.
## Features
### Read Operations
- Open and read existing Fossil repositories
- Browse repository history and check-ins
- List and read files at any check-in
- Find files using glob patterns
- Navigate directory structures
- Access branch and tag information
### Write Operations
- Create new repositories from scratch
- Commit files with full manifest generation
- Create and manage branches
- Add tags to check-ins
- Manage users and permissions
### Synchronization (Optional Features)
- **HTTP sync** - Standard Fossil sync over HTTP/HTTPS
- **TCP sync** - Direct TCP connections with optional LZ4 compression
- **Encrypted sync** - ChaCha20-Poly1305 encryption for TCP
- **QUIC sync** - Modern UDP-based protocol with TLS 1.3
## Installation
Add `heroforge` to your `Cargo.toml`:
```toml
[dependencies]
heroforge = "0.1"
```
### Optional Features
Enable additional sync protocols as needed:
```toml
[dependencies]
# HTTP sync support
heroforge = { version = "0.1", features = ["sync-http"] }
# TCP sync with compression and encryption
heroforge = { version = "0.1", features = ["sync-tcp-full"] }
# QUIC sync (modern, fast)
heroforge = { version = "0.1", features = ["sync-quic"] }
# All features
heroforge = { version = "0.1", features = ["sync-http", "sync-tcp-full", "sync-quic"] }
```
## Quick Start
### Reading from an Existing Repository
```rust
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
// Open a Fossil repository
let repo = Repository::open("project.fossil")?;
// Get the latest check-in on trunk
let tip = repo.trunk_tip()?;
println!("Latest: {} by {}", tip.hash, tip.user);
println!("Comment: {}", tip.comment);
// List all files in the latest check-in
let files = repo.list_files(&tip.hash)?;
for file in &files {
println!(" {}", file.name);
}
// Read a specific file
let content = repo.read_file(&tip.hash, "README.md")?;
println!("README:\n{}", String::from_utf8_lossy(&content));
Ok(())
}
```
### Creating a New Repository
```rust
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
// Create a new repository
let repo = Repository::init("new_project.fossil")?;
// Create initial check-in
let init_hash = repo.create_initial_checkin("admin")?;
// Add some files
let files: Vec<(&str, &[u8])> = vec![
("README.md", b"# My Project\n"),
("src/main.rs", b"fn main() { println!(\"Hello!\"); }\n"),
];
let commit_hash = repo.commit(
&files,
"Initial project structure",
"developer",
Some(&init_hash),
None, // stays on trunk
)?;
// Tag the release
repo.add_tag("v1.0.0", &commit_hash, "developer")?;
// Create a feature branch
let branch_hash = repo.create_branch("feature-x", &commit_hash, "developer")?;
Ok(())
}
```
### Finding Files with Glob Patterns
```rust
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.fossil")?;
let tip = repo.trunk_tip()?;
// Find all Rust files
let rust_files = repo.find_files(&tip.hash, "**/*.rs")?;
for file in rust_files {
println!("Found: {}", file.name);
}
// Find files in a specific directory
let src_files = repo.find_files(&tip.hash, "src/**/*")?;
Ok(())
}
```
### Browsing History
```rust
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.fossil")?;
// Get recent check-ins
let history = repo.get_checkins(10)?;
for checkin in history {
println!("{} | {} | {}",
&checkin.hash[..12],
checkin.user,
checkin.comment
);
}
// List all branches
let branches = repo.list_branches()?;
for branch in branches {
println!("Branch: {}", branch);
}
// List all tags
let tags = repo.list_tags()?;
for tag in tags {
println!("Tag: {}", tag);
}
Ok(())
}
```
### HTTP Synchronization
```rust
use heroforge::Repository;
use heroforge::sync::HttpSyncClient;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.fossil")?;
// Create sync client
let client = HttpSyncClient::new(
"https://fossil.example.com/repo",
Some("username"),
Some("password"),
)?;
// Perform sync
client.sync(&repo)?;
Ok(())
}
```
## Using heroforge in Your Project
### As a Library Dependency
1. Add to your `Cargo.toml`:
```toml
[dependencies]
heroforge = "0.1"
```
2. Import and use:
```rust
use heroforge::{Repository, Result, FossilError};
fn main() -> Result<()> {
let repo = Repository::open("my-repo.fossil")?;
// ... your code
Ok(())
}
```
### Building a CLI Tool
```rust
use heroforge::Repository;
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} <repository.fossil>", args[0]);
std::process::exit(1);
}
match Repository::open(&args[1]) {
Ok(repo) => {
match repo.trunk_tip() {
Ok(tip) => {
println!("Repository: {}", args[1]);
println!("Latest commit: {}", tip.hash);
println!("Author: {}", tip.user);
println!("Message: {}", tip.comment);
}
Err(e) => eprintln!("Error reading tip: {}", e),
}
}
Err(e) => eprintln!("Error opening repository: {}", e),
}
}
```
## Repository Compatibility
Repositories created with `heroforge` are fully compatible with the Fossil CLI:
- Use `fossil ui` to browse repositories created by this library
- `heroforge` can read repositories created by the Fossil CLI
- Sync with remote Fossil servers works seamlessly
## Feature Flags
| `sync-http` | HTTP/HTTPS sync support | `ureq` |
| `sync-tcp` | Basic TCP sync | - |
| `sync-tcp-compression` | TCP with LZ4 compression | `lz4_flex` |
| `sync-tcp-encryption` | TCP with ChaCha20-Poly1305 | `chacha20poly1305`, `rand` |
| `sync-tcp-full` | All TCP features | compression + encryption |
| `sync-quic` | QUIC protocol sync | `quinn`, `rustls`, `tokio` |
## Examples
The repository includes many examples demonstrating various features:
```bash
# Basic repository reading
cargo run --example read_repo
# Find files with glob patterns
cargo run --example find_and_read
# Full demo with repository creation
cargo run --example full_demo
# HTTP sync (requires sync-http feature)
cargo run --example sync_demo --features sync-http
# TCP sync benchmark (requires sync-tcp-full feature)
cargo run --example tcp_sync_benchmark --features sync-tcp-full
# QUIC sync (requires sync-quic feature)
cargo run --example quic_sync_benchmark --features sync-quic
```
## Documentation
Full API documentation is available at [docs.rs/heroforge](https://docs.rs/heroforge).
Generate local documentation with:
```bash
cargo doc --open --all-features
```
## Architecture
A Fossil repository is a SQLite database containing:
- **Blobs**: Compressed file contents and manifests (zlib)
- **Manifests**: Check-in metadata with file lists, timestamps, comments
- **Tags**: Branch names, version tags, and other labels
- **Events**: Timeline of repository activity
- **Delta encoding**: Efficient storage of similar content
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.