feat(args): add --load argument for preloading values

This commit is contained in:
Orhun Parmaksız 2021-12-09 22:16:59 +03:00
parent 762c25a84d
commit a56d562f3d
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
4 changed files with 52 additions and 18 deletions

View file

@ -9,3 +9,6 @@ pub mod display;
/// Kernel parameter.
pub mod parameter;
/// Default location to preload values.
pub const DEFAULT_PRELOAD: &str = "/etc/sysctl.conf";

View file

@ -8,6 +8,7 @@ use systeroid_core::error::Result;
use systeroid_core::parsers::KERNEL_DOCS_PATH;
use systeroid_core::regex::Regex;
use systeroid_core::sysctl::controller::Sysctl;
use systeroid_parser::reader;
/// Label for caching the kernel parameters.
const PARAMETERS_CACHE_LABEL: &str = "parameters";
@ -109,28 +110,45 @@ impl<'a> App<'a> {
}
/// Updates the parameter if it has the format `name=value`, displays it otherwise.
pub fn process_parameter(&mut self, mut param_name: String) -> Result<()> {
let new_value = if param_name.contains('=') {
let fields = param_name
pub fn process_parameter(&mut self, mut parameter: String, display_value: bool) -> Result<()> {
let new_value = if parameter.contains('=') {
let fields = parameter
.split('=')
.take(2)
.map(|v| v.trim().to_string())
.collect::<Vec<String>>();
param_name = fields[0].to_string();
Some(fields[1].to_string())
parameter = fields[0].to_string();
Some(fields[1..].join("="))
} else {
None
};
if let Some(new_value) = new_value {
if let Some(parameter) = self.sysctl.get_parameter(&param_name) {
parameter.update_value(&new_value, self.config, &mut self.stdout)?;
if let Some(param) = self.sysctl.get_parameter(&parameter) {
param.update_value(&new_value, self.config, &mut self.stdout)?;
}
} else {
} else if display_value {
self.sysctl
.get_parameters(&param_name)
.get_parameters(&parameter)
.iter()
.try_for_each(|parameter| parameter.display_value(self.config, &mut self.stdout))?;
}
Ok(())
}
/// Processes the parameters in the given file.
pub fn preload_values(&mut self, file: String) -> Result<()> {
let path = PathBuf::from(file);
if !path.exists() {
eprintln!(
"{}: cannot open {:?}: No such file or directory",
env!("CARGO_PKG_NAME"),
path
);
return Ok(());
}
let contents = reader::read_to_string(path)?;
for parameter in contents.lines() {
self.process_parameter(parameter.to_string(), false)?;
}
Ok(())
}
}

View file

@ -3,6 +3,7 @@ use std::env;
use std::path::PathBuf;
use systeroid_core::regex::Regex;
use systeroid_core::sysctl::display::DisplayType;
use systeroid_core::sysctl::DEFAULT_PRELOAD;
/// Help message for the arguments.
const HELP_MESSAGE: &str = r#"
@ -29,12 +30,14 @@ pub struct Args {
pub ignore_errors: bool,
/// Do not pipe output into a pager.
pub no_pager: bool,
/// Whether if files are given to preload values.
pub preload_files: bool,
/// Pattern for matching the parameters.
pub pattern: Option<Regex>,
/// Parameter to explain.
pub param_to_explain: Option<String>,
/// Parameter names.
pub param_names: Vec<String>,
/// Free string fragments.
pub values: Vec<String>,
}
impl Args {
@ -48,6 +51,7 @@ impl Args {
opts.optflag("e", "ignore", "ignore unknown variables errors");
opts.optflag("N", "names", "print variable names without values");
opts.optflag("n", "values", "print only values of the given variable(s)");
opts.optflag("p", "load", "read values from file");
opts.optopt(
"r",
"pattern",
@ -73,7 +77,7 @@ impl Args {
opts.optflag("V", "version", "output version information and exit");
let env_args = env::args().collect::<Vec<String>>();
let matches = opts
let mut matches = opts
.parse(&env_args[1..])
.map_err(|e| eprintln!("error: `{}`", e))
.ok()?;
@ -82,7 +86,8 @@ impl Args {
|| matches.opt_present("A")
|| matches.opt_present("X")
|| !matches.free.is_empty()
|| matches.opt_str("explain").is_some();
|| matches.opt_str("explain").is_some()
|| matches.opt_present("p");
if matches.opt_present("h") || env_args.len() == 1 {
let usage = opts.usage_with_format(|opts| {
@ -113,6 +118,9 @@ impl Args {
} else {
DisplayType::Default
};
if matches.opt_present("p") && matches.free.is_empty() {
matches.free = vec![DEFAULT_PRELOAD.to_string()];
}
Some(Args {
verbose: matches.opt_present("v"),
quiet: matches.opt_present("q"),
@ -120,11 +128,12 @@ impl Args {
display_type,
ignore_errors: matches.opt_present("e"),
no_pager: matches.opt_present("P"),
preload_files: matches.opt_present("p"),
pattern: matches
.opt_str("r")
.map(|v| Regex::new(&v).expect("invalid regex")),
param_to_explain: matches.opt_str("E"),
param_names: matches.free,
values: matches.free,
})
}
}

View file

@ -29,11 +29,15 @@ pub fn run(args: Args) -> Result<()> {
if let Some(param) = args.param_to_explain {
app.update_documentation(args.kernel_docs.as_ref())?;
app.display_documentation(&param)?;
} else if args.param_names.is_empty() {
} else if args.values.is_empty() {
app.display_parameters(args.pattern)?;
} else if args.preload_files {
for file in args.values {
app.preload_values(file)?;
}
} else {
for param_name in args.param_names {
app.process_parameter(param_name)?;
for param_name in args.values {
app.process_parameter(param_name, true)?;
}
}