diff --git a/crates/grite/Cargo.toml b/crates/grite/Cargo.toml index 8341d16..09507c3 100644 --- a/crates/grite/Cargo.toml +++ b/crates/grite/Cargo.toml @@ -17,6 +17,10 @@ authors.workspace = true name = "grite" path = "src/main.rs" +[features] +default = ["context"] +context = ["libgrite-core/context", "libgrite-cli/context", "libgrite-git/context"] + [dependencies] libgrite-core = { path = "../libgrite-core", version = "0.5.1" } libgrite-git = { path = "../libgrite-git", version = "0.5.1" } diff --git a/crates/grite/src/cli.rs b/crates/grite/src/cli.rs index 49f8d2d..11d4e85 100644 --- a/crates/grite/src/cli.rs +++ b/crates/grite/src/cli.rs @@ -114,6 +114,7 @@ pub enum Command { }, /// Context store management (file/symbol indexing) + #[cfg(feature = "context")] Context { #[command(subcommand)] cmd: ContextCommand, @@ -541,6 +542,7 @@ pub enum DepCommand { }, } +#[cfg(feature = "context")] #[derive(Clone, Subcommand)] pub enum ContextCommand { /// Index files in the repository diff --git a/crates/grite/src/commands/mod.rs b/crates/grite/src/commands/mod.rs index 9170e83..f5e9ea6 100644 --- a/crates/grite/src/commands/mod.rs +++ b/crates/grite/src/commands/mod.rs @@ -1,4 +1,5 @@ pub mod actor; +#[cfg(feature = "context")] pub mod context; pub mod daemon; pub mod db; diff --git a/crates/grite/src/main.rs b/crates/grite/src/main.rs index 1d1ee45..7747867 100644 --- a/crates/grite/src/main.rs +++ b/crates/grite/src/main.rs @@ -50,6 +50,7 @@ fn run_command(cli: &Cli) -> Result<(), GriteError> { Command::Daemon { cmd } => commands::daemon::run(cli, cmd.clone()), Command::Lock { cmd } => commands::lock::run(cli, cmd.clone()), Command::Doctor { fix } => commands::doctor::run(cli, *fix), + #[cfg(feature = "context")] Command::Context { cmd } => commands::context::run(cli, cmd.clone()), Command::InstallSkill { global, force } => { commands::install_skill::run(cli, *global, *force) diff --git a/crates/grite/src/router.rs b/crates/grite/src/router.rs index 7dc1b03..c93c743 100644 --- a/crates/grite/src/router.rs +++ b/crates/grite/src/router.rs @@ -107,6 +107,7 @@ pub fn should_route_through_daemon(cmd: &crate::cli::Command) -> bool { Command::Doctor { .. } => false, // Context commands are local-only (need filesystem access) + #[cfg(feature = "context")] Command::Context { .. } => false, // Install-skill is local-only @@ -150,8 +151,9 @@ pub fn cli_to_ipc_command(cmd: &crate::cli::Command) -> Option { | Command::Daemon { .. } | Command::Lock { .. } | Command::Doctor { .. } - | Command::Context { .. } | Command::InstallSkill { .. } => None, + #[cfg(feature = "context")] + Command::Context { .. } => None, } } diff --git a/crates/libgrite-cli/Cargo.toml b/crates/libgrite-cli/Cargo.toml index a91e897..ce4112e 100644 --- a/crates/libgrite-cli/Cargo.toml +++ b/crates/libgrite-cli/Cargo.toml @@ -14,8 +14,9 @@ readme = "README.md" authors.workspace = true [features] -default = [] +default = ["context"] async = ["dep:tokio"] +context = ["libgrite-core/context"] [dependencies] libgrite-core = { path = "../libgrite-core", version = "0.5.1" } diff --git a/crates/libgrite-cli/src/async_wrappers.rs b/crates/libgrite-cli/src/async_wrappers.rs index d317d44..e1201f0 100644 --- a/crates/libgrite-cli/src/async_wrappers.rs +++ b/crates/libgrite-cli/src/async_wrappers.rs @@ -140,6 +140,7 @@ pub async fn rebuild_async( } /// Async: index context. +#[cfg(feature = "context")] pub async fn context_index_async( ctx: &GriteContext, opts: ContextIndexOptions, diff --git a/crates/libgrite-cli/src/lib.rs b/crates/libgrite-cli/src/lib.rs index 24f5b2c..86e3598 100644 --- a/crates/libgrite-cli/src/lib.rs +++ b/crates/libgrite-cli/src/lib.rs @@ -9,6 +9,7 @@ pub mod actor; pub mod context; +#[cfg(feature = "context")] pub mod context_cmd; pub mod daemon; pub mod db; diff --git a/crates/libgrite-cli/src/types.rs b/crates/libgrite-cli/src/types.rs index 825f364..208a7a0 100644 --- a/crates/libgrite-cli/src/types.rs +++ b/crates/libgrite-cli/src/types.rs @@ -501,6 +501,7 @@ pub struct DoctorCheckResult { } /// Options for context index. +#[cfg(feature = "context")] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ContextIndexOptions { pub paths: Vec, @@ -509,6 +510,7 @@ pub struct ContextIndexOptions { } /// Result of context index. +#[cfg(feature = "context")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextIndexResult { pub indexed_files: usize, @@ -516,42 +518,49 @@ pub struct ContextIndexResult { } /// Options for context query. +#[cfg(feature = "context")] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ContextQueryOptions { pub query: String, } /// Result of context query. +#[cfg(feature = "context")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextQueryResult { pub symbols: Vec, } /// Options for context show. +#[cfg(feature = "context")] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ContextShowOptions { pub path: String, } /// Result of context show. +#[cfg(feature = "context")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextShowResult { pub file: libgrite_core::FileContext, } /// Options for context project. +#[cfg(feature = "context")] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ContextProjectOptions { pub key: Option, } /// Result of context project. +#[cfg(feature = "context")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextProjectResult { pub entries: Vec, } /// Options for context set. +#[cfg(feature = "context")] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ContextSetOptions { pub key: String, @@ -559,6 +568,7 @@ pub struct ContextSetOptions { } /// Result of context set. +#[cfg(feature = "context")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextSetResult { pub key: String, diff --git a/crates/libgrite-core/Cargo.toml b/crates/libgrite-core/Cargo.toml index faead8e..1602de5 100644 --- a/crates/libgrite-core/Cargo.toml +++ b/crates/libgrite-core/Cargo.toml @@ -13,6 +13,24 @@ description = "Core library for grite: event types, CRDT projections, hashing, a readme = "README.md" authors.workspace = true +[features] +default = ["context"] +context = [ + "dep:tree-sitter", + "dep:tree-sitter-language", + "dep:streaming-iterator", + "dep:tree-sitter-rust", + "dep:tree-sitter-python", + "dep:tree-sitter-typescript", + "dep:tree-sitter-javascript", + "dep:tree-sitter-go", + "dep:tree-sitter-java", + "dep:tree-sitter-c", + "dep:tree-sitter-cpp", + "dep:tree-sitter-ruby", + "dep:tree-sitter-elixir", +] + [dependencies] blake2 = { workspace = true } ciborium = { workspace = true } @@ -29,19 +47,19 @@ sha2 = { workspace = true } ed25519-dalek = { workspace = true } fs2 = { workspace = true } regex = { workspace = true } -tree-sitter = { workspace = true } -tree-sitter-language = { workspace = true } -streaming-iterator = { workspace = true } -tree-sitter-rust = { workspace = true } -tree-sitter-python = { workspace = true } -tree-sitter-typescript = { workspace = true } -tree-sitter-javascript = { workspace = true } -tree-sitter-go = { workspace = true } -tree-sitter-java = { workspace = true } -tree-sitter-c = { workspace = true } -tree-sitter-cpp = { workspace = true } -tree-sitter-ruby = { workspace = true } -tree-sitter-elixir = { workspace = true } +tree-sitter = { workspace = true, optional = true } +tree-sitter-language = { workspace = true, optional = true } +streaming-iterator = { workspace = true, optional = true } +tree-sitter-rust = { workspace = true, optional = true } +tree-sitter-python = { workspace = true, optional = true } +tree-sitter-typescript = { workspace = true, optional = true } +tree-sitter-javascript = { workspace = true, optional = true } +tree-sitter-go = { workspace = true, optional = true } +tree-sitter-java = { workspace = true, optional = true } +tree-sitter-c = { workspace = true, optional = true } +tree-sitter-cpp = { workspace = true, optional = true } +tree-sitter-ruby = { workspace = true, optional = true } +tree-sitter-elixir = { workspace = true, optional = true } [dev-dependencies] tempfile = "3.10" diff --git a/crates/libgrite-core/src/export.rs b/crates/libgrite-core/src/export.rs index ea4521d..f0f4001 100644 --- a/crates/libgrite-core/src/export.rs +++ b/crates/libgrite-core/src/export.rs @@ -174,6 +174,7 @@ fn event_kind_to_json(kind: &EventKind) -> serde_json::Value { } }) } + #[cfg(feature = "context")] EventKind::ContextUpdated { path, language, @@ -191,6 +192,7 @@ fn event_kind_to_json(kind: &EventKind) -> serde_json::Value { } }) } + #[cfg(feature = "context")] EventKind::ProjectContextUpdated { key, value } => { serde_json::json!({ "ProjectContextUpdated": { diff --git a/crates/libgrite-core/src/hash.rs b/crates/libgrite-core/src/hash.rs index 0a62474..fea0f28 100644 --- a/crates/libgrite-core/src/hash.rs +++ b/crates/libgrite-core/src/hash.rs @@ -127,6 +127,7 @@ pub fn kind_to_tag_and_payload(kind: &EventKind) -> (u32, ciborium::Value) { Value::Text(dep_type.as_str().to_string()), ]), ), + #[cfg(feature = "context")] EventKind::ContextUpdated { path, language, @@ -161,6 +162,7 @@ pub fn kind_to_tag_and_payload(kind: &EventKind) -> (u32, ciborium::Value) { ]), ) } + #[cfg(feature = "context")] EventKind::ProjectContextUpdated { key, value } => ( 14, Value::Array(vec![Value::Text(key.clone()), Value::Text(value.clone())]), @@ -497,6 +499,7 @@ mod tests { assert_ne!(id1, id_add); } + #[cfg(feature = "context")] #[test] fn test_vector_13_context_updated() { use crate::types::event::SymbolInfo; @@ -553,6 +556,7 @@ mod tests { assert_eq!(id1, id3, "Symbol order should not affect hash"); } + #[cfg(feature = "context")] #[test] fn test_vector_14_project_context_updated() { let issue_id: IssueId = hex_to_id("000102030405060708090a0b0c0d0e0f").unwrap(); diff --git a/crates/libgrite-core/src/lib.rs b/crates/libgrite-core/src/lib.rs index fd72153..f27fcb6 100644 --- a/crates/libgrite-core/src/lib.rs +++ b/crates/libgrite-core/src/lib.rs @@ -22,6 +22,7 @@ //! - **Append-only** for comments, links, attachments pub mod config; +#[cfg(feature = "context")] pub mod context; pub mod error; pub mod export; @@ -47,8 +48,11 @@ pub use lock::{resource_hash, Lock, LockCheckResult, LockPolicy, LockStatus, DEF pub use signing::{verify_signature, SigningError, SigningKeyPair, VerificationPolicy}; pub use store::{DbStats, GriteStore, IssueFilter, LockedStore, RebuildStats}; pub use types::actor::ActorConfig; +#[cfg(feature = "context")] pub use types::context::{FileContext, ProjectContext, ProjectContextEntry}; -pub use types::event::{DependencyType, Event, EventKind, IssueState, SymbolInfo}; +#[cfg(feature = "context")] +pub use types::event::SymbolInfo; +pub use types::event::{DependencyType, Event, EventKind, IssueState}; pub use types::ids::{generate_actor_id, generate_issue_id, hex_to_id, id_to_hex}; pub use types::issue::{IssueProjection, IssueSummary, Version}; pub use types::{ActorId, EventId, IssueId}; diff --git a/crates/libgrite-core/src/projection.rs b/crates/libgrite-core/src/projection.rs index 7fe04fb..8c57aa5 100644 --- a/crates/libgrite-core/src/projection.rs +++ b/crates/libgrite-core/src/projection.rs @@ -105,6 +105,7 @@ impl IssueProjection { }); } + #[cfg(feature = "context")] EventKind::ContextUpdated { .. } | EventKind::ProjectContextUpdated { .. } => { // Context events are handled by the context store, not issue projections return Ok(()); diff --git a/crates/libgrite-core/src/store/mod.rs b/crates/libgrite-core/src/store/mod.rs index f52364c..22993d3 100644 --- a/crates/libgrite-core/src/store/mod.rs +++ b/crates/libgrite-core/src/store/mod.rs @@ -6,12 +6,11 @@ use std::time::{Duration, Instant}; use fs2::FileExt; use crate::error::GriteError; +#[cfg(feature = "context")] use crate::types::context::{FileContext, ProjectContextEntry}; -use crate::types::event::IssueState; -use crate::types::event::{DependencyType, Event, EventKind}; +use crate::types::event::{DependencyType, Event, EventKind, IssueState}; use crate::types::ids::{EventId, IssueId}; -use crate::types::issue::Version; -use crate::types::issue::{IssueProjection, IssueSummary}; +use crate::types::issue::{IssueProjection, IssueSummary, Version}; /// Default threshold for events since rebuild before recommending rebuild pub const DEFAULT_REBUILD_EVENTS_THRESHOLD: usize = 10000; @@ -100,8 +99,11 @@ pub struct GriteStore { metadata: sled::Tree, dep_forward: sled::Tree, dep_reverse: sled::Tree, + #[cfg(feature = "context")] context_files: sled::Tree, + #[cfg(feature = "context")] context_symbols: sled::Tree, + #[cfg(feature = "context")] context_project: sled::Tree, } @@ -116,8 +118,11 @@ impl GriteStore { let metadata = db.open_tree("metadata")?; let dep_forward = db.open_tree("dep_forward")?; let dep_reverse = db.open_tree("dep_reverse")?; + #[cfg(feature = "context")] let context_files = db.open_tree("context_files")?; + #[cfg(feature = "context")] let context_symbols = db.open_tree("context_symbols")?; + #[cfg(feature = "context")] let context_project = db.open_tree("context_project")?; Ok(Self { @@ -129,8 +134,11 @@ impl GriteStore { metadata, dep_forward, dep_reverse, + #[cfg(feature = "context")] context_files, + #[cfg(feature = "context")] context_symbols, + #[cfg(feature = "context")] context_project, }) } @@ -233,6 +241,7 @@ impl GriteStore { /// Update the issue projection for an event fn update_projection(&self, event: &Event) -> Result<(), GriteError> { // Handle context events separately (they don't have issue projections) + #[cfg(feature = "context")] match &event.kind { EventKind::ContextUpdated { path, @@ -302,6 +311,7 @@ impl GriteStore { } /// Update file context (LWW per path) + #[cfg(feature = "context")] fn update_file_context( &self, event: &Event, @@ -358,6 +368,7 @@ impl GriteStore { } /// Update project context (LWW per key) + #[cfg(feature = "context")] fn update_project_context( &self, event: &Event, @@ -549,8 +560,11 @@ impl GriteStore { self.label_index.clear()?; self.dep_forward.clear()?; self.dep_reverse.clear()?; + #[cfg(feature = "context")] self.context_files.clear()?; + #[cfg(feature = "context")] self.context_symbols.clear()?; + #[cfg(feature = "context")] self.context_project.clear()?; // Collect all events @@ -599,8 +613,11 @@ impl GriteStore { self.label_index.clear()?; self.dep_forward.clear()?; self.dep_reverse.clear()?; + #[cfg(feature = "context")] self.context_files.clear()?; + #[cfg(feature = "context")] self.context_symbols.clear()?; + #[cfg(feature = "context")] self.context_project.clear()?; self.events.clear()?; @@ -838,6 +855,7 @@ impl GriteStore { // --- Context Query Methods --- /// Get file context for a specific path + #[cfg(feature = "context")] pub fn get_file_context(&self, path: &str) -> Result, GriteError> { let key = context_file_key(path); match self.context_files.get(&key)? { @@ -847,6 +865,7 @@ impl GriteStore { } /// Query symbols by name prefix + #[cfg(feature = "context")] pub fn query_symbols(&self, query: &str) -> Result, GriteError> { let prefix = context_symbol_prefix(query); let mut results = Vec::new(); @@ -869,6 +888,7 @@ impl GriteStore { } /// List all indexed file paths + #[cfg(feature = "context")] pub fn list_context_files(&self) -> Result, GriteError> { let mut paths = Vec::new(); for result in self.context_files.iter() { @@ -883,6 +903,7 @@ impl GriteStore { } /// Get a project context entry by key + #[cfg(feature = "context")] pub fn get_project_context( &self, key: &str, @@ -895,6 +916,7 @@ impl GriteStore { } /// List all project context entries + #[cfg(feature = "context")] pub fn list_project_context(&self) -> Result, GriteError> { let mut entries = Vec::new(); for result in self.context_project.iter() { @@ -1024,6 +1046,7 @@ fn parse_dep_key_suffix(key: &[u8], prefix_len: usize) -> Option<(IssueId, Depen // Context key helpers +#[cfg(feature = "context")] fn context_file_key(path: &str) -> Vec { let mut key = Vec::new(); key.extend_from_slice(b"ctx/file/"); @@ -1031,6 +1054,7 @@ fn context_file_key(path: &str) -> Vec { key } +#[cfg(feature = "context")] fn context_symbol_prefix(name: &str) -> Vec { let mut key = Vec::new(); key.extend_from_slice(b"ctx/sym/"); @@ -1038,6 +1062,7 @@ fn context_symbol_prefix(name: &str) -> Vec { key } +#[cfg(feature = "context")] fn context_symbol_key(name: &str, path: &str) -> Vec { let mut key = context_symbol_prefix(name); key.push(b'/'); @@ -1045,6 +1070,7 @@ fn context_symbol_key(name: &str, path: &str) -> Vec { key } +#[cfg(feature = "context")] fn context_project_key(key_name: &str) -> Vec { let mut key = Vec::new(); key.extend_from_slice(b"ctx/proj/"); diff --git a/crates/libgrite-core/src/types/event.rs b/crates/libgrite-core/src/types/event.rs index 2f24546..d230929 100644 --- a/crates/libgrite-core/src/types/event.rs +++ b/crates/libgrite-core/src/types/event.rs @@ -298,25 +298,28 @@ mod tests { .kind_tag(), 12 ); - assert_eq!( - EventKind::ContextUpdated { - path: String::new(), - language: String::new(), - symbols: vec![], - summary: String::new(), - content_hash: [0; 32] - } - .kind_tag(), - 13 - ); - assert_eq!( - EventKind::ProjectContextUpdated { - key: String::new(), - value: String::new() - } - .kind_tag(), - 14 - ); + #[cfg(feature = "context")] + { + assert_eq!( + EventKind::ContextUpdated { + path: String::new(), + language: String::new(), + symbols: vec![], + summary: String::new(), + content_hash: [0; 32] + } + .kind_tag(), + 13 + ); + assert_eq!( + EventKind::ProjectContextUpdated { + key: String::new(), + value: String::new() + } + .kind_tag(), + 14 + ); + } } #[test] diff --git a/crates/libgrite-core/src/types/mod.rs b/crates/libgrite-core/src/types/mod.rs index bfde0b7..9f433d5 100644 --- a/crates/libgrite-core/src/types/mod.rs +++ b/crates/libgrite-core/src/types/mod.rs @@ -1,4 +1,5 @@ pub mod actor; +#[cfg(feature = "context")] pub mod context; pub mod event; pub mod ids; diff --git a/crates/libgrite-git/Cargo.toml b/crates/libgrite-git/Cargo.toml index b99460e..095fc6e 100644 --- a/crates/libgrite-git/Cargo.toml +++ b/crates/libgrite-git/Cargo.toml @@ -13,6 +13,10 @@ description = "Git WAL, sync, and snapshot operations for grite" readme = "README.md" authors.workspace = true +[features] +default = ["context"] +context = ["libgrite-core/context"] + [dependencies] libgrite-core = { path = "../libgrite-core", version = "0.5.1" } git2 = { workspace = true } diff --git a/crates/libgrite-ipc/Cargo.toml b/crates/libgrite-ipc/Cargo.toml index 760bb26..0ec5896 100644 --- a/crates/libgrite-ipc/Cargo.toml +++ b/crates/libgrite-ipc/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" authors.workspace = true [dependencies] -libgrite-core = { path = "../libgrite-core", version = "0.5.1" } +libgrite-core = { path = "../libgrite-core", default-features = false } rkyv = { workspace = true } serde = { workspace = true } serde_json = { workspace = true }