Merge PreInstall commands
This commit is contained in:
103
src/command.rs
103
src/command.rs
@ -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 machine’s 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(),
|
||||
));
|
||||
|
@ -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()
|
||||
),
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user