Skip to main content

pmpx_plugin/
manager.rs

1//! The trait a plugin implements: the one thing a plugin author writes by hand.
2
3use std::ffi::OsString;
4
5use crate::{CommandSpec, Context, Family, PluginError, Verb};
6
7/// An implementation of one package manager backend, a purely synchronous interface: no `async`,
8/// no callbacks, no I/O -- passing a `Future` across the `dlopen` boundary is the most fragile
9/// part of this approach. It should only do mapping; see the crate docs for the constraints.
10///
11/// A panic in any of these methods is caught by the `export!` shell -- the `#[unsafe(no_mangle)]`
12/// wrapper catches it before it can cross `extern "C"`, which would abort the host process. The
13/// host then sees a failed call, or the [`PANIC_MARKER`](crate::shell::PANIC_MARKER) name, and
14/// refuses to use the plugin; the panic message itself goes to stderr as usual.
15pub trait PackageManager: Send + Sync {
16    /// Plugin name, e.g. `"cargo"`. The host compares it against the name declared in the
17    /// manifest and refuses to load on a mismatch.
18    fn name(&self) -> &str;
19
20    /// The ecosystem it belongs to.
21    fn family(&self) -> Family;
22
23    /// Translate "verb + arguments" into one concrete command.
24    /// Return [`PluginError::UnsupportedVerb`] when a verb is not supported and do not improvise a
25    /// near-equivalent command -- the host degrades `exec`, the other verbs report the error as-is,
26    /// and either is better than guessing.
27    fn command(
28        &self,
29        ctx: &Context,
30        verb: Verb,
31        args: &[OsString],
32    ) -> Result<CommandSpec, PluginError>;
33}