mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-07-08 11:40:01 +02:00
feat: Generate binary documentation
Some checks failed
Checks / Prefligit / prefligit (push) Failing after 1s
Release Docker Image / define-variables (push) Failing after 1s
Release Docker Image / build-image (linux/amd64, release, linux-amd64, base) (push) Has been skipped
Release Docker Image / build-image (linux/arm64, release, linux-arm64, base) (push) Has been skipped
Release Docker Image / merge (push) Has been skipped
Checks / Rust / Format (push) Failing after 1s
Checks / Rust / Clippy (push) Failing after 27s
Checks / Rust / Cargo Test (push) Failing after 26s
Some checks failed
Checks / Prefligit / prefligit (push) Failing after 1s
Release Docker Image / define-variables (push) Failing after 1s
Release Docker Image / build-image (linux/amd64, release, linux-amd64, base) (push) Has been skipped
Release Docker Image / build-image (linux/arm64, release, linux-arm64, base) (push) Has been skipped
Release Docker Image / merge (push) Has been skipped
Checks / Rust / Format (push) Failing after 1s
Checks / Rust / Clippy (push) Failing after 27s
Checks / Rust / Cargo Test (push) Failing after 26s
Also refactors main.rs/mod.rs to silence clippy
This commit is contained in:
parent
d98ce2c7b9
commit
28a29c3a7b
12 changed files with 281 additions and 209 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -6129,7 +6129,7 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtask-admin-command"
|
name = "xtask-generate-commands"
|
||||||
version = "0.5.0-rc.6"
|
version = "0.5.0-rc.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap-markdown",
|
"clap-markdown",
|
||||||
|
|
|
@ -768,7 +768,7 @@ inherits = "dev"
|
||||||
# '-Clink-arg=-Wl,-z,nodlopen',
|
# '-Clink-arg=-Wl,-z,nodlopen',
|
||||||
# '-Clink-arg=-Wl,-z,nodelete',
|
# '-Clink-arg=-Wl,-z,nodelete',
|
||||||
#]
|
#]
|
||||||
[profile.dev.package.xtask-admin-command]
|
[profile.dev.package.xtask-generate-commands]
|
||||||
inherits = "dev"
|
inherits = "dev"
|
||||||
[profile.dev.package.conduwuit]
|
[profile.dev.package.conduwuit]
|
||||||
inherits = "dev"
|
inherits = "dev"
|
||||||
|
|
21
docs/server_reference.md
Normal file
21
docs/server_reference.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Command-Line Help for `continuwuity`
|
||||||
|
|
||||||
|
This document contains the help content for the `continuwuity` command-line program.
|
||||||
|
|
||||||
|
**Command Overview:**
|
||||||
|
|
||||||
|
* [`continuwuity`↴](#continuwuity)
|
||||||
|
|
||||||
|
## `continuwuity`
|
||||||
|
|
||||||
|
a very cool Matrix chat homeserver written in Rust
|
||||||
|
|
||||||
|
**Usage:** `continuwuity [OPTIONS]`
|
||||||
|
|
||||||
|
###### **Options:**
|
||||||
|
|
||||||
|
* `-c`, `--config <CONFIG>` — Path to the config TOML file (optional)
|
||||||
|
* `-O`, `--option <OPTION>` — Override a configuration variable using TOML 'key=value' syntax
|
||||||
|
* `--read-only` — Run in a stricter read-only --maintenance mode
|
||||||
|
* `--maintenance` — Run in maintenance mode while refusing connections
|
||||||
|
* `--execute <EXECUTE>` — Execute console command automatically after startup
|
|
@ -18,35 +18,35 @@ use conduwuit_core::{
|
||||||
name = conduwuit_core::name(),
|
name = conduwuit_core::name(),
|
||||||
version = conduwuit_core::version(),
|
version = conduwuit_core::version(),
|
||||||
)]
|
)]
|
||||||
pub(crate) struct Args {
|
pub struct Args {
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
/// Path to the config TOML file (optional)
|
/// Path to the config TOML file (optional)
|
||||||
pub(crate) config: Option<Vec<PathBuf>>,
|
pub config: Option<Vec<PathBuf>>,
|
||||||
|
|
||||||
/// Override a configuration variable using TOML 'key=value' syntax
|
/// Override a configuration variable using TOML 'key=value' syntax
|
||||||
#[arg(long, short('O'))]
|
#[arg(long, short('O'))]
|
||||||
pub(crate) option: Vec<String>,
|
pub option: Vec<String>,
|
||||||
|
|
||||||
/// Run in a stricter read-only --maintenance mode.
|
/// Run in a stricter read-only --maintenance mode.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub(crate) read_only: bool,
|
pub read_only: bool,
|
||||||
|
|
||||||
/// Run in maintenance mode while refusing connections.
|
/// Run in maintenance mode while refusing connections.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub(crate) maintenance: bool,
|
pub maintenance: bool,
|
||||||
|
|
||||||
#[cfg(feature = "console")]
|
#[cfg(feature = "console")]
|
||||||
/// Activate admin command console automatically after startup.
|
/// Activate admin command console automatically after startup.
|
||||||
#[arg(long, num_args(0))]
|
#[arg(long, num_args(0))]
|
||||||
pub(crate) console: bool,
|
pub console: bool,
|
||||||
|
|
||||||
/// Execute console command automatically after startup.
|
/// Execute console command automatically after startup.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub(crate) execute: Vec<String>,
|
pub execute: Vec<String>,
|
||||||
|
|
||||||
/// Set functional testing modes if available. Ex '--test=smoke'
|
/// Set functional testing modes if available. Ex '--test=smoke'
|
||||||
#[arg(long, hide(true))]
|
#[arg(long, hide(true))]
|
||||||
pub(crate) test: Vec<String>,
|
pub test: Vec<String>,
|
||||||
|
|
||||||
/// Override the tokio worker_thread count.
|
/// Override the tokio worker_thread count.
|
||||||
#[arg(
|
#[arg(
|
||||||
|
@ -55,19 +55,19 @@ pub(crate) struct Args {
|
||||||
env = "TOKIO_WORKER_THREADS",
|
env = "TOKIO_WORKER_THREADS",
|
||||||
default_value = available_parallelism().to_string(),
|
default_value = available_parallelism().to_string(),
|
||||||
)]
|
)]
|
||||||
pub(crate) worker_threads: usize,
|
pub worker_threads: usize,
|
||||||
|
|
||||||
/// Override the tokio global_queue_interval.
|
/// Override the tokio global_queue_interval.
|
||||||
#[arg(long, hide(true), env = "TOKIO_GLOBAL_QUEUE_INTERVAL", default_value = "192")]
|
#[arg(long, hide(true), env = "TOKIO_GLOBAL_QUEUE_INTERVAL", default_value = "192")]
|
||||||
pub(crate) global_event_interval: u32,
|
pub global_event_interval: u32,
|
||||||
|
|
||||||
/// Override the tokio event_interval.
|
/// Override the tokio event_interval.
|
||||||
#[arg(long, hide(true), env = "TOKIO_EVENT_INTERVAL", default_value = "512")]
|
#[arg(long, hide(true), env = "TOKIO_EVENT_INTERVAL", default_value = "512")]
|
||||||
pub(crate) kernel_event_interval: u32,
|
pub kernel_event_interval: u32,
|
||||||
|
|
||||||
/// Override the tokio max_io_events_per_tick.
|
/// Override the tokio max_io_events_per_tick.
|
||||||
#[arg(long, hide(true), env = "TOKIO_MAX_IO_EVENTS_PER_TICK", default_value = "512")]
|
#[arg(long, hide(true), env = "TOKIO_MAX_IO_EVENTS_PER_TICK", default_value = "512")]
|
||||||
pub(crate) kernel_events_per_tick: usize,
|
pub kernel_events_per_tick: usize,
|
||||||
|
|
||||||
/// Set the histogram bucket size, in microseconds (tokio_unstable). Default
|
/// Set the histogram bucket size, in microseconds (tokio_unstable). Default
|
||||||
/// is 25 microseconds. If the values of the histogram don't approach zero
|
/// is 25 microseconds. If the values of the histogram don't approach zero
|
||||||
|
@ -81,7 +81,7 @@ pub(crate) struct Args {
|
||||||
env = "CONDUWUIT_RUNTIME_HISTOGRAM_INTERVAL",
|
env = "CONDUWUIT_RUNTIME_HISTOGRAM_INTERVAL",
|
||||||
default_value = "25"
|
default_value = "25"
|
||||||
)]
|
)]
|
||||||
pub(crate) worker_histogram_interval: u64,
|
pub worker_histogram_interval: u64,
|
||||||
|
|
||||||
/// Set the histogram bucket count (tokio_unstable). Default is 20.
|
/// Set the histogram bucket count (tokio_unstable). Default is 20.
|
||||||
#[arg(
|
#[arg(
|
||||||
|
@ -91,7 +91,7 @@ pub(crate) struct Args {
|
||||||
env = "CONDUWUIT_RUNTIME_HISTOGRAM_BUCKETS",
|
env = "CONDUWUIT_RUNTIME_HISTOGRAM_BUCKETS",
|
||||||
default_value = "20"
|
default_value = "20"
|
||||||
)]
|
)]
|
||||||
pub(crate) worker_histogram_buckets: usize,
|
pub worker_histogram_buckets: usize,
|
||||||
|
|
||||||
/// Toggles worker affinity feature.
|
/// Toggles worker affinity feature.
|
||||||
#[arg(
|
#[arg(
|
||||||
|
@ -105,7 +105,7 @@ pub(crate) struct Args {
|
||||||
default_value = "true",
|
default_value = "true",
|
||||||
default_missing_value = "true",
|
default_missing_value = "true",
|
||||||
)]
|
)]
|
||||||
pub(crate) worker_affinity: bool,
|
pub worker_affinity: bool,
|
||||||
|
|
||||||
/// Toggles feature to promote memory reclamation by the operating system
|
/// Toggles feature to promote memory reclamation by the operating system
|
||||||
/// when tokio worker runs out of work.
|
/// when tokio worker runs out of work.
|
||||||
|
@ -118,7 +118,7 @@ pub(crate) struct Args {
|
||||||
num_args = 0..=1,
|
num_args = 0..=1,
|
||||||
require_equals(false),
|
require_equals(false),
|
||||||
)]
|
)]
|
||||||
pub(crate) gc_on_park: Option<bool>,
|
pub gc_on_park: Option<bool>,
|
||||||
|
|
||||||
/// Toggles muzzy decay for jemalloc arenas associated with a tokio
|
/// Toggles muzzy decay for jemalloc arenas associated with a tokio
|
||||||
/// worker (when worker-affinity is enabled). Setting to false releases
|
/// worker (when worker-affinity is enabled). Setting to false releases
|
||||||
|
@ -134,12 +134,12 @@ pub(crate) struct Args {
|
||||||
num_args = 0..=1,
|
num_args = 0..=1,
|
||||||
require_equals(false),
|
require_equals(false),
|
||||||
)]
|
)]
|
||||||
pub(crate) gc_muzzy: Option<bool>,
|
pub gc_muzzy: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse commandline arguments into structured data
|
/// Parse commandline arguments into structured data
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(super) fn parse() -> Args { Args::parse() }
|
pub(crate) fn parse() -> Args { Args::parse() }
|
||||||
|
|
||||||
/// Synthesize any command line options with configuration file options.
|
/// Synthesize any command line options with configuration file options.
|
||||||
pub(crate) fn update(mut config: Figment, args: &Args) -> Result<Figment> {
|
pub(crate) fn update(mut config: Figment, args: &Args) -> Result<Figment> {
|
||||||
|
|
121
src/main/main.rs
121
src/main/main.rs
|
@ -1,120 +1,3 @@
|
||||||
#![type_length_limit = "49152"] //TODO: reduce me
|
use conduwuit::Result;
|
||||||
|
|
||||||
pub(crate) mod clap;
|
fn main() -> Result<()> { conduwuit::run() }
|
||||||
mod logging;
|
|
||||||
mod mods;
|
|
||||||
mod restart;
|
|
||||||
mod runtime;
|
|
||||||
mod sentry;
|
|
||||||
mod server;
|
|
||||||
mod signal;
|
|
||||||
|
|
||||||
use std::sync::{Arc, atomic::Ordering};
|
|
||||||
|
|
||||||
use conduwuit_core::{Error, Result, debug_info, error, rustc_flags_capture};
|
|
||||||
use server::Server;
|
|
||||||
|
|
||||||
rustc_flags_capture! {}
|
|
||||||
|
|
||||||
fn main() -> Result {
|
|
||||||
let args = clap::parse();
|
|
||||||
let runtime = runtime::new(&args)?;
|
|
||||||
let server = Server::new(&args, Some(runtime.handle()))?;
|
|
||||||
|
|
||||||
runtime.spawn(signal::signal(server.clone()));
|
|
||||||
runtime.block_on(async_main(&server))?;
|
|
||||||
runtime::shutdown(&server, runtime);
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
if server.server.restarting.load(Ordering::Acquire) {
|
|
||||||
restart::restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_info!("Exit");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Operate the server normally in release-mode static builds. This will start,
|
|
||||||
/// run and stop the server within the asynchronous runtime.
|
|
||||||
#[cfg(any(not(conduwuit_mods), not(feature = "conduwuit_mods")))]
|
|
||||||
#[tracing::instrument(
|
|
||||||
name = "main",
|
|
||||||
parent = None,
|
|
||||||
skip_all
|
|
||||||
)]
|
|
||||||
async fn async_main(server: &Arc<Server>) -> Result<(), Error> {
|
|
||||||
extern crate conduwuit_router as router;
|
|
||||||
|
|
||||||
match router::start(&server.server).await {
|
|
||||||
| Ok(services) => server.services.lock().await.insert(services),
|
|
||||||
| Err(error) => {
|
|
||||||
error!("Critical error starting server: {error}");
|
|
||||||
return Err(error);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(error) = router::run(
|
|
||||||
server
|
|
||||||
.services
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.as_ref()
|
|
||||||
.expect("services initialized"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
error!("Critical error running server: {error}");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(error) = router::stop(
|
|
||||||
server
|
|
||||||
.services
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.take()
|
|
||||||
.expect("services initialized"),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
error!("Critical error stopping server: {error}");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_info!("Exit runtime");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Operate the server in developer-mode dynamic builds. This will start, run,
|
|
||||||
/// and hot-reload portions of the server as-needed before returning for an
|
|
||||||
/// actual shutdown. This is not available in release-mode or static builds.
|
|
||||||
#[cfg(all(conduwuit_mods, feature = "conduwuit_mods"))]
|
|
||||||
async fn async_main(server: &Arc<Server>) -> Result<(), Error> {
|
|
||||||
let mut starts = true;
|
|
||||||
let mut reloads = true;
|
|
||||||
while reloads {
|
|
||||||
if let Err(error) = mods::open(server).await {
|
|
||||||
error!("Loading router: {error}");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = mods::run(server, starts).await;
|
|
||||||
if let Ok(result) = result {
|
|
||||||
(starts, reloads) = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let force = !reloads || result.is_err();
|
|
||||||
if let Err(error) = mods::close(server, force).await {
|
|
||||||
error!("Unloading router: {error}");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(error) = result {
|
|
||||||
error!("{error}");
|
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_info!("Exit runtime");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
119
src/main/mod.rs
119
src/main/mod.rs
|
@ -1,8 +1,10 @@
|
||||||
#![type_length_limit = "49152"] //TODO: reduce me
|
#![type_length_limit = "49152"] //TODO: reduce me
|
||||||
|
|
||||||
use conduwuit_core::rustc_flags_capture;
|
use std::sync::{Arc, atomic::Ordering};
|
||||||
|
|
||||||
pub(crate) mod clap;
|
use conduwuit_core::{debug_info, error, rustc_flags_capture};
|
||||||
|
|
||||||
|
mod clap;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod mods;
|
mod mods;
|
||||||
mod restart;
|
mod restart;
|
||||||
|
@ -11,4 +13,117 @@ mod sentry;
|
||||||
mod server;
|
mod server;
|
||||||
mod signal;
|
mod signal;
|
||||||
|
|
||||||
|
use server::Server;
|
||||||
|
|
||||||
rustc_flags_capture! {}
|
rustc_flags_capture! {}
|
||||||
|
|
||||||
|
pub use conduwuit_core::{Error, Result};
|
||||||
|
|
||||||
|
pub use crate::clap::Args;
|
||||||
|
|
||||||
|
pub fn run() -> Result<()> {
|
||||||
|
let args = clap::parse();
|
||||||
|
run_with_args(&args)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_with_args(args: &Args) -> Result<()> {
|
||||||
|
let runtime = runtime::new(args)?;
|
||||||
|
let server = Server::new(args, Some(runtime.handle()))?;
|
||||||
|
|
||||||
|
runtime.spawn(signal::signal(server.clone()));
|
||||||
|
runtime.block_on(async_main(&server))?;
|
||||||
|
runtime::shutdown(&server, runtime);
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
if server.server.restarting.load(Ordering::Acquire) {
|
||||||
|
restart::restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_info!("Exit");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Operate the server normally in release-mode static builds. This will start,
|
||||||
|
/// run and stop the server within the asynchronous runtime.
|
||||||
|
#[cfg(any(not(conduwuit_mods), not(feature = "conduwuit_mods")))]
|
||||||
|
#[tracing::instrument(
|
||||||
|
name = "main",
|
||||||
|
parent = None,
|
||||||
|
skip_all
|
||||||
|
)]
|
||||||
|
async fn async_main(server: &Arc<Server>) -> Result<(), Error> {
|
||||||
|
extern crate conduwuit_router as router;
|
||||||
|
|
||||||
|
match router::start(&server.server).await {
|
||||||
|
| Ok(services) => server.services.lock().await.insert(services),
|
||||||
|
| Err(error) => {
|
||||||
|
error!("Critical error starting server: {error}");
|
||||||
|
return Err(error);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = router::run(
|
||||||
|
server
|
||||||
|
.services
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.as_ref()
|
||||||
|
.expect("services initialized"),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!("Critical error running server: {error}");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(error) = router::stop(
|
||||||
|
server
|
||||||
|
.services
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.take()
|
||||||
|
.expect("services initialized"),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!("Critical error stopping server: {error}");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_info!("Exit runtime");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Operate the server in developer-mode dynamic builds. This will start, run,
|
||||||
|
/// and hot-reload portions of the server as-needed before returning for an
|
||||||
|
/// actual shutdown. This is not available in release-mode or static builds.
|
||||||
|
#[cfg(all(conduwuit_mods, feature = "conduwuit_mods"))]
|
||||||
|
async fn async_main(server: &Arc<Server>) -> Result<(), Error> {
|
||||||
|
let mut starts = true;
|
||||||
|
let mut reloads = true;
|
||||||
|
while reloads {
|
||||||
|
if let Err(error) = mods::open(server).await {
|
||||||
|
error!("Loading router: {error}");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = mods::run(server, starts).await;
|
||||||
|
if let Ok(result) = result {
|
||||||
|
(starts, reloads) = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let force = !reloads || result.is_err();
|
||||||
|
if let Err(error) = mods::close(server, force).await {
|
||||||
|
error!("Unloading router: {error}");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(error) = result {
|
||||||
|
error!("{error}");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_info!("Exit runtime");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,10 @@ use conduwuit_core::{
|
||||||
};
|
};
|
||||||
use tokio::{runtime, sync::Mutex};
|
use tokio::{runtime, sync::Mutex};
|
||||||
|
|
||||||
use crate::{clap::Args, logging::TracingFlameGuard};
|
use crate::{
|
||||||
|
clap::{Args, update},
|
||||||
|
logging::TracingFlameGuard,
|
||||||
|
};
|
||||||
|
|
||||||
/// Server runtime state; complete
|
/// Server runtime state; complete
|
||||||
pub(crate) struct Server {
|
pub(crate) struct Server {
|
||||||
|
@ -43,7 +46,7 @@ impl Server {
|
||||||
.map(PathBuf::as_path);
|
.map(PathBuf::as_path);
|
||||||
|
|
||||||
let config = Config::load(config_paths)
|
let config = Config::load(config_paths)
|
||||||
.and_then(|raw| crate::clap::update(raw, args))
|
.and_then(|raw| update(raw, args))
|
||||||
.and_then(|raw| Config::new(&raw))?;
|
.and_then(|raw| Config::new(&raw))?;
|
||||||
|
|
||||||
let (tracing_reload_handle, tracing_flame_guard, capture) =
|
let (tracing_reload_handle, tracing_flame_guard, capture) =
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::{self, Write},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use clap_builder::{Command, CommandFactory};
|
|
||||||
use conduwuit_admin::AdminCommand;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let mut args = std::env::args().skip(1);
|
|
||||||
let task = args.next();
|
|
||||||
match task {
|
|
||||||
| None => todo!(),
|
|
||||||
| Some(t) => match t.as_str() {
|
|
||||||
| "man" => {
|
|
||||||
let dir = Path::new("./admin-man");
|
|
||||||
gen_manpages(dir)?;
|
|
||||||
},
|
|
||||||
| "md" => {
|
|
||||||
let command = AdminCommand::command().name("admin");
|
|
||||||
|
|
||||||
let res = clap_markdown::help_markdown_command_custom(
|
|
||||||
&command,
|
|
||||||
&clap_markdown::MarkdownOptions::default().show_footer(false),
|
|
||||||
)
|
|
||||||
.replace("\n\r", "\n")
|
|
||||||
.replace("\r\n", "\n")
|
|
||||||
.replace(" \n", "\n");
|
|
||||||
|
|
||||||
let mut file = File::create(Path::new("./docs/admin_reference.md"))?;
|
|
||||||
Write::write_all(&mut file, res.trim_end().as_bytes())?;
|
|
||||||
file.write(b"\n")?;
|
|
||||||
},
|
|
||||||
| invalid => return Err(format!("Invalid task name: {invalid}").into()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_manpages(dir: &Path) -> Result<(), io::Error> {
|
|
||||||
fn r#gen(dir: &Path, c: &Command, prefix: Option<&str>) -> Result<(), io::Error> {
|
|
||||||
fs::create_dir_all(dir)?;
|
|
||||||
let sub_name = c.get_display_name().unwrap_or_else(|| c.get_name());
|
|
||||||
let name = if let Some(prefix) = prefix {
|
|
||||||
format!("{prefix}-{sub_name}")
|
|
||||||
} else {
|
|
||||||
sub_name.to_owned()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut out = File::create(dir.join(format!("{name}.1")))?;
|
|
||||||
let clap_mangen = clap_mangen::Man::new(c.to_owned().disable_help_flag(true));
|
|
||||||
clap_mangen.render(&mut out)?;
|
|
||||||
|
|
||||||
for sub in c.get_subcommands() {
|
|
||||||
r#gen(&dir.join(sub_name), sub, Some(&name))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
r#gen(dir, &AdminCommand::command().name("admin"), None)
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "xtask-admin-command"
|
name = "xtask-generate-commands"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
description.workspace = true
|
description.workspace = true
|
113
xtask/generate-generate-commands/src/main.rs
Normal file
113
xtask/generate-generate-commands/src/main.rs
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
use std::{
|
||||||
|
fs::{self, File},
|
||||||
|
io::{self, Write},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
use clap_builder::{Command, CommandFactory};
|
||||||
|
use conduwuit_admin::AdminCommand;
|
||||||
|
|
||||||
|
enum CommandType {
|
||||||
|
Admin,
|
||||||
|
Server,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut args = std::env::args().skip(1);
|
||||||
|
let command_type = args.next();
|
||||||
|
let task = args.next();
|
||||||
|
|
||||||
|
match (command_type, task) {
|
||||||
|
| (None, _) => {
|
||||||
|
return Err("Missing command type (admin or server)".into());
|
||||||
|
},
|
||||||
|
| (Some(cmd_type), None) => {
|
||||||
|
return Err(format!("Missing task for {cmd_type} command").into());
|
||||||
|
},
|
||||||
|
| (Some(cmd_type), Some(task)) => {
|
||||||
|
let command_type = match cmd_type.as_str() {
|
||||||
|
| "admin" => CommandType::Admin,
|
||||||
|
| "server" => CommandType::Server,
|
||||||
|
| _ => return Err(format!("Invalid command type: {cmd_type}").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
match task.as_str() {
|
||||||
|
| "man" => match command_type {
|
||||||
|
| CommandType::Admin => {
|
||||||
|
let dir = Path::new("./admin-man");
|
||||||
|
gen_admin_manpages(dir)?;
|
||||||
|
},
|
||||||
|
| CommandType::Server => {
|
||||||
|
let dir = Path::new("./server-man");
|
||||||
|
gen_server_manpages(dir)?;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
| "md" => {
|
||||||
|
match command_type {
|
||||||
|
| CommandType::Admin => {
|
||||||
|
let command = AdminCommand::command().name("admin");
|
||||||
|
|
||||||
|
let res = clap_markdown::help_markdown_command_custom(
|
||||||
|
&command,
|
||||||
|
&clap_markdown::MarkdownOptions::default().show_footer(false),
|
||||||
|
)
|
||||||
|
.replace("\n\r", "\n")
|
||||||
|
.replace("\r\n", "\n")
|
||||||
|
.replace(" \n", "\n");
|
||||||
|
|
||||||
|
let mut file = File::create(Path::new("./docs/admin_reference.md"))?;
|
||||||
|
file.write_all(res.trim_end().as_bytes())?;
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
},
|
||||||
|
| CommandType::Server => {
|
||||||
|
// Get the server command from the conduwuit crate
|
||||||
|
let command = conduwuit::Args::command();
|
||||||
|
|
||||||
|
let res = clap_markdown::help_markdown_command_custom(
|
||||||
|
&command,
|
||||||
|
&clap_markdown::MarkdownOptions::default().show_footer(false),
|
||||||
|
)
|
||||||
|
.replace("\n\r", "\n")
|
||||||
|
.replace("\r\n", "\n")
|
||||||
|
.replace(" \n", "\n");
|
||||||
|
|
||||||
|
let mut file = File::create(Path::new("./docs/server_reference.md"))?;
|
||||||
|
file.write_all(res.trim_end().as_bytes())?;
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
| invalid => return Err(format!("Invalid task name: {invalid}").into()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_manpage_common(dir: &Path, c: &Command, prefix: Option<&str>) -> Result<(), io::Error> {
|
||||||
|
fs::create_dir_all(dir)?;
|
||||||
|
let sub_name = c.get_display_name().unwrap_or_else(|| c.get_name());
|
||||||
|
let name = if let Some(prefix) = prefix {
|
||||||
|
format!("{prefix}-{sub_name}")
|
||||||
|
} else {
|
||||||
|
sub_name.to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut out = File::create(dir.join(format!("{name}.1")))?;
|
||||||
|
let clap_mangen = clap_mangen::Man::new(c.to_owned().disable_help_flag(true));
|
||||||
|
clap_mangen.render(&mut out)?;
|
||||||
|
|
||||||
|
for sub in c.get_subcommands() {
|
||||||
|
gen_manpage_common(&dir.join(sub_name), sub, Some(&name))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_admin_manpages(dir: &Path) -> Result<(), io::Error> {
|
||||||
|
gen_manpage_common(dir, &AdminCommand::command().name("admin"), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_server_manpages(dir: &Path) -> Result<(), io::Error> {
|
||||||
|
gen_manpage_common(dir, &conduwuit::Args::command(), None)
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ version.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
# Required for working with JSON output from cargo metadata
|
# Required for working with JSON output from cargo metadata
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde.workspace = true
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{env, process::Command};
|
use std::{env, process::Command};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut child = Command::new("cargo").args(["run", "--package", "xtask-admin-command", "--"].into_iter().map(ToOwned::to_owned).chain(env::args().skip(2)))
|
let mut child = Command::new("cargo").args(["run", "--package", "xtask-generate-commands", "--"].into_iter().map(ToOwned::to_owned).chain(env::args().skip(2)))
|
||||||
// .stdout(Stdio::piped())
|
// .stdout(Stdio::piped())
|
||||||
// .stderr(Stdio::piped())
|
// .stderr(Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
|
|
Loading…
Add table
Reference in a new issue