feat: upgrade panproto to v0.28.0, use incremental import and typed XRPC responses - All panproto deps bumped from v0.27.3 to v0.28.0 - receive_pack: switch to import_git_repo_incremental with persistent marks file (.git-import-marks) so repeated pushes only import new commits instead of walking the entire history - list_commits: return panproto_xrpc::ListCommitsResult (typed) instead of hand-built serde_json::Value - diff_commits: return panproto_xrpc::DiffCommitsResult (typed) with FileDiff structs; fix contextLines query param deserialization (camelCase to match frontend) - Handle new Value::List variant in search_structural
Author: Aaron Steven White
Commit
b2707f62cc5c83500c49d51bcd9d6dad82bb0e69Parent: f9664e89d9
Structural diff unavailable
These commits were pushed via plain git push, so no pre-parsed
schemas are available. Install git-remote-cospan and re-push via panproto:// to
see scope-level changes, breaking change detection, and semantic diffs.
brew install panproto/tap/git-remote-cospan9 files changed +295 -228
@@ -621,6 +621,7 @@ dependencies = [
621621 "panproto-protocols", 622622 "panproto-schema", 623623 "panproto-vcs", 624+ "panproto-xrpc", 624625 "reqwest", 625626 "rmp-serde", 626627 "serde",
@@ -2490,8 +2491,8 @@ dependencies = [
24902491 24912492 [[package]] 24922493 name = "panproto-check" 2493-version = "0.27.3" 2494-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2494+version = "0.28.0" 2495+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 24952496 dependencies = [ 24962497 "panproto-gat", 24972498 "panproto-lens",
@@ -2505,8 +2506,8 @@ dependencies = [
25052506 25062507 [[package]] 25072508 name = "panproto-core" 2508-version = "0.27.3" 2509-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2509+version = "0.28.0" 2510+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25102511 dependencies = [ 25112512 "panproto-check", 25122513 "panproto-gat",
@@ -2521,8 +2522,8 @@ dependencies = [
25212522 25222523 [[package]] 25232524 name = "panproto-expr" 2524-version = "0.27.3" 2525-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2525+version = "0.28.0" 2526+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25262527 dependencies = [ 25272528 "rustc-hash", 25282529 "serde",
@@ -2531,8 +2532,8 @@ dependencies = [
25312532 25322533 [[package]] 25332534 name = "panproto-expr-parser" 2534-version = "0.27.3" 2535-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2535+version = "0.28.0" 2536+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25362537 dependencies = [ 25372538 "chumsky", 25382539 "logos 0.16.1",
@@ -2541,8 +2542,8 @@ dependencies = [
25412542 25422543 [[package]] 25432544 name = "panproto-gat" 2544-version = "0.27.3" 2545-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2545+version = "0.28.0" 2546+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25462547 dependencies = [ 25472548 "panproto-expr", 25482549 "rustc-hash",
@@ -2552,8 +2553,8 @@ dependencies = [
25522553 25532554 [[package]] 25542555 name = "panproto-git" 2555-version = "0.27.3" 2556-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2556+version = "0.28.0" 2557+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25572558 dependencies = [ 25582559 "git2", 25592560 "miette",
@@ -2570,8 +2571,8 @@ dependencies = [
25702571 25712572 [[package]] 25722573 name = "panproto-grammars" 2573-version = "0.27.3" 2574-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2574+version = "0.28.0" 2575+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25752576 dependencies = [ 25762577 "cc", 25772578 "serde",
@@ -2582,8 +2583,8 @@ dependencies = [
25822583 25832584 [[package]] 25842585 name = "panproto-inst" 2585-version = "0.27.3" 2586-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2586+version = "0.28.0" 2587+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 25872588 dependencies = [ 25882589 "bumpalo", 25892590 "panproto-expr",
@@ -2598,8 +2599,8 @@ dependencies = [
25982599 25992600 [[package]] 26002601 name = "panproto-io" 2601-version = "0.27.3" 2602-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2602+version = "0.28.0" 2603+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26032604 dependencies = [ 26042605 "bumpalo", 26052606 "memchr",
@@ -2621,8 +2622,8 @@ dependencies = [
26212622 26222623 [[package]] 26232624 name = "panproto-lens" 2624-version = "0.27.3" 2625-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2625+version = "0.28.0" 2626+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26262627 dependencies = [ 26272628 "panproto-expr", 26282629 "panproto-gat",
@@ -2638,8 +2639,8 @@ dependencies = [
26382639 26392640 [[package]] 26402641 name = "panproto-lens-dsl" 2641-version = "0.27.3" 2642-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2642+version = "0.28.0" 2643+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26432644 dependencies = [ 26442645 "miette", 26452646 "nickel-lang",
@@ -2657,8 +2658,8 @@ dependencies = [
26572658 26582659 [[package]] 26592660 name = "panproto-mig" 2660-version = "0.27.3" 2661-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2661+version = "0.28.0" 2662+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26622663 dependencies = [ 26632664 "panproto-expr", 26642665 "panproto-gat",
@@ -2671,8 +2672,8 @@ dependencies = [
26712672 26722673 [[package]] 26732674 name = "panproto-parse" 2674-version = "0.27.3" 2675-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2675+version = "0.28.0" 2676+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26762677 dependencies = [ 26772678 "memchr", 26782679 "miette",
@@ -2690,8 +2691,8 @@ dependencies = [
26902691 26912692 [[package]] 26922693 name = "panproto-project" 2693-version = "0.27.3" 2694-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2694+version = "0.28.0" 2695+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 26952696 dependencies = [ 26962697 "blake3", 26972698 "globset",
@@ -2710,8 +2711,8 @@ dependencies = [
27102711 27112712 [[package]] 27122713 name = "panproto-protocols" 2713-version = "0.27.3" 2714-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2714+version = "0.28.0" 2715+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 27152716 dependencies = [ 27162717 "blake3", 27172718 "panproto-gat",
@@ -2725,8 +2726,8 @@ dependencies = [
27252726 27262727 [[package]] 27272728 name = "panproto-schema" 2728-version = "0.27.3" 2729-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2729+version = "0.28.0" 2730+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 27302731 dependencies = [ 27312732 "panproto-expr", 27322733 "panproto-gat",
@@ -2738,8 +2739,8 @@ dependencies = [
27382739 27392740 [[package]] 27402741 name = "panproto-vcs" 2741-version = "0.27.3" 2742-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2742+version = "0.28.0" 2743+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 27432744 dependencies = [ 27442745 "blake3", 27452746 "panproto-check",
@@ -2759,8 +2760,8 @@ dependencies = [
27592760 27602761 [[package]] 27612762 name = "panproto-xrpc" 2762-version = "0.27.3" 2763-source = "git+https://github.com/panproto/panproto.git?tag=v0.27.3#8d55ceface4d59752903f996c1ae34935b50cbea" 2763+version = "0.28.0" 2764+source = "git+https://github.com/panproto/panproto.git?tag=v0.28.0#4db61dee8a553b6abd0905408b116d175f394a44" 27642765 dependencies = [ 27652766 "hex", 27662767 "miette",
@@ -13,24 +13,24 @@ license = "AGPL-3.0-or-later"
1313 repository = "https://github.com/cospan-dev/cospan" 1414 1515 [workspace.dependencies] 16-# panproto v0.27.3 17-panproto-core = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 18-panproto-vcs = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 19-panproto-schema = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 20-panproto-check = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 21-panproto-lens = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 22-panproto-lens-dsl = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 23-panproto-protocols = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 24-panproto-io = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 25-panproto-inst = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 26-panproto-gat = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 27-panproto-mig = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 28-panproto-expr = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 29-panproto-expr-parser = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 30-panproto-xrpc = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 31-panproto-parse = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3", features = ["group-all"] } 32-panproto-git = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 33-panproto-project = { git = "https://github.com/panproto/panproto.git", tag = "v0.27.3" } 16+# panproto v0.28.0 17+panproto-core = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 18+panproto-vcs = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 19+panproto-schema = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 20+panproto-check = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 21+panproto-lens = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 22+panproto-lens-dsl = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 23+panproto-protocols = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 24+panproto-io = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 25+panproto-inst = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 26+panproto-gat = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 27+panproto-mig = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 28+panproto-expr = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 29+panproto-expr-parser = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 30+panproto-xrpc = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 31+panproto-parse = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0", features = ["group-all"] } 32+panproto-git = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 33+panproto-project = { git = "https://github.com/panproto/panproto.git", tag = "v0.28.0" } 3434 git2 = "0.20" 3535 3636 # Web framework
@@ -163,6 +163,9 @@ fn value_to_json(v: &panproto_inst::value::Value) -> serde_json::Value {
163163 .collect(); 164164 serde_json::Value::Object(m) 165165 } 166+ Value::List(items) => { 167+ serde_json::Value::Array(items.iter().map(value_to_json).collect()) 168+ } 166169 } 167170 } 168171
@@ -21,6 +21,7 @@ panproto-lens.workspace = true
2121 panproto-parse.workspace = true 2222 panproto-git.workspace = true 2323 panproto-vcs.workspace = true 24+panproto-xrpc.workspace = true 2425 git2.workspace = true 2526 2627 axum.workspace = true
@@ -214,20 +214,17 @@ pub async fn git_receive_pack(
214214 215215 drop(store_guard); 216216 217- // 5. Import into panproto-vcs asynchronously. The push response is 218- // sent immediately; the import runs in the background. This is 219- // necessary because import_git_repo walks the entire commit 220- // history (tracked upstream at panproto/panproto#26) and can 221- // take minutes for repos with 100+ commits. 217+ // 5. Import into panproto-vcs asynchronously using incremental 218+ // import. The marks file tracks which git OIDs have already been 219+ // translated, so repeated pushes only import new commits. 222220 if !import_tasks.is_empty() { 223221 let store_clone = state.store.clone(); 224222 let did_clone = did.clone(); 225223 let repo_clone = repo.clone(); 226224 tokio::task::spawn_blocking(move || { 227- // Open the stores under the lock, then DROP the lock before 228- // the expensive import. FsStore is file-backed so concurrent 229- // reads (listCommits, diffCommits) work fine while we write. 230- let (mirror, mut vcs_store) = { 225+ // Open the stores under the lock, load marks, then DROP the 226+ // lock before the expensive import. 227+ let (mirror, mut vcs_store, known) = { 231228 let store_guard = store_clone.blocking_lock(); 232229 let mirror = match store_guard.open_or_init_git_mirror(&did_clone, &repo_clone) { 233230 Ok(m) => m,
@@ -243,17 +240,31 @@ pub async fn git_receive_pack(
243240 return; 244241 } 245242 }; 246- (mirror, vcs_store) 243+ let known = store_guard.load_import_marks(&did_clone, &repo_clone); 244+ (mirror, vcs_store, known) 247245 // store_guard dropped here: lock released 248246 }; 249247 for (new_oid, refname) in &import_tasks { 250- match panproto_git::import_git_repo(&mirror, &mut vcs_store, new_oid) { 248+ match panproto_git::import_git_repo_incremental( 249+ &mirror, 250+ &mut vcs_store, 251+ new_oid, 252+ &known, 253+ ) { 251254 Ok(result) => { 252255 let _ = panproto_vcs::Store::set_ref(&mut vcs_store, refname, result.head_id); 256+ // Persist the new OID mappings for future incremental imports. 257+ let store_guard = store_clone.blocking_lock(); 258+ store_guard.save_import_marks( 259+ &did_clone, 260+ &repo_clone, 261+ &result.oid_map, 262+ ); 263+ drop(store_guard); 253264 tracing::info!( 254265 did = %did_clone, repo = %repo_clone, %refname, 255266 commits = result.commit_count, 256- "background: imported git commits into panproto-vcs" 267+ "background: incrementally imported git commits into panproto-vcs" 257268 ); 258269 } 259270 Err(e) => {