git-ents.gitmain
⌘K
foforge
lsp.rs72 lines · 2.5 KB · rusthistorycomment on this file
1//! `git ents lsp`: reuse [`LocalRoot`]'s existing wiring and add only the
2//! `ents-lens` Language Server Protocol frontend, over stdio (`lens.serve`).
3//!
4//! `lens.serve` requires this command to serve LSP over stdio reusing the
5//! local composition root exactly as `git ents serve` reuses it for the web
6//! UI (`roots.local`), binding no socket and adding no git transport. This
7//! module upholds that: it is handed an already-open [`LocalRoot`] (never
8//! opens its own), resolves the user's own signing key exactly as every
9//! other mutation command does, and hands both to
10//! [`ents_lens::serve_stdio`], which speaks only stdin/stdout.
11//!
12//! The signing identity is injected the same way `serve` injects
13//! `ents-web`'s (`roots.web-agnostic` parity): the lens crate resolves no
14//! key and assumes no editor is attached; this composition root builds an
15//! owned [`ents_lens::Signing`] from the user's own key
16//! (`roots.web-signing`'s local half — no server-key indirection exists
17//! here) and moves it in.
18
19use std::path::PathBuf;
20
21use ents_lens::{Lens, Signing};
22
23use super::{actor, signer};
24use crate::error::{Error, Result};
25use crate::root::LocalRoot;
26
27/// Run `git ents lsp`: build the lens from `root`'s seams and the user's
28/// resolved signing key, then serve LSP over stdio until the client shuts
29/// it down.
30///
31/// Takes no output writer: the process's stdout is the LSP protocol
32/// channel, so this command must write nothing else to it.
33///
34/// # Errors
35///
36/// Propagates a signing-key resolution failure ([`crate::sign::Signer`]),
37/// or an [`Error::Io`] if the LSP transport fails.
38// @relation(lens.serve, roots.local, scope=function)
39pub fn run(root: LocalRoot, key: Option<PathBuf>) -> Result<()> {
40 let signer = signer(&root, key)?;
41 let identity_actor = actor(&signer);
42 let public_openssh = signer.public_openssh();
43 // The user's own key signs composed comments (`roots.web-signing`'s
44 // local half): no server-key indirection is imported into the local
45 // root, exactly as `serve` keeps it out.
46 let signing = Signing::new(
47 identity_actor,
48 Box::new(move |payload| signer.sign(payload)),
49 public_openssh,
50 );
51
52 let mode = root.mode();
53 let LocalRoot {
54 path,
55 refs,
56 objects,
57 events,
58 executor: _,
59 } = root;
60 let lens = Lens::new(
61 Box::new(refs),
62 objects,
63 Box::new(events),
64 mode,
65 signing,
66 path,
67 );
68 ents_lens::serve_stdio(lens).map_err(|source| Error::Io {
69 path: PathBuf::from("<lsp stdio>"),
70 source,
71 })
72}