Skip to content

Commit

Permalink
feat: improve markdown option list output
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma committed Feb 6, 2025
1 parent e39c0bc commit f4f4c88
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 130 deletions.
2 changes: 1 addition & 1 deletion release
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cargo update
cargo check
cargo test --bins

RUST_LOG=warn cargo run -- list-systemd-options > systemd_options.md
RUST_LOG=warn cargo run -- list-systemd-options | head -n -1 > systemd_options.md

git add Cargo.{toml,lock} systemd_options.md

Expand Down
28 changes: 10 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
)]

use std::{
env,
fs::{self, File},
thread,
io, thread,
};

use anyhow::Context as _;
Expand Down Expand Up @@ -39,9 +40,10 @@ fn sd_options(
#[cfg(feature = "gen-man-pages")]
fn main() -> anyhow::Result<()> {
use clap::CommandFactory as _;

// Use the binary name instead of the default of the package name
let cmd = cl::Args::command().name(env!("CARGO_BIN_NAME"));
let output = std::env::args_os()
let output = env::args_os()
.nth(1)
.ok_or_else(|| anyhow::anyhow!("Missing output dir argument"))?;
clap_mangen::generate_to(cmd, output)?;
Expand All @@ -50,8 +52,6 @@ fn main() -> anyhow::Result<()> {

#[cfg(not(feature = "gen-man-pages"))]
fn main() -> anyhow::Result<()> {
use std::env;

// Init logger
simple_logger::SimpleLogger::new()
.with_level(if cfg!(debug_assertions) {
Expand Down Expand Up @@ -253,20 +253,12 @@ fn main() -> anyhow::Result<()> {
&cl::HardeningOptions::strict(),
);
sd_opts.sort_unstable_by_key(|o| o.name);
for sd_opt in sd_opts {
println!("- [`{sd_opt}`](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#{sd_opt}=)");
for opt_val in sd_opt.possible_values {
match opt_val.value {
systemd::OptionValue::Boolean(v) => {
println!(" - `{}`", if v { "true" } else { "false" });
}
systemd::OptionValue::String(v) => println!(" - `{v}`"),
systemd::OptionValue::List(systemd::ListOptionValue { values, .. }) => {
for val in values {
println!(" - `{val}`");
}
}
}
{
let mut stdout = io::stdout().lock();
for sd_opt in sd_opts {
sd_opt
.write_markdown(&mut stdout)
.context("Failed to write markdown output")?;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/systemd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod service;
mod version;

pub(crate) use options::{
build_options, ListOptionValue, OptionDescription, OptionValue, SocketFamily, SocketProtocol,
build_options, ListOptionValue, OptionDescription, SocketFamily, SocketProtocol,
};
pub(crate) use resolver::resolve;
pub(crate) use service::Service;
Expand Down
70 changes: 69 additions & 1 deletion src/systemd/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
use std::{
borrow::ToOwned,
collections::{HashMap, HashSet},
fmt, fs, iter,
fmt, fs,
io::{self, Write},
iter,
num::NonZeroUsize,
os::unix::ffi::OsStrExt as _,
path::{Path, PathBuf},
Expand All @@ -32,6 +34,8 @@ pub(crate) struct OptionUpdater {
fn(&OptionValueEffect, &ProgramAction, &HardeningOptions) -> Option<OptionValueEffect>,
/// Generate new options from the new effect
pub options: fn(&OptionValueEffect, &HardeningOptions) -> Vec<OptionWithValue<&'static str>>,
/// Names of the options that might be generated by the updater (used for markdown option list generation)
pub dynamic_option_names: Vec<&'static str>,
}

/// Systemd option with its possibles values, and their effect
Expand All @@ -42,6 +46,62 @@ pub(crate) struct OptionDescription {
pub updater: Option<OptionUpdater>,
}

impl OptionDescription {
pub(crate) fn write_markdown<W: Write>(&self, w: &mut W) -> io::Result<()> {
const MARKDOWN_IDENT: &str = " ";
writeln!(w, "- [`{}`](https://www.freedesktop.org/software/systemd/man/latest/systemd.directives.html#{}=)\n", self.name, self.name)?;
for opt_val in &self.possible_values {
if let OptionValue::List(list) = &opt_val.value {
writeln!(
w,
"{}- *dynamic {}{}*",
MARKDOWN_IDENT,
if list.mergeable_paths { "path " } else { "" },
match list.mode {
ListMode::BlackList => "blacklisting",
ListMode::WhiteList => "whitelisting",
}
)?;
break;
}
match &opt_val.value {
OptionValue::Boolean(v) => {
writeln!(
w,
"{}- `{}`",
MARKDOWN_IDENT,
if *v { "true" } else { "false" }
)?;
}
OptionValue::String(v) => writeln!(w, "{MARKDOWN_IDENT}- `{v}`")?,
OptionValue::List(ListOptionValue { values, .. }) => {
for val in values {
writeln!(w, "{MARKDOWN_IDENT}- `{val}`")?;
}
}
}
}
if let Some(updater) = &self.updater {
let mut first = true;
for new_opt_name in updater
.dynamic_option_names
.iter()
.filter(|n| **n != self.name)
{
if first {
writeln!(
w,
"{MARKDOWN_IDENT}- to support this option, other options may be dynamically enabled:",
)?;
first = false;
}
writeln!(w, "{MARKDOWN_IDENT}{MARKDOWN_IDENT}- [`{new_opt_name}`](https://www.freedesktop.org/software/systemd/man/latest/systemd.directives.html#{new_opt_name}=)")?;
}
}
writeln!(w)
}
}

impl fmt::Display for OptionDescription {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.name.fmt(f)
Expand Down Expand Up @@ -1359,6 +1419,7 @@ pub(crate) fn build_options(
}
_ => unreachable!(),
},
dynamic_option_names: Vec::from(["ReadOnlyPaths", "ReadWritePaths"]),
}),
});

Expand Down Expand Up @@ -1596,6 +1657,11 @@ pub(crate) fn build_options(
}
_ => unreachable!(),
},
dynamic_option_names: Vec::from([
"TemporaryFileSystem",
"BindReadOnlyPaths",
"BindPaths",
]),
}),
});

Expand Down Expand Up @@ -1671,6 +1737,7 @@ pub(crate) fn build_options(
}
_ => unreachable!(),
},
dynamic_option_names: Vec::from(["NoExecPaths", "ExecPaths"]),
}),
});
}
Expand Down Expand Up @@ -1885,6 +1952,7 @@ pub(crate) fn build_options(
}),
}]
},
dynamic_option_names: Vec::from(["SocketBindDeny"]),
}),
});

Expand Down
Loading

0 comments on commit f4f4c88

Please sign in to comment.