Add a yes argument for commands

This commit is contained in:
Zykino 2023-01-15 23:59:30 +01:00
parent 976fd7bd96
commit 10496f75db
6 changed files with 103 additions and 105 deletions

68
Cargo.lock generated
View File

@ -57,61 +57,6 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "darling"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "enumset"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753"
dependencies = [
"enumset_derive",
]
[[package]]
name = "enumset_derive"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "errno"
version = "0.2.8"
@ -133,12 +78,6 @@ dependencies = [
"libc",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "hashbrown"
version = "0.12.3"
@ -160,12 +99,6 @@ dependencies = [
"libc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "1.9.2"
@ -345,7 +278,6 @@ name = "system-updater"
version = "0.1.0"
dependencies = [
"clap",
"enumset",
"serde",
"serde_yaml",
]

View File

@ -11,6 +11,5 @@ name = "sup"
[dependencies]
clap = { version = "4.1", features = ["derive"] }
enumset = { version = "1.0" , feature = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

View File

@ -28,5 +28,4 @@ systems:
- -a
current_dir: null
env: {}
steps: Install
nice: null

View File

@ -27,4 +27,3 @@ systems:
- -a
current_dir: null
env: {}
steps: Install

View File

@ -1,5 +1,4 @@
use crate::*;
use enumset::EnumSetType;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
@ -7,8 +6,7 @@ use std::io::{stdout, Write};
use std::path::PathBuf;
use std::process::Command;
#[derive(Debug, Serialize, Deserialize, EnumSetType)]
//#[enumset(serialize_as_list)] // TODO: use it or not?
#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum UpdateSteps {
Fetch,
Compile,
@ -18,7 +16,6 @@ enum UpdateSteps {
#[derive(Debug, Serialize, Deserialize)]
pub struct Updater {
systems: Vec<System>,
steps: UpdateSteps,
}
#[derive(Debug, Serialize, Deserialize)]
@ -31,20 +28,52 @@ pub struct System {
// exclusive_with : List
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Cmd {
exe: String,
params: Vec<String>,
yes: Option<String>,
current_dir: Option<PathBuf>,
env: HashMap<String, String>,
}
#[derive(Debug, Serialize, Deserialize)]
struct ActualCmd {
exe: String,
params: Vec<String>,
current_dir: Option<PathBuf>,
env: HashMap<String, String>,
}
// QUESTION: Would String be less awkward?
impl From<&str> for UpdateSteps {
fn from(value: &str) -> Self {
match &*value.to_lowercase() {
"fetch" => UpdateSteps::Fetch,
"compile" => UpdateSteps::Compile,
"install" => UpdateSteps::Install,
_ => panic!("Step {} not recognized", value),
}
}
}
// QUESTION: Would String be less awkward?
impl From<&String> for UpdateSteps {
fn from(value: &String) -> Self {
match &*value.to_lowercase() {
"fetch" => UpdateSteps::Fetch,
"compile" => UpdateSteps::Compile,
"install" => UpdateSteps::Install,
_ => panic!("Step {} not recognized", value),
}
}
}
impl Updater {
fn new() -> Updater {
let mut up = Updater {
systems: vec![],
steps: UpdateSteps::Fetch,
};
let mut up = Updater { systems: vec![] };
up.systems.push(System {
fetch: None,
compile: None,
@ -78,13 +107,18 @@ impl Updater {
}
pub fn update_all(&self, opt: &Opt) -> Result<()> {
let mut errors = vec![];
for sys in &self.systems {
if let Err(err) = self.update(sys, opt) {
eprintln!("Error catched {}", err);
errors.push(err);
}
}
let errors: Vec<_> = self
.systems
.iter()
.filter_map(|sys| {
if let Err(err) = self.update(sys, opt) {
eprintln!("Error catched {}", err);
Some(err)
} else {
None
}
})
.collect();
// TODO:
if errors.len() == 0 {
@ -98,13 +132,22 @@ impl Updater {
}
fn update(&self, sys: &System, opt: &Opt) -> Result<()> {
if self.steps == UpdateSteps::Fetch {
let steps = match &opt.steps {
Some(v) => v.iter().map(|u| u.into()).collect(),
None => vec![
UpdateSteps::Fetch,
UpdateSteps::Compile,
UpdateSteps::Install,
],
};
if steps.contains(&UpdateSteps::Fetch) {
sys.fetch(opt)?;
}
if self.steps == UpdateSteps::Compile {
if steps.contains(&UpdateSteps::Compile) {
sys.compile(opt)?;
}
if self.steps == UpdateSteps::Install {
if steps.contains(&UpdateSteps::Install) {
sys.install(opt)?;
}
@ -115,20 +158,20 @@ impl Updater {
impl System {
pub fn fetch(&self, opt: &Opt) -> Result<()> {
if let Some(fetch) = &self.fetch {
fetch.execute(opt)?;
fetch.clone().prepare(opt).execute(&opt)?;
}
Ok(())
}
pub fn compile(&self, opt: &Opt) -> Result<()> {
if let Some(compile) = &self.compile {
compile.execute(opt)?;
compile.clone().prepare(opt).execute(opt)?;
}
Ok(())
}
pub fn install(&self, opt: &Opt) -> Result<()> {
self.install.execute(opt)?;
self.install.clone().prepare(opt).execute(opt)?;
Ok(())
}
}
@ -138,16 +181,40 @@ impl Cmd {
Cmd {
exe: "".into(),
params: vec![],
yes: None,
current_dir: None,
env: HashMap::new(),
}
}
fn execute(&self, opt: &Opt) -> Result<()> {
fn prepare(self, opt: &Opt) -> ActualCmd {
let mut params = self.params;
if opt.yes {
if let Some(y) = &self.yes {
params.push(y.to_owned());
}
};
let mut env = self.env;
if !env.contains_key("PATH") {
env.insert("PATH".to_owned(), std::env!("PATH").to_owned());
}
ActualCmd {
exe: self.exe,
params,
current_dir: self.current_dir,
env,
}
}
}
impl ActualCmd {
fn execute(&self, opt: &Opt) -> Result<bool> {
let mut cmd = Command::new(&self.exe);
cmd.args(&self.params)
.env_clear()
.env("PATH", std::env!("PATH"))
.envs(&self.env)
// .stdout(cfg)
// .stderr(cfg)
@ -170,20 +237,20 @@ impl Cmd {
.expect("Unable to read users input");
}
if !yes_no.to_lowercase().starts_with('n') {
if cmd.status().unwrap().success() {
eprintln!("Youpi !");
// Other checks?
} else {
eprintln!("Error executing the command")
}
if yes_no.to_lowercase().starts_with('n') {
eprintln!(
"yes_no? {} {}",
yes_no,
yes_no.to_lowercase().starts_with('n')
);
return Ok(false);
}
Ok(())
Ok(cmd.status().unwrap().success())
}
}
impl fmt::Display for Cmd {
impl fmt::Display for ActualCmd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let command = if !self.params.is_empty() {
format!("{} {}", &self.exe, &self.params.join(" "))
@ -198,7 +265,7 @@ impl fmt::Display for Cmd {
if !self.env.is_empty() {
writeln!(f, " with the following environment variable:")?;
writeln!(f, "{:?}", self.env)
writeln!(f, "{:#?}", self.env)
} else {
write!(f, " without any environment variable. ")
}

View File

@ -26,6 +26,8 @@ pub struct Opt {
#[arg(short)]
pub yes: bool,
//pub quiet: bool, // imply yes
#[arg(short, long)]
pub steps: Option<Vec<String>>,
}
pub fn run(opt: &Opt) {