Add a visual separation between commands and for the summary
This commit is contained in:
parent
9bff5b2f81
commit
7b9c487650
@ -1,17 +1,9 @@
|
||||
packages:
|
||||
- name: Flatpack
|
||||
fetch:
|
||||
- exe: flatpak
|
||||
params:
|
||||
- update
|
||||
- --no-deploy
|
||||
- --assumeyes
|
||||
- --noninteractive
|
||||
install:
|
||||
exe: flatpak
|
||||
params:
|
||||
- update
|
||||
- --no-pull
|
||||
- --assumeyes
|
||||
- --noninteractive
|
||||
post-install:
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, ExitStatus, Stdio};
|
||||
@ -14,17 +14,25 @@ enum UpdateSteps {
|
||||
PostInstall,
|
||||
}
|
||||
|
||||
// TODO: change the struct’s names for the `topgrade`’s one. They are much better.
|
||||
|
||||
/// Root of the machine’s dependency graph
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Updater {
|
||||
pub systems: Vec<System>,
|
||||
pub systems: BTreeMap<String, System>,
|
||||
}
|
||||
|
||||
/// A list of equivalent executors that will update a given component
|
||||
///
|
||||
/// Example: the `system` one will try to do update the system for as if it is Debian with `apt update`, if it fails it will try for openSUSE with `zypper refresh`, …
|
||||
/// The step will be considered a succes if **any** executor succeed and will skip all the other ones.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct System {
|
||||
packages: Vec<Package>,
|
||||
// TODO: => make a system dependend on another? This will allow to give a "Rust" config which update "rustup", and a custom "git helix" could then be executed after (with the updated toolchain, and NOT concurrently)
|
||||
}
|
||||
|
||||
/// All the infos for an executor to proceed until completion
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Package {
|
||||
pub name: String,
|
||||
@ -36,20 +44,22 @@ pub struct Package {
|
||||
// exclusive_with : List
|
||||
}
|
||||
|
||||
/// A command to execute on the system as part of an executor
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct Cmd {
|
||||
exe: String,
|
||||
params: Option<Vec<String>>,
|
||||
current_dir: Option<PathBuf>,
|
||||
env: Option<HashMap<String, String>>,
|
||||
env: Option<BTreeMap<String, String>>,
|
||||
}
|
||||
|
||||
/// The actual (cleaned) command that will be executed on the system as part of an executor
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct ActualCmd {
|
||||
exe: String,
|
||||
params: Vec<String>,
|
||||
current_dir: Option<PathBuf>,
|
||||
env: HashMap<String, String>,
|
||||
env: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
// QUESTION: Would String be less awkward?
|
||||
@ -94,10 +104,12 @@ pub fn get_packages_folder(opt: &Opt) -> io::Result<PathBuf> {
|
||||
|
||||
impl Updater {
|
||||
fn new() -> Updater {
|
||||
Updater { systems: vec![] }
|
||||
Updater {
|
||||
systems: BTreeMap::from([(String::new(), System { packages: vec![] })]),
|
||||
}
|
||||
}
|
||||
|
||||
// /// To create a sample config from code
|
||||
/// To create a sample config from code
|
||||
#[doc(hidden)]
|
||||
fn write_config(&self, opt: &Opt) {
|
||||
use std::fs::OpenOptions;
|
||||
@ -123,9 +135,15 @@ impl Updater {
|
||||
|
||||
// Example to generate a config file
|
||||
if false {
|
||||
updater.systems.push(System { packages: vec![] });
|
||||
updater
|
||||
.systems
|
||||
.insert("Test".to_owned(), System { packages: vec![] });
|
||||
let sys = updater
|
||||
.systems
|
||||
.get_mut("Test")
|
||||
.expect("We just created the key");
|
||||
|
||||
updater.systems[0].packages.push(Package {
|
||||
sys.packages.push(Package {
|
||||
name: "Rustup".to_owned(),
|
||||
fetch: None,
|
||||
compile: None,
|
||||
@ -138,7 +156,7 @@ impl Updater {
|
||||
post_install: None,
|
||||
});
|
||||
|
||||
updater.systems[0].packages.push(Package {
|
||||
sys.packages.push(Package {
|
||||
name: "Cargo".to_owned(),
|
||||
fetch: None,
|
||||
compile: None,
|
||||
@ -171,7 +189,16 @@ impl Updater {
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
for file in packages_folder.read_dir()? {
|
||||
for file in packages_folder.read_dir()?.filter(|name| match name {
|
||||
Ok(n) => {
|
||||
if n.file_name().into_string().unwrap().ends_with(".yaml") {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Err(..) => false,
|
||||
}) {
|
||||
let file = packages_folder.join(file?.path()); // "default.yaml");
|
||||
let sys = std::fs::read_to_string(&file).unwrap();
|
||||
let sys = serde_yaml::from_str(&sys).map_err(|err| {
|
||||
@ -184,7 +211,9 @@ impl Updater {
|
||||
),
|
||||
)
|
||||
})?;
|
||||
updater.systems.push(sys);
|
||||
updater
|
||||
.systems
|
||||
.insert(file.file_stem().unwrap().to_str().unwrap().to_owned(), sys);
|
||||
}
|
||||
|
||||
// eprintln!("{:#?}", updater);
|
||||
@ -196,7 +225,7 @@ impl Updater {
|
||||
let mut status: Vec<_> = vec![];
|
||||
|
||||
// XXX: We may parallelise (iter_par from rayon?) this loop. But the UI will be problematic to handle
|
||||
for sys in &self.systems {
|
||||
for (_sys_name, sys) in &self.systems {
|
||||
for pkg in &sys.packages {
|
||||
status.push((pkg.name.clone(), self.update(&pkg, opt).into()));
|
||||
}
|
||||
@ -328,7 +357,7 @@ impl Cmd {
|
||||
// This means I need to know how to know which values to pass for (at least) rustup & cargo
|
||||
let env = match self.env {
|
||||
Some(env) => env,
|
||||
None => HashMap::from([("PATH".to_owned(), std::env!("PATH").to_owned())]),
|
||||
None => BTreeMap::default(),
|
||||
};
|
||||
|
||||
ActualCmd {
|
||||
@ -350,7 +379,9 @@ impl ActualCmd {
|
||||
cmd.current_dir(std::fs::canonicalize(cdir)?);
|
||||
}
|
||||
|
||||
print!("Executing: {}", self);
|
||||
println!();
|
||||
println!("*** Executing: {} ***", self);
|
||||
// eprintln!("{:?}", self.params);
|
||||
|
||||
if opt.quiet {
|
||||
// FIXME: stdin does not work with sudo?
|
||||
@ -370,7 +401,7 @@ impl fmt::Display for ActualCmd {
|
||||
} else {
|
||||
self.exe.clone()
|
||||
};
|
||||
write!(f, "`{}`", command)?;
|
||||
write!(f, "{}", command)?;
|
||||
|
||||
if let Some(cdir) = &self.current_dir {
|
||||
write!(f, " in {:?}", cdir)?;
|
||||
|
@ -55,7 +55,8 @@ pub struct Summary {
|
||||
|
||||
impl Display for Summary {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "Summary:")?;
|
||||
writeln!(f, "")?;
|
||||
writeln!(f, "*** Summary: ***")?;
|
||||
for (name, status) in &self.status {
|
||||
// TODO: also print version before/after, update time
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user