166 lines
4.8 KiB
Rust
166 lines
4.8 KiB
Rust
#[macro_use]
|
|
extern crate serde_derive;
|
|
extern crate toml;
|
|
extern crate fern;
|
|
extern crate chrono;
|
|
#[macro_use]
|
|
extern crate clap;
|
|
#[macro_use]
|
|
extern crate log;
|
|
|
|
use std::fs::File;
|
|
use std::fs;
|
|
use std::io::prelude::*;
|
|
use std::fs::Permissions;
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct Config {
|
|
pub folders: Vec<Folder>,
|
|
pub reduce_to_config: bool,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct Folder {
|
|
pub path: String,
|
|
pub scripts: Vec<Script>,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
pub struct Script {
|
|
pub name: String,
|
|
pub commands: Vec<String>,
|
|
}
|
|
|
|
|
|
fn main() {
|
|
let clap = setup_clap();
|
|
let mut verbosity : usize = 0;
|
|
setup_fern(match clap.occurrences_of("v") {
|
|
0 => log::LogLevelFilter::Error,
|
|
1 => log::LogLevelFilter::Warn,
|
|
2 => log::LogLevelFilter::Info,
|
|
3 => log::LogLevelFilter::Debug,
|
|
4 => log::LogLevelFilter::Trace,
|
|
n => {
|
|
verbosity = n as usize;
|
|
log::LogLevelFilter::Trace
|
|
}
|
|
});
|
|
|
|
check_verbosity(verbosity);
|
|
|
|
let mut file = match File::open("foo.txt") {
|
|
Ok(file) => file,
|
|
Err(_) => {
|
|
error!("error opening file");
|
|
return;
|
|
}
|
|
};
|
|
let mut contents = String::new();
|
|
match file.read_to_string(&mut contents) {
|
|
Ok(_) => info!("read file to string successfully"),
|
|
Err(_) => {
|
|
error!("couldn't read file to string");
|
|
return;
|
|
}
|
|
};
|
|
let config: Config = match toml::from_str(&contents) {
|
|
Ok(config) => {
|
|
info!("successfully deserialized config file");
|
|
config
|
|
}
|
|
Err(_) => {
|
|
error!("couldn't deserialize config file");
|
|
return;
|
|
}
|
|
};
|
|
|
|
for folder in config.folders {
|
|
if config.reduce_to_config {
|
|
match fs::remove_dir_all(&folder.path) {
|
|
Ok(_) => info!("cleared folder {}", folder.path),
|
|
Err(_) => warn!("couldn't clear folder {}", folder.path),
|
|
};
|
|
}
|
|
|
|
match fs::DirBuilder::new().recursive(true).create(&folder.path) {
|
|
Err(_) => warn!("couldn't make sure folder {} existed", folder.path),
|
|
_ => {}
|
|
}
|
|
for script in folder.scripts {
|
|
let mut script_string = String::new();
|
|
script_string.push_str("#!/bin/sh\n");
|
|
script_string.push_str("# DO NOT EDIT THIS MANUALLY\n");
|
|
script_string.push_str("# THIS HAS BEEN GENERATED BY run-parts-gen-rs\n");
|
|
for command in script.commands {
|
|
script_string.push_str(&command);
|
|
script_string.push_str("\n");
|
|
}
|
|
let mut script_file = match File::create(&format!(
|
|
"{}{}{}",
|
|
folder.path,
|
|
std::path::MAIN_SEPARATOR,
|
|
script.name
|
|
)) {
|
|
Ok(file) => file,
|
|
Err(_) => {
|
|
warn!(
|
|
"couldn't open script {}{}{} for writing",
|
|
folder.path,
|
|
std::path::MAIN_SEPARATOR,
|
|
script.name
|
|
);
|
|
continue;
|
|
}
|
|
};
|
|
match script_file.write_all(script_string.as_bytes()) {
|
|
Ok(_) => info!("script {} written successfully", script.name),
|
|
Err(_) => warn!("error writing script {}", script.name),
|
|
};
|
|
match script_file.set_permissions(Permissions::from_mode(0o755)) {
|
|
Ok(_) => info!("made script {} executable", script.name),
|
|
Err(_) => warn!("couldn't make script {} executable", script.name),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn check_verbosity(verbosity: usize) {
|
|
if verbosity > 4 {
|
|
trace!("specifying more than 4 doesn't do anything");
|
|
trace!("did you really expect {} different levels?!", verbosity)
|
|
}
|
|
}
|
|
|
|
fn setup_fern(level: log::LogLevelFilter) {
|
|
match fern::Dispatch::new()
|
|
.format(|out, message, record| {
|
|
out.finish(format_args!(
|
|
"[{}][{}] {}",
|
|
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
|
|
record.level(),
|
|
message
|
|
))
|
|
})
|
|
.level(level)
|
|
.chain(std::io::stdout())
|
|
.apply() {
|
|
Err(_) => {
|
|
eprintln!("error setting up logging!");
|
|
}
|
|
_ => info!("logging set up properly"),
|
|
}
|
|
}
|
|
|
|
fn setup_clap() -> (clap::ArgMatches<'static>) {
|
|
clap_app!(myapp =>
|
|
(name: crate_name!())
|
|
(version: crate_version!())
|
|
(author: crate_authors!())
|
|
(about: crate_description!())
|
|
(@arg CONFIG: +required "Set config file to use")
|
|
(@arg v: -v --verbose ... "Be verbose (you can add this up to 4 times for more logs)")
|
|
).get_matches()
|
|
}
|