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
26	let DirectHandle = Parameter.get("handle").and_then(Value::as_u64).map(|H| H as u32);
27
28	if ScmId.is_empty() && DirectHandle.is_none() {
29		dev_log!("provider-register", "[ProviderUnregister] scm skip: missing handle / scmId");
30
31		return;
32	}
33
34	let Handle = DirectHandle.unwrap_or_else(|| {
35		ScmId
36			.as_bytes()
37			.iter()
38			.fold(0u32, |Acc, B| Acc.wrapping_mul(31).wrapping_add(*B as u32))
39	});
40
41	Service
42		.RunTime()
43		.Environment
44		.ApplicationState
45		.Extension
46		.ProviderRegistration
47		.UnregisterProvider(Handle);
48
49	let _ = Service
50		.ApplicationHandle()
51		.emit("sky://scm/unregister", serde_json::json!({ "scmId": ScmId }));
52
53	dev_log!(
54		"provider-register",
55		"[ProviderUnregister] scm scm_id={} handle={}",
56		ScmId,
57		Handle
58	);
59}