refactor: move schema generation to its own binary, go back to lib-bin (#1630)
* refactor: separate schema generation to its own binary, go back to lib-bin setup Decided it might be nicer to separate the schema generation bit to its own binary. This does mean that we have to go back to the lib-bin system, as otherwise passing shared code is _really_ hard. * handle versioning * run fmt
This commit is contained in:
parent
196d6d18c6
commit
24cb8a417c
17
Cargo.toml
17
Cargo.toml
|
@ -40,13 +40,24 @@ exclude = [
|
|||
# The oldest version I've tested that should still build - note this is not an official MSRV!
|
||||
rust-version = "1.81.0"
|
||||
|
||||
[[bin]]
|
||||
name = "btm"
|
||||
path = "src/main.rs"
|
||||
[lib]
|
||||
test = true
|
||||
doctest = true
|
||||
doc = true
|
||||
|
||||
[[bin]]
|
||||
name = "btm"
|
||||
path = "src/bin/main.rs"
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "schema"
|
||||
path = "src/bin/schema.rs"
|
||||
test = false
|
||||
doctest = false
|
||||
doc = false
|
||||
required-features = ["generate_schema"]
|
||||
|
||||
# Compile dependencies with optimizations enabled, even in debug mode.
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
|
|
|
@ -5,4 +5,4 @@ set -e
|
|||
cd "$(dirname "$0")";
|
||||
cd ../..
|
||||
|
||||
cargo run --features="generate_schema" -- --generate_schema > schema/nightly/bottom.json
|
||||
cargo run --bin schema --features="generate_schema" -- $1 > schema/nightly/bottom.json
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
use bottom::start_bottom;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
start_bottom()
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#![cfg(feature = "generate_schema")]
|
||||
|
||||
use bottom::{options::config, widgets};
|
||||
use clap::Parser;
|
||||
use itertools::Itertools;
|
||||
use strum::VariantArray;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct SchemaOptions {
|
||||
/// The version of the schema.
|
||||
version: Option<String>,
|
||||
}
|
||||
|
||||
fn generate_schema(schema_options: SchemaOptions) -> anyhow::Result<()> {
|
||||
let mut schema = schemars::schema_for!(config::Config);
|
||||
{
|
||||
// TODO: Maybe make this case insensitive? See https://stackoverflow.com/a/68639341
|
||||
|
||||
let proc_columns = schema.definitions.get_mut("ProcColumn").unwrap();
|
||||
match proc_columns {
|
||||
schemars::schema::Schema::Object(proc_columns) => {
|
||||
let enums = proc_columns.enum_values.as_mut().unwrap();
|
||||
*enums = widgets::ProcColumn::VARIANTS
|
||||
.iter()
|
||||
.flat_map(|var| var.get_schema_names())
|
||||
.sorted()
|
||||
.map(|v| serde_json::Value::String(v.to_string()))
|
||||
.dedup()
|
||||
.collect();
|
||||
}
|
||||
_ => anyhow::bail!("missing proc columns definition"),
|
||||
}
|
||||
|
||||
let disk_columns = schema.definitions.get_mut("DiskColumn").unwrap();
|
||||
match disk_columns {
|
||||
schemars::schema::Schema::Object(disk_columns) => {
|
||||
let enums = disk_columns.enum_values.as_mut().unwrap();
|
||||
*enums = widgets::DiskColumn::VARIANTS
|
||||
.iter()
|
||||
.flat_map(|var| var.get_schema_names())
|
||||
.sorted()
|
||||
.map(|v| serde_json::Value::String(v.to_string()))
|
||||
.dedup()
|
||||
.collect();
|
||||
}
|
||||
_ => anyhow::bail!("missing disk columns definition"),
|
||||
}
|
||||
}
|
||||
|
||||
let metadata = schema.schema.metadata.as_mut().unwrap();
|
||||
let version = schema_options.version.unwrap_or("nightly".to_string());
|
||||
metadata.id = Some(format!(
|
||||
"https://github.com/ClementTsang/bottom/blob/main/schema/{version}/bottom.json"
|
||||
));
|
||||
metadata.description = Some(format!(
|
||||
"https://clementtsang.github.io/bottom/{}/configuration/config-file",
|
||||
if version == "nightly" {
|
||||
"nightly"
|
||||
} else {
|
||||
"stable"
|
||||
}
|
||||
));
|
||||
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let schema_options = SchemaOptions::parse();
|
||||
generate_schema(schema_options)?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -3,8 +3,7 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use super::ProcessHarvest;
|
||||
use crate::data_collection::error::CollectionResult;
|
||||
use crate::data_collection::DataCollector;
|
||||
use crate::data_collection::{error::CollectionResult, DataCollector};
|
||||
|
||||
// TODO: There's a lot of shared code with this and the unix impl.
|
||||
pub fn sysinfo_process_data(
|
||||
|
|
|
@ -272,67 +272,13 @@ fn create_collection_thread(
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "generate_schema")]
|
||||
fn generate_schema() -> anyhow::Result<()> {
|
||||
let mut schema = schemars::schema_for!(crate::options::config::Config);
|
||||
{
|
||||
use itertools::Itertools;
|
||||
use strum::VariantArray;
|
||||
|
||||
// TODO: Maybe make this case insensitive? See https://stackoverflow.com/a/68639341
|
||||
|
||||
let proc_columns = schema.definitions.get_mut("ProcColumn").unwrap();
|
||||
match proc_columns {
|
||||
schemars::schema::Schema::Object(proc_columns) => {
|
||||
let enums = proc_columns.enum_values.as_mut().unwrap();
|
||||
*enums = widgets::ProcColumn::VARIANTS
|
||||
.iter()
|
||||
.flat_map(|var| var.get_schema_names())
|
||||
.sorted()
|
||||
.map(|v| serde_json::Value::String(v.to_string()))
|
||||
.dedup()
|
||||
.collect();
|
||||
}
|
||||
_ => anyhow::bail!("missing proc columns definition"),
|
||||
}
|
||||
|
||||
let disk_columns = schema.definitions.get_mut("DiskColumn").unwrap();
|
||||
match disk_columns {
|
||||
schemars::schema::Schema::Object(disk_columns) => {
|
||||
let enums = disk_columns.enum_values.as_mut().unwrap();
|
||||
*enums = widgets::DiskColumn::VARIANTS
|
||||
.iter()
|
||||
.flat_map(|var| var.get_schema_names())
|
||||
.sorted()
|
||||
.map(|v| serde_json::Value::String(v.to_string()))
|
||||
.dedup()
|
||||
.collect();
|
||||
}
|
||||
_ => anyhow::bail!("missing disk columns definition"),
|
||||
}
|
||||
}
|
||||
|
||||
let metadata = schema.schema.metadata.as_mut().unwrap();
|
||||
metadata.id = Some(
|
||||
"https://github.com/ClementTsang/bottom/blob/main/schema/nightly/bottom.json".to_string(),
|
||||
);
|
||||
metadata.description =
|
||||
Some("https://clementtsang.github.io/bottom/nightly/configuration/config-file".to_string());
|
||||
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
/// Main code to call.
|
||||
#[inline]
|
||||
pub fn start_bottom() -> anyhow::Result<()> {
|
||||
// let _profiler = dhat::Profiler::new_heap();
|
||||
|
||||
let args = args::get_args();
|
||||
|
||||
#[cfg(feature = "generate_schema")]
|
||||
if args.other.generate_schema {
|
||||
return generate_schema();
|
||||
}
|
||||
|
||||
#[cfg(feature = "logging")]
|
||||
{
|
||||
if let Err(err) = init_logger(
|
|
@ -195,6 +195,7 @@ pub fn get_or_create_config(config_path: Option<&Path>) -> anyhow::Result<Config
|
|||
}
|
||||
}
|
||||
|
||||
/// Initialize the app.
|
||||
pub(crate) fn init_app(
|
||||
args: BottomArgs, config: Config,
|
||||
) -> Result<(App, BottomLayout, ColourPalette)> {
|
||||
|
@ -1235,10 +1236,10 @@ mod test {
|
|||
#[cfg(target_os = "macos")]
|
||||
#[test]
|
||||
fn test_get_config_path_macos() {
|
||||
use super::get_config_path;
|
||||
use super::DEFAULT_CONFIG_FILE_LOCATION;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::{get_config_path, DEFAULT_CONFIG_FILE_LOCATION};
|
||||
|
||||
// Case three: no previous config, no XDG var.
|
||||
// SAFETY: this is the only test that does this
|
||||
unsafe {
|
||||
|
|
|
@ -566,10 +566,6 @@ pub struct OtherArgs {
|
|||
|
||||
#[arg(short = 'V', long, action = ArgAction::Version, help = "Prints version information.")]
|
||||
version: (),
|
||||
|
||||
#[cfg(feature = "generate_schema")]
|
||||
#[arg(long, action = ArgAction::SetTrue)]
|
||||
pub generate_schema: bool,
|
||||
}
|
||||
|
||||
/// Returns a [`BottomArgs`].
|
||||
|
|
|
@ -18,6 +18,7 @@ use temperature::TempConfig;
|
|||
pub use self::ignore_list::IgnoreList;
|
||||
use self::{cpu::CpuConfig, layout::Row, process::ProcessesConfig};
|
||||
|
||||
/// Overall config for `bottom`.
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "generate_schema",
|
||||
|
@ -65,9 +66,10 @@ mod test {
|
|||
#[test]
|
||||
#[cfg(feature = "default")]
|
||||
fn test_integration_valid_configs() {
|
||||
use super::Config;
|
||||
use std::fs;
|
||||
|
||||
use super::Config;
|
||||
|
||||
for config_path in fs::read_dir("./tests/valid_configs").unwrap() {
|
||||
let config_path = config_path.unwrap();
|
||||
let config_path_str = config_path.path().display().to_string();
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::options::DiskColumn;
|
||||
|
||||
use super::IgnoreList;
|
||||
use crate::options::DiskColumn;
|
||||
|
||||
/// Disk configuration.
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
|
|
|
@ -23,9 +23,8 @@ use tui::style::Style;
|
|||
use utils::{opt, set_colour, set_colour_list, set_style};
|
||||
use widgets::WidgetStyle;
|
||||
|
||||
use crate::options::{args::BottomArgs, OptionError, OptionResult};
|
||||
|
||||
use super::Config;
|
||||
use crate::options::{args::BottomArgs, OptionError, OptionResult};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))]
|
||||
|
|
|
@ -17,4 +17,5 @@ macro_rules! hex {
|
|||
};
|
||||
}
|
||||
|
||||
pub(super) use {color, hex};
|
||||
pub(super) use color;
|
||||
pub(super) use hex;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use tui::style::{Color, Modifier, Style};
|
||||
|
||||
use crate::options::config::style::ColourPalette;
|
||||
|
||||
use super::color;
|
||||
use crate::options::config::style::ColourPalette;
|
||||
|
||||
impl ColourPalette {
|
||||
pub(crate) fn default_palette() -> Self {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use tui::style::{Color, Modifier};
|
||||
|
||||
use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette};
|
||||
|
||||
use super::{color, hex};
|
||||
use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette};
|
||||
|
||||
impl ColourPalette {
|
||||
pub(crate) fn gruvbox_palette() -> Self {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use tui::style::{Color, Modifier};
|
||||
|
||||
use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette};
|
||||
|
||||
use super::{color, hex};
|
||||
use crate::options::config::style::{utils::convert_hex_to_color, ColourPalette};
|
||||
|
||||
impl ColourPalette {
|
||||
pub(crate) fn nord_palette() -> Self {
|
||||
|
|
|
@ -247,16 +247,18 @@ macro_rules! set_colour_list {
|
|||
};
|
||||
}
|
||||
|
||||
pub(super) use {opt, set_colour, set_colour_list, set_style};
|
||||
pub(super) use opt;
|
||||
pub(super) use set_colour;
|
||||
pub(super) use set_colour_list;
|
||||
pub(super) use set_style;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use tui::style::{Modifier, Style};
|
||||
|
||||
use crate::options::config::style::{ColorStr, TextStyleConfig};
|
||||
|
||||
use super::*;
|
||||
use crate::options::config::style::{ColorStr, TextStyleConfig};
|
||||
|
||||
#[test]
|
||||
fn general_str_to_colour() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Tests config files that have sometimes caused issues despite being valid.
|
||||
|
||||
use std::{io::Read, thread, time::Duration};
|
||||
|
||||
#[cfg(feature = "default")]
|
||||
use std::{io::Write, path::Path};
|
||||
|
||||
|
|
Loading…
Reference in New Issue