Skip to main content

Mountain/Vine/Server/Notification/
UnregisterScmProvider.rs

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