| Crates.io | heroforge |
| lib.rs | heroforge |
| version | 0.2.1 |
| created_at | 2025-12-16 21:06:45.981333+00 |
| updated_at | 2025-12-17 06:39:29.977491+00 |
| description | Pure Rust client library for reading and writing Fossil SCM repositories |
| homepage | https://github.com/herocode/heroforge |
| repository | https://github.com/herocode/heroforge |
| max_upload_size | |
| id | 1988735 |
| size | 475,981 |
heroforge provides a complete API for interacting with Heroforge repositories programmatically, without requiring the Heroforge CLI to be installed. It supports both reading from existing repositories and creating new ones from scratch.
sync-quic feature)Add heroforge to your Cargo.toml:
[dependencies]
heroforge = "0.1"
Enable QUIC sync for remote repository synchronization:
[dependencies]
heroforge = { version = "0.1", features = ["sync-quic"] }
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
// Open a Heroforge repository
let repo = Repository::open("project.heroforge")?;
// Get the latest check-in on trunk
let tip = repo.history().trunk_tip()?;
println!("Latest: {} by {}", tip.hash, tip.user);
println!("Comment: {}", tip.comment);
// List all files on trunk
let files = repo.files().on_trunk().list()?;
for file in &files {
println!(" {}", file.name);
}
// Read a specific file from trunk
let content = repo.files().on_trunk().read("README.md")?;
println!("README:\n{}", String::from_utf8_lossy(&content));
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
// Create a new repository
let repo = Repository::init("new_project.heroforge")?;
// Create initial check-in
let init_hash = repo.commit_builder()
.message("initial empty check-in")
.author("admin")
.initial()
.execute()?;
// Add some files in a new commit
let commit_hash = repo.commit_builder()
.message("Initial project structure")
.author("developer")
.parent(&init_hash)
.file("README.md", b"# My Project\n")
.file("src/main.rs", b"fn main() { println!(\"Hello!\"); }\n")
.execute()?;
// Tag the release
repo.tags()
.create("v1.0.0")
.at_commit(&commit_hash)
.author("developer")
.execute()?;
// Create a feature branch
repo.branches()
.create("feature-x")
.from_commit(&commit_hash)
.author("developer")
.execute()?;
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.heroforge")?;
// Find all Rust files on trunk
let rust_files = repo.files().on_trunk().find("**/*.rs")?;
for file in rust_files {
println!("Found: {}", file.name);
}
// Find files in a specific directory on a branch
let src_files = repo.files().on_branch("feature-x").find("src/**/*")?;
// Find files at a specific tag
let tagged_files = repo.files().at_tag("v1.0.0").find("*.md")?;
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.heroforge")?;
// Get recent check-ins
let history = repo.history().recent(10)?;
for checkin in history {
println!("{} | {} | {}",
&checkin.hash[..12],
checkin.user,
checkin.comment
);
}
// List all branches
let branches = repo.branches().list()?;
for branch in branches {
println!("Branch: {}", branch);
}
// List all tags
let tags = repo.tags().list()?;
for tag in tags {
println!("Tag: {}", tag);
}
// Get the tip of a specific branch
let feature_tip = repo.history().branch_tip("feature-x")?;
println!("Feature branch tip: {}", feature_tip.hash);
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::init("project.heroforge")?;
// Create a new user
repo.users()
.create("developer")
.password("secret123")
.capabilities("ei") // edit + check-in
.execute()?;
// List all users
let users = repo.users().list()?;
for (login, caps) in users {
println!("User: {} ({})", login, caps);
}
// Get user capabilities
if let Some(caps) = repo.users().get_capabilities("developer")? {
println!("Developer capabilities: {}", caps);
}
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open("project.heroforge")?;
// Sync with a remote repository over QUIC
repo.sync()
.url("quic://heroforge.example.com:4443/repo")
.execute()?;
Ok(())
}
use heroforge::Repository;
fn main() -> heroforge::Result<()> {
let repo = Repository::open_rw("project.heroforge")?;
// Copy, move, delete files atomically
let hash = repo.fs().modify()
.message("Reorganize project")
.author("developer")
.copy_file("README.md", "docs/README.md")
.move_dir("scripts", "tools")
.delete_file("old_config.txt")
.make_executable("tools/build.sh")
.symlink("build", "tools/build.sh")
.execute()?;
// Advanced find with ignore patterns
let files = repo.fs().find()
.pattern("**/*.rs")
.ignore("target/**")
.ignore_hidden()
.max_depth(3)
.paths()?;
// Utility functions
println!("Exists: {}", repo.fs().exists("README.md")?);
println!("Is dir: {}", repo.fs().is_dir("src")?);
println!("Total size: {} bytes", repo.fs().du("**/*.rs")?);
Ok(())
}
The library uses a fluent builder pattern for all operations:
| Builder | Entry Point | Purpose |
|---|---|---|
FilesBuilder |
repo.files() |
Read files, list directories, find with glob patterns |
CommitBuilder |
repo.commit_builder() |
Create new check-ins with files |
BranchesBuilder |
repo.branches() |
List and create branches |
TagsBuilder |
repo.tags() |
List, create, and resolve tags |
HistoryBuilder |
repo.history() |
Browse commits and history |
UsersBuilder |
repo.users() |
Manage repository users |
SyncBuilder |
repo.sync() |
Synchronize with remote repositories (QUIC) |
FsOpsBuilder |
repo.fs() |
Filesystem operations (copy, move, delete, chmod, find, symlinks) |
Cargo.toml:[dependencies]
heroforge = "0.1"
use heroforge::{Repository, Result, FossilError};
fn main() -> Result<()> {
let repo = Repository::open("my-repo.heroforge")?;
// ... your code
Ok(())
}
use heroforge::Repository;
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} <repository.heroforge>", args[0]);
std::process::exit(1);
}
match Repository::open(&args[1]) {
Ok(repo) => {
match repo.history().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),
}
}
Repositories created with heroforge are fully compatible with the Heroforge CLI:
heroforge ui to browse repositories created by this libraryheroforge can read repositories created by the Heroforge CLI| Feature | Description | Dependencies |
|---|---|---|
sync-quic |
QUIC protocol sync | quinn, rustls, tokio |
The repository includes many examples demonstrating various features:
# Basic repository reading
cargo run --example read_repo
# Find files with glob patterns
cargo run --example find_and_read
# Branches and tags demonstration
cargo run --example branch_tag_test
# Comprehensive API demo
cargo run --example comprehensive_test
# Filesystem operations (copy, move, delete, chmod, symlinks)
cargo run --example fs_operations
# Advanced find with ignore patterns
cargo run --example fs_find
# QUIC sync (requires sync-quic feature)
cargo run --example quic_incremental_sync_test --features sync-quic
Full API documentation is available at docs.rs/heroforge.
Generate local documentation with:
cargo doc --open --all-features
A Heroforge repository is a SQLite database containing: