Merge PreInstall commands

This commit is contained in:
Zykino
2023-06-28 22:46:56 +02:00
parent 7b9c487650
commit 804584d21c
10 changed files with 201 additions and 232 deletions

View File

@ -8,8 +8,7 @@ use std::{fmt, fs, io};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum UpdateSteps {
Fetch,
Compile,
PreInstall,
Install,
PostInstall,
}
@ -19,7 +18,7 @@ enum UpdateSteps {
/// Root of the machines dependency graph
#[derive(Debug, Serialize, Deserialize)]
pub struct Updater {
pub systems: BTreeMap<String, System>,
pub packagers: BTreeMap<String, Packager>,
}
/// A list of equivalent executors that will update a given component
@ -27,21 +26,19 @@ pub struct Updater {
/// 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>,
pub struct Packager {
executors: Vec<Executor>,
// 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 struct Executor {
pub name: String,
fetch: Option<Vec<Cmd>>,
compile: Option<Vec<Cmd>>,
pre_install: Option<Vec<Cmd>>,
install: Cmd,
post_install: Option<Vec<Cmd>>,
// deps or rDeps : Tree
// exclusive_with : List
}
/// A command to execute on the system as part of an executor
@ -62,26 +59,10 @@ pub(crate) struct ActualCmd {
env: BTreeMap<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,
"post_install" => UpdateSteps::PostInstall,
_ => 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,
match value.to_lowercase().as_str() {
"pre_install" => UpdateSteps::PreInstall,
"install" => UpdateSteps::Install,
"post_install" => UpdateSteps::PostInstall,
@ -105,7 +86,7 @@ pub fn get_packages_folder(opt: &Opt) -> io::Result<PathBuf> {
impl Updater {
fn new() -> Updater {
Updater {
systems: BTreeMap::from([(String::new(), System { packages: vec![] })]),
packagers: BTreeMap::from([(String::new(), Packager { executors: vec![] })]),
}
}
@ -136,17 +117,16 @@ impl Updater {
// Example to generate a config file
if false {
updater
.systems
.insert("Test".to_owned(), System { packages: vec![] });
.packagers
.insert("Test".to_owned(), Packager { executors: vec![] });
let sys = updater
.systems
.packagers
.get_mut("Test")
.expect("We just created the key");
sys.packages.push(Package {
sys.executors.push(Executor {
name: "Rustup".to_owned(),
fetch: None,
compile: None,
pre_install: None,
install: Cmd {
exe: "rustup".to_owned(),
params: Some(vec!["self".to_owned(), "update".to_owned()]),
@ -156,10 +136,9 @@ impl Updater {
post_install: None,
});
sys.packages.push(Package {
sys.executors.push(Executor {
name: "Cargo".to_owned(),
fetch: None,
compile: None,
pre_install: None,
install: Cmd {
exe: "cargo".to_owned(),
params: Some(vec!["install-update".to_owned(), "-a".to_owned()]),
@ -212,7 +191,7 @@ impl Updater {
)
})?;
updater
.systems
.packagers
.insert(file.file_stem().unwrap().to_str().unwrap().to_owned(), sys);
}
@ -225,8 +204,8 @@ 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_name, sys) in &self.systems {
for pkg in &sys.packages {
for (_packager_name, packager) in &self.packagers {
for pkg in &packager.executors {
status.push((pkg.name.clone(), self.update(&pkg, opt).into()));
}
}
@ -234,12 +213,11 @@ impl Updater {
Summary { status }
}
fn update(&self, sys: &Package, opt: &Opt) -> Result<()> {
fn update(&self, sys: &Executor, opt: &Opt) -> Result<()> {
// TODO: compute once before calling this function, maybe?
let steps = if opt.steps.is_empty() {
vec![
UpdateSteps::Fetch,
UpdateSteps::Compile,
UpdateSteps::PreInstall,
UpdateSteps::Install,
UpdateSteps::PostInstall,
]
@ -247,11 +225,8 @@ impl Updater {
opt.steps.iter().map(|u| u.into()).collect()
};
if steps.contains(&UpdateSteps::Fetch) {
sys.fetch(opt)?;
}
if steps.contains(&UpdateSteps::Compile) {
sys.compile(opt)?;
if steps.contains(&UpdateSteps::PreInstall) {
sys.pre_install(opt)?;
}
if steps.contains(&UpdateSteps::Install) {
sys.install(opt)?;
@ -264,38 +239,18 @@ impl Updater {
}
}
impl Package {
pub fn fetch(&self, opt: &Opt) -> Result<()> {
if let Some(fetch) = &self.fetch {
for cmd in fetch {
impl Executor {
pub fn pre_install(&self, opt: &Opt) -> Result<()> {
if let Some(pre_install) = &self.pre_install {
for cmd in pre_install {
let cmd = cmd.clone().prepare(opt);
let exit_status = cmd
.execute(opt)
.map_err(|err| MyError::new(MyErrorKind::Fetch, err, cmd.clone()))?;
.map_err(|err| MyError::new(MyErrorKind::PreInstall, err, cmd.clone()))?;
if !exit_status.success() {
return Err(MyError::new(
MyErrorKind::Fetch,
io::Error::new(io::ErrorKind::Other, format!("{}", exit_status)),
cmd.clone(),
));
}
}
}
Ok(())
}
pub fn compile(&self, opt: &Opt) -> Result<()> {
if let Some(compile) = &self.compile {
for cmd in compile {
let cmd = cmd.clone().prepare(opt);
let exit_status = cmd
.execute(opt)
.map_err(|err| MyError::new(MyErrorKind::Compile, err, cmd.clone()))?;
if !exit_status.success() {
return Err(MyError::new(
MyErrorKind::Compile,
MyErrorKind::PreInstall,
io::Error::new(io::ErrorKind::Other, format!("{}", exit_status)),
cmd.clone(),
));

View File

@ -22,8 +22,7 @@ pub struct MyError {
#[non_exhaustive]
pub enum MyErrorKind {
Config,
Fetch,
Compile,
PreInstall,
Install,
PostInstall,
}
@ -53,15 +52,9 @@ impl Display for MyError {
"Could not read configuration file: {}",
self.source().unwrap()
),
MyErrorKind::Fetch => write!(
MyErrorKind::PreInstall => write!(
f,
"Could not fetch with command {}: {}",
self.cmd,
self.source().unwrap()
),
MyErrorKind::Compile => write!(
f,
"Could not compile with command {}: {}",
"Could not do the pre_install with command {}: {}",
self.cmd,
self.source().unwrap()
),

View File

@ -69,7 +69,7 @@ impl Display for Summary {
pub fn run(opt: &Opt) -> io::Result<Summary> {
let updater = Updater::from_config(opt)?;
if updater.systems.is_empty() {
if updater.packagers.is_empty() {
let package_folder = get_packages_folder(&opt)?;
return Err(io::Error::new(
io::ErrorKind::Other,