Vine/Server/Notification/
RegisterScmProvider.rs1use serde_json::{Value, json};
20
21use crate::{Host::VineHost, dev_log};
22
23fn BuildUrlFromComponents(O:&serde_json::Map<String, Value>) -> Option<String> {
27 let Scheme = O.get("scheme").and_then(Value::as_str)?;
28
29 if Scheme.is_empty() {
30 return None;
31 }
32
33 let Authority = O.get("authority").and_then(Value::as_str).unwrap_or("");
34
35 let Path = O.get("path").and_then(Value::as_str).unwrap_or("");
36
37 let Query = O.get("query").and_then(Value::as_str).unwrap_or("");
38
39 let Fragment = O.get("fragment").and_then(Value::as_str).unwrap_or("");
40
41 let mut Url = format!("{}://{}{}", Scheme, Authority, Path);
42
43 if !Query.is_empty() {
44 Url.push('?');
45
46 Url.push_str(Query);
47 }
48
49 if !Fragment.is_empty() {
50 Url.push('#');
51
52 Url.push_str(Fragment);
53 }
54
55 Some(Url)
56}
57
58pub async fn RegisterScmProvider(Host:&dyn VineHost, Parameter:&Value) {
59 let ScmId = Parameter
62 .get("id")
63 .or_else(|| Parameter.get("scmId"))
64 .or_else(|| Parameter.get("scm_id"))
65 .and_then(Value::as_str)
66 .unwrap_or("")
67 .to_string();
68
69 let Label = Parameter.get("label").and_then(Value::as_str).unwrap_or(&ScmId).to_string();
70
71 let ExtensionId = Parameter
72 .get("extensionId")
73 .or_else(|| Parameter.get("extension_id"))
74 .and_then(Value::as_str)
75 .unwrap_or("")
76 .to_string();
77
78 let RootUri = Parameter
79 .get("rootUri")
80 .or_else(|| Parameter.get("root_uri"))
81 .cloned()
82 .unwrap_or(Value::Null);
83
84 if ScmId.is_empty() {
85 dev_log!("provider-register", "[ProviderRegister] scm skip: missing scm_id");
86
87 return;
88 }
89
90 let Handle = Parameter
93 .get("handle")
94 .or_else(|| Parameter.get("scmHandle"))
95 .or_else(|| Parameter.get("scm_handle"))
96 .and_then(Value::as_u64)
97 .map(|H| H as u32)
98 .unwrap_or_else(|| {
99 ScmId
100 .as_bytes()
101 .iter()
102 .fold(0u32, |Acc, B| Acc.wrapping_mul(31).wrapping_add(*B as u32))
103 });
104
105 Host.RegisterScmInRegistry(Handle, &ScmId, &Label, &ExtensionId);
107
108 let RootUriString = match &RootUri {
110 Value::String(S) => S.clone(),
111
112 Value::Object(O) => {
113 BuildUrlFromComponents(O)
114 .or_else(|| O.get("external").and_then(Value::as_str).map(str::to_string))
115 .or_else(|| {
116 O.get("path")
117 .and_then(Value::as_str)
118 .filter(|P| P.starts_with('/'))
119 .map(|P| format!("file://{}", P))
120 })
121 .unwrap_or_else(|| "file:///".to_string())
122 },
123
124 _ => "file:///".to_string(),
125 };
126
127 let CreateData = json!({
132 "handle": Handle,
133 "id": &ScmId,
134 "label": &Label,
135 "rootUri": RootUriString,
136 });
137
138 Host.CreateSourceControl(CreateData).await;
140
141 Host.EmitToRenderer(
143 "sky://scm/register",
144 json!({
145 "scmId": &ScmId,
146 "label": &Label,
147 "rootUri": &RootUriString,
148 "extensionId": &ExtensionId,
149 "handle": Handle,
150 }),
151 );
152
153 dev_log!(
154 "grpc",
155 "[Scm] register provider scmId={} label={} ext={} handle={}",
156 ScmId,
157 Label,
158 ExtensionId,
159 Handle
160 );
161}