Skip to main content

Mountain/Vine/Server/Notification/
UnregisterScmProvider.rs

1#![allow(non_snake_case)]
2//! Cocoon → Mountain `unregister_scm_provider` notification.
3//! Emitted by `Cocoon/.../ScmNamespace.ts:82` when
4//! `vscode.scm.createSourceControl(...).dispose()` fires. The paired
5//! `RegisterScmProvider` typed gRPC (`RPC/CocoonService/SCM.rs`) derives
6//! the handle as a DJB-style hash of the `scmId`; we recompute the same
7//! hash here so unregister cleans up the exact entry `RegisterScmProvider`
8//! stored without needing Cocoon to hand the u32 back over the wire.
9
10use serde_json::Value;
11use tauri::Emitter;
12
13use crate::{Vine::Server::MountainVinegRPCService::MountainVinegRPCService, dev_log};
14
15pub async fn UnregisterScmProvider(Service:&MountainVinegRPCService, Parameter:&Value) {
16	// Cocoon's `ScmNamespace.ts:dispose` sends only `{ handle }` (number).
17	// `scmId` (camelCase) and `scm_id` (legacy snake_case) are also
18	// probed for callers that send the string identifier instead.
19	let ScmId = Parameter
20		.get("scmId")
21		.or_else(|| Parameter.get("scm_id"))
22		.and_then(Value::as_str)
23		.unwrap_or("")
24		.to_string();
25	let DirectHandle = Parameter.get("handle").and_then(Value::as_u64).map(|H| H as u32);
26	if ScmId.is_empty() && DirectHandle.is_none() {
27		dev_log!("provider-register", "[ProviderUnregister] scm skip: missing handle / scmId");
28		return;
29	}
30	let Handle = DirectHandle.unwrap_or_else(|| {
31		ScmId
32			.as_bytes()
33			.iter()
34			.fold(0u32, |Acc, B| Acc.wrapping_mul(31).wrapping_add(*B as u32))
35	});
36	Service
37		.RunTime()
38		.Environment
39		.ApplicationState
40		.Extension
41		.ProviderRegistration
42		.UnregisterProvider(Handle);
43	let _ = Service
44		.ApplicationHandle()
45		.emit("sky://scm/unregister", serde_json::json!({ "scmId": ScmId }));
46	dev_log!(
47		"provider-register",
48		"[ProviderUnregister] scm scm_id={} handle={}",
49		ScmId,
50		Handle
51	);
52}