From 271959ee271229e21594c7ddb2d2f52165ad8955 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 25 Jul 2024 21:29:37 +0000 Subject: [PATCH] add debug list-dependencies admin command Signed-off-by: Jason Volk --- src/admin/debug/commands.rs | 24 ++++++++++++++++++++++++ src/admin/debug/mod.rs | 6 ++++++ src/core/info/cargo.rs | 24 +++++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/admin/debug/commands.rs b/src/admin/debug/commands.rs index 32fba409..307495d7 100644 --- a/src/admin/debug/commands.rs +++ b/src/admin/debug/commands.rs @@ -745,3 +745,27 @@ pub(super) async fn time(_body: &[&str]) -> Result { let now = SystemTime::now(); Ok(RoomMessageEventContent::text_markdown(utils::time::format(now, "%+"))) } + +pub(super) async fn list_dependencies(_body: &[&str], names: bool) -> Result { + if names { + let out = info::cargo::dependencies_names().join(" "); + return Ok(RoomMessageEventContent::notice_markdown(out)); + } + + let deps = info::cargo::dependencies(); + let mut out = String::new(); + writeln!(out, "| name | version | features |")?; + writeln!(out, "| ---- | ------- | -------- |")?; + for (name, dep) in deps { + let version = dep.try_req().unwrap_or("*"); + let feats = dep.req_features(); + let feats = if !feats.is_empty() { + feats.join(" ") + } else { + String::new() + }; + writeln!(out, "{name} | {version} | {feats}")?; + } + + Ok(RoomMessageEventContent::notice_markdown(out)) +} diff --git a/src/admin/debug/mod.rs b/src/admin/debug/mod.rs index 77bc36b8..babd6047 100644 --- a/src/admin/debug/mod.rs +++ b/src/admin/debug/mod.rs @@ -178,6 +178,12 @@ pub(super) enum DebugCommand { /// - Print the current time Time, + /// - List dependencies + ListDependencies { + #[arg(short, long)] + names: bool, + }, + /// - Developer test stubs #[command(subcommand)] #[allow(non_snake_case)] diff --git a/src/core/info/cargo.rs b/src/core/info/cargo.rs index 0d2db1ad..544bbb8f 100644 --- a/src/core/info/cargo.rs +++ b/src/core/info/cargo.rs @@ -5,7 +5,7 @@ use std::sync::OnceLock; -use cargo_toml::Manifest; +use cargo_toml::{DepsSet, Manifest}; use conduit_macros::cargo_manifest; use crate::Result; @@ -36,6 +36,18 @@ const MAIN_MANIFEST: &'static str = (); /// For *enabled* features see the info::rustc module instead. static FEATURES: OnceLock> = OnceLock::new(); +/// Processed list of dependencies. This is generated from the datas captured in +/// the MANIFEST. +static DEPENDENCIES: OnceLock = OnceLock::new(); + +#[must_use] +pub fn dependencies_names() -> Vec<&'static str> { dependencies().keys().map(String::as_str).collect() } + +pub fn dependencies() -> &'static DepsSet { + DEPENDENCIES + .get_or_init(|| init_dependencies().unwrap_or_else(|e| panic!("Failed to initialize dependencies: {e}"))) +} + /// List of all possible features for the project. For *enabled* features in /// this build see the companion function in info::rustc. pub fn features() -> &'static Vec { @@ -64,3 +76,13 @@ fn append_features(features: &mut Vec, manifest: &str) -> Result<()> { Ok(()) } + +fn init_dependencies() -> Result { + let manifest = Manifest::from_str(WORKSPACE_MANIFEST)?; + Ok(manifest + .workspace + .as_ref() + .expect("manifest has workspace section") + .dependencies + .clone()) +}