1use std::sync::Arc;
4
5use async_trait::async_trait;
6use serde_json::Value;
7
8use khive_runtime::pack::PackRuntime;
9use khive_runtime::{
10 KhiveRuntime, KindHook, NamespaceToken, NoteKindSpec, PackSchemaPlan, RuntimeError, SchemaPlan,
11 VerbRegistry,
12};
13use khive_types::{EdgeEndpointRule, HandlerDef, Pack};
14
15use crate::hook::{CommitHook, IssueLikeHook};
16use crate::vocab::{GIT_NOTE_KIND_SPECS, GIT_SCHEMA_PLAN_STMTS};
17
18pub struct GitPack {
26 runtime: KhiveRuntime,
27}
28
29impl Pack for GitPack {
30 const NAME: &'static str = "git";
31 const NOTE_KINDS: &'static [&'static str] = &["commit", "issue", "pull_request"];
32 const ENTITY_KINDS: &'static [&'static str] = &[];
33 const HANDLERS: &'static [HandlerDef] = &crate::vocab::GIT_HANDLERS;
34 const EDGE_RULES: &'static [EdgeEndpointRule] = &crate::vocab::GIT_EDGE_RULES;
35 const REQUIRES: &'static [&'static str] = &["kg"];
36 const NOTE_KIND_SPECS: &'static [NoteKindSpec] = &GIT_NOTE_KIND_SPECS;
37 const SCHEMA_PLAN: Option<PackSchemaPlan> = Some(PackSchemaPlan {
38 pack: "git",
39 statements: &GIT_SCHEMA_PLAN_STMTS,
40 });
41}
42
43impl GitPack {
44 pub fn new(runtime: KhiveRuntime) -> Self {
46 Self { runtime }
47 }
48
49 pub(crate) fn runtime(&self) -> &KhiveRuntime {
53 &self.runtime
54 }
55}
56
57struct GitPackFactory;
60
61impl khive_runtime::PackFactory for GitPackFactory {
62 fn name(&self) -> &'static str {
63 "git"
64 }
65
66 fn requires(&self) -> &'static [&'static str] {
67 &["kg"]
68 }
69
70 fn create(&self, runtime: KhiveRuntime) -> Box<dyn khive_runtime::PackRuntime> {
71 Box::new(GitPack::new(runtime))
72 }
73}
74
75inventory::submit! { khive_runtime::PackRegistration(&GitPackFactory) }
76
77#[async_trait]
78impl PackRuntime for GitPack {
79 fn name(&self) -> &str {
80 <GitPack as Pack>::NAME
81 }
82
83 fn note_kinds(&self) -> &'static [&'static str] {
84 <GitPack as Pack>::NOTE_KINDS
85 }
86
87 fn entity_kinds(&self) -> &'static [&'static str] {
88 <GitPack as Pack>::ENTITY_KINDS
89 }
90
91 fn handlers(&self) -> &'static [HandlerDef] {
92 <GitPack as Pack>::HANDLERS
93 }
94
95 fn edge_rules(&self) -> &'static [EdgeEndpointRule] {
96 <GitPack as Pack>::EDGE_RULES
97 }
98
99 fn requires(&self) -> &'static [&'static str] {
100 <GitPack as Pack>::REQUIRES
101 }
102
103 fn note_kind_specs(&self) -> &'static [NoteKindSpec] {
104 <GitPack as Pack>::NOTE_KIND_SPECS
105 }
106
107 fn schema_plan(&self) -> SchemaPlan {
108 SchemaPlan {
109 pack: "git",
110 statements: &GIT_SCHEMA_PLAN_STMTS,
111 }
112 }
113
114 fn kind_hook(&self, kind: &str) -> Option<Arc<dyn KindHook>> {
115 match kind {
116 "commit" => Some(Arc::new(CommitHook)),
117 "issue" => Some(Arc::new(IssueLikeHook { kind: "issue" })),
118 "pull_request" => Some(Arc::new(IssueLikeHook {
119 kind: "pull_request",
120 })),
121 _ => None,
122 }
123 }
124
125 async fn dispatch(
126 &self,
127 verb: &str,
128 params: Value,
129 registry: &VerbRegistry,
130 token: &NamespaceToken,
131 ) -> Result<Value, RuntimeError> {
132 match verb {
133 "git.digest" => self.handle_digest(token, registry, params).await,
134 _ => Err(RuntimeError::InvalidInput(format!(
135 "git pack does not handle verb {verb:?}"
136 ))),
137 }
138 }
139}