Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 6 additions & 40 deletions cli/src/cmd/init.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};

use agentfs_sdk::{agentfs_dir, AgentFS, AgentFSOptions};
use agentfs_sdk::{agentfs_dir, AgentFS, AgentFSOptions, OverlayFS};
use anyhow::{Context, Result as AnyhowResult};

pub async fn init_database(
Expand Down Expand Up @@ -63,52 +63,18 @@ pub async fn init_database(
.await
.context("Failed to initialize database")?;

// If base is provided, store the overlay configuration
// If base is provided, initialize the overlay schema using the SDK
if let Some(base_path) = base {
let conn = agent.get_connection();

// Create whiteout table for overlay support
conn.execute(
"CREATE TABLE IF NOT EXISTS fs_whiteout (
path TEXT PRIMARY KEY,
created_at INTEGER NOT NULL
)",
(),
)
.await
.context("Failed to create whiteout table")?;

// Create overlay config table
conn.execute(
"CREATE TABLE IF NOT EXISTS fs_overlay_config (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
)",
(),
)
.await
.context("Failed to create overlay config table")?;

// Store base path configuration
let base_path_str = base_path
.canonicalize()
.context("Failed to canonicalize base path")?
.to_string_lossy()
.to_string();

conn.execute(
"INSERT INTO fs_overlay_config (key, value) VALUES ('base_type', 'hostfs')",
(),
)
.await
.context("Failed to store base type")?;

conn.execute(
"INSERT INTO fs_overlay_config (key, value) VALUES ('base_path', ?)",
(base_path_str.as_str(),),
)
.await
.context("Failed to store base path")?;
// Use SDK's OverlayFS::init_schema to ensure schema consistency
OverlayFS::init_schema(&agent.get_connection(), &base_path_str)
.await
.context("Failed to initialize overlay schema")?;

eprintln!("Created overlay filesystem: {}", db_path.display());
eprintln!("Agent ID: {}", id);
Expand Down
23 changes: 17 additions & 6 deletions sdk/rust/src/filesystem/overlayfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};
use turso::Value;
use turso::{Connection, Value};

use super::{agentfs::AgentFS, DirEntry, FileSystem, FilesystemStats, FsError, Stats};

Expand Down Expand Up @@ -38,16 +38,15 @@ impl OverlayFS {
Self { base, delta }
}

/// Initialize the overlay filesystem schema (creates whiteout table)
/// Initialize the overlay filesystem schema in a database.
///
/// This must be called before using the overlay filesystem to ensure
/// the whiteout tracking table exists in the delta layer.
/// This is a static method that can be called without creating an OverlayFS
/// instance, useful for CLI tools that need to initialize an overlay database.
///
/// The `base_path` parameter specifies the actual filesystem path that the
/// base layer represents. This is stored in the delta database so that
/// tools like `agentfs diff` can determine what files were modified.
pub async fn init(&self, base_path: &str) -> Result<()> {
let conn = self.delta.get_connection();
pub async fn init_schema(conn: &Connection, base_path: &str) -> Result<()> {
conn.execute(
"CREATE TABLE IF NOT EXISTS fs_whiteout (
path TEXT PRIMARY KEY,
Expand Down Expand Up @@ -80,6 +79,18 @@ impl OverlayFS {
Ok(())
}

/// Initialize the overlay filesystem schema (creates whiteout table)
///
/// This must be called before using the overlay filesystem to ensure
/// the whiteout tracking table exists in the delta layer.
///
/// The `base_path` parameter specifies the actual filesystem path that the
/// base layer represents. This is stored in the delta database so that
/// tools like `agentfs diff` can determine what files were modified.
pub async fn init(&self, base_path: &str) -> Result<()> {
Self::init_schema(&self.delta.get_connection(), base_path).await
}

/// Extract the parent path from a normalized path
fn parent_path(path: &str) -> String {
if path == "/" {
Expand Down