gitcortex-store 0.5.1

KuzuDB-backed graph store for GitCortex — branch-namespaced, embedded, zero server process
Documentation

gitcortex-store

KuzuDB-backed graph store for GitCortex. Implements the GraphStore trait from gitcortex-core with a local embedded database — one database file per repository, with independent per-branch node and edge tables inside it. No server process, no external dependencies.

Add to your project

[dependencies]
gitcortex-core  = "0.2"
gitcortex-store = "0.2"

Quick start

use gitcortex_store::kuzu::KuzuGraphStore;
use gitcortex_core::store::GraphStore;
use std::path::Path;

// Open or create the database for the repo at this path
let mut store = KuzuGraphStore::open(Path::new("/path/to/your/repo"))?;

// Apply a diff produced by gitcortex-indexer
store.apply_diff("main", &diff)?;
store.set_last_indexed_sha("main", &head_sha)?;

// Query
let nodes = store.lookup_symbol("main", "process_request", false)?;
let callers = store.find_callers("main", "process_request")?;

Where data is stored

The database lives in your home directory, never in the repo:

~/.local/share/gitcortex/{repo_id}/
    graph.kuzu        # KuzuDB database (all branches in one file)
    schema_version    # schema version marker for auto-migration
    main.sha          # last indexed SHA for branch "main"
    feat__auth.sha    # last indexed SHA for branch "feat/auth"

These files are machine-local and should never be committed.

Branch isolation

Each branch gets its own node and edge tables inside the single database file. Switching branches in the query API is as simple as passing a different branch name — no file switching, no re-opening the database.

// Query the same symbol across two branches
let on_main = store.lookup_symbol("main", "AuthService", false)?;
let on_feat = store.lookup_symbol("feat/auth", "AuthService", false)?;

Branch names are normalised automatically: / becomes __, leading digits are prefixed, so feat/my-branch becomes the table prefix feat__my_branch internally.

Schema versioning

If the on-disk schema doesn't match the current version, the store automatically wipes all data for that repo and prints a message:

gitcortex: schema version mismatch (expected 4); wiping graph store for re-index

The next gcx hook (or store.apply_diff) triggers a full re-index from scratch.

Full API

All methods are from the GraphStore trait in gitcortex-core:

use gitcortex_core::store::GraphStore;
use std::path::Path;

// Write
store.apply_diff("main", &diff)?;
store.set_last_indexed_sha("main", &sha)?;

// Basic lookups
let nodes  = store.lookup_symbol("main", "MyStruct", false)?; // exact match
let nodes  = store.lookup_symbol("main", "My", true)?;        // fuzzy (substring)
let defs   = store.list_definitions("main", Path::new("src/auth.rs"))?;
let all    = store.list_all_nodes("main")?;
let edges  = store.list_all_edges("main")?;

// Caller / callee traversal
let callers  = store.find_callers("main", "validate_token")?;      // 1 hop
let deep     = store.find_callers_deep("main", "validate_token", 3)?; // up to 3 hops
let callees  = store.find_callees("main", "handle_request", 2)?;   // forward, 2 hops

// Structural queries
let impls  = store.find_implementors("main", "AuthProvider")?;
let path   = store.trace_path("main", "main", "validate_token")?;   // shortest BFS path
let sub    = store.get_subgraph("main", "UserService", 2, "both")?; // 2-hop neighbourhood
let ctx    = store.symbol_context("main", "process_request")?;      // callers + callees + used_by
let range  = store.list_symbols_in_range("main", Path::new("src/auth.rs"), 10, 50)?;
let dead   = store.find_unused_symbols("main", None)?;

// Branch diff
let diff   = store.branch_diff("main", "feat/auth")?; // nodes/edges added or removed

// Index state
let sha    = store.last_indexed_sha("main")?; // None if never indexed

Multi-hop results

find_callers_deep, find_callees return a CallersDeep struct:

pub struct CallersDeep {
    pub hops: Vec<Vec<Node>>, // hops[0] = direct callers (hop 1), hops[1] = hop 2, ...
    pub risk_level: &'static str, // "LOW" | "MEDIUM" | "HIGH"
}

Symbol context

symbol_context gives a 360° view of a single symbol:

pub struct SymbolContext {
    pub definition: Node,    // the node itself
    pub callers: Vec<Node>,  // what calls this symbol
    pub callees: Vec<Node>,  // what this symbol calls
    pub used_by: Vec<Node>,  // what references this symbol via Uses edges
}

Subgraph

get_subgraph returns all nodes and edges within N hops of a seed symbol:

let sub = store.get_subgraph("main", "UserService", 2, "both")?;
println!("{} nodes, {} edges", sub.nodes.len(), sub.edges.len());

// direction options: "in" (callers only), "out" (callees only), "both"

Using without gitcortex-indexer

The store is independent of the indexer. You can build GraphDiff values manually and apply them directly — useful for testing or custom import pipelines:

use gitcortex_core::graph::{GraphDiff, Node, NodeId, Span, NodeMetadata};
use gitcortex_core::schema::{NodeKind, Visibility};
use gitcortex_store::kuzu::KuzuGraphStore;
use gitcortex_core::store::GraphStore;

let mut store = KuzuGraphStore::open(Path::new("/tmp/test-repo"))?;

let node = Node {
    id: NodeId::new(),
    kind: NodeKind::Function,
    name: "my_func".into(),
    qualified_name: "crate::my_func".into(),
    file: "src/lib.rs".into(),
    span: Span { start_line: 1, end_line: 5 },
    metadata: NodeMetadata { visibility: Visibility::Pub, ..Default::default() },
};

let diff = GraphDiff { added_nodes: vec![node], ..Default::default() };
store.apply_diff("main", &diff)?;

Testing

The round-trip tests in tests/round_trip.rs demonstrate the full write→read cycle:

cargo test -p gitcortex-store

Each test uses a tempfile::TempDir so tests are fully isolated. Because KuzuDB cannot open the same database path from multiple processes simultaneously, tests that open different databases run in parallel safely; tests sharing a path must be serialised.

Dependencies

Crate Purpose
gitcortex-core Shared graph types and GraphStore trait
kuzu Embedded graph database
dashmap Concurrent map for in-memory branch metadata caching
tracing Structured logging for slow query diagnostics

License

MIT — free for commercial and open-source use.

GitHub · Issues