forked from lix-project/lix-installer
Add skipped option to ActionState (#74)
* Make plans versioned * Delint * speeeeeeeeling * remove file that was dead * Flesh out docs and improve public API * Speeling * Fixups * Fix doctests * Do a better job with actionstate * Add some more docs * Fix doctest * Make CLI stuff optional * Touchup * Speeling * add skipped to ActionState
This commit is contained in:
parent
4134f7af02
commit
017bcaf1f6
|
@ -49,7 +49,7 @@ impl CreateDirectory {
|
||||||
path.display(),
|
path.display(),
|
||||||
);
|
);
|
||||||
// TODO: Validate owner/group...
|
// TODO: Validate owner/group...
|
||||||
ActionState::Completed
|
ActionState::Skipped
|
||||||
} else {
|
} else {
|
||||||
return Err(CreateDirectoryError::Exists(std::io::Error::new(
|
return Err(CreateDirectoryError::Exists(std::io::Error::new(
|
||||||
std::io::ErrorKind::AlreadyExists,
|
std::io::ErrorKind::AlreadyExists,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::action::StatefulAction;
|
||||||
use crate::execute_command;
|
use crate::execute_command;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{Action, ActionDescription, ActionState},
|
action::{Action, ActionDescription},
|
||||||
BoxableError,
|
BoxableError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ pub struct CreateApfsVolume {
|
||||||
disk: PathBuf,
|
disk: PathBuf,
|
||||||
name: String,
|
name: String,
|
||||||
case_sensitive: bool,
|
case_sensitive: bool,
|
||||||
action_state: ActionState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateApfsVolume {
|
impl CreateApfsVolume {
|
||||||
|
@ -29,7 +28,6 @@ impl CreateApfsVolume {
|
||||||
disk: disk.as_ref().to_path_buf(),
|
disk: disk.as_ref().to_path_buf(),
|
||||||
name,
|
name,
|
||||||
case_sensitive,
|
case_sensitive,
|
||||||
action_state: ActionState::Uncompleted,
|
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
@ -60,7 +58,6 @@ impl Action for CreateApfsVolume {
|
||||||
disk,
|
disk,
|
||||||
name,
|
name,
|
||||||
case_sensitive,
|
case_sensitive,
|
||||||
action_state: _,
|
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
execute_command(
|
execute_command(
|
||||||
|
@ -107,7 +104,6 @@ impl Action for CreateApfsVolume {
|
||||||
disk: _,
|
disk: _,
|
||||||
name,
|
name,
|
||||||
case_sensitive: _,
|
case_sensitive: _,
|
||||||
action_state: _,
|
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
execute_command(
|
execute_command(
|
||||||
|
|
|
@ -25,53 +25,73 @@ where
|
||||||
impl StatefulAction<Box<dyn Action>> {
|
impl StatefulAction<Box<dyn Action>> {
|
||||||
/// A description of what this action would do during execution
|
/// A description of what this action would do during execution
|
||||||
pub fn describe_execute(&self) -> Vec<ActionDescription> {
|
pub fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||||
if self.state == ActionState::Completed {
|
match self.state {
|
||||||
return vec![];
|
ActionState::Uncompleted | ActionState::Skipped => {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
_ => self.action.execute_description(),
|
||||||
}
|
}
|
||||||
return self.action.execute_description();
|
|
||||||
}
|
}
|
||||||
/// A description of what this action would do during revert
|
/// A description of what this action would do during revert
|
||||||
pub fn describe_revert(&self) -> Vec<ActionDescription> {
|
pub fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||||
if self.state == ActionState::Uncompleted {
|
match self.state {
|
||||||
return vec![];
|
ActionState::Completed | ActionState::Skipped => {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
_ => self.action.revert_description(),
|
||||||
}
|
}
|
||||||
return self.action.revert_description();
|
|
||||||
}
|
}
|
||||||
/// Perform any execution steps
|
/// Perform any execution steps
|
||||||
///
|
///
|
||||||
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
||||||
pub async fn try_execute(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub async fn try_execute(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if self.state == ActionState::Completed {
|
match self.state {
|
||||||
tracing::trace!(
|
ActionState::Completed => {
|
||||||
"Completed: (Already done) {}",
|
tracing::trace!(
|
||||||
self.action.tracing_synopsis()
|
"Completed: (Already done) {}",
|
||||||
);
|
self.action.tracing_synopsis()
|
||||||
return Ok(());
|
);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
ActionState::Skipped => {
|
||||||
|
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self.state = ActionState::Progress;
|
||||||
|
tracing::debug!("Executing: {}", self.action.tracing_synopsis());
|
||||||
|
self.action.execute().await?;
|
||||||
|
self.state = ActionState::Completed;
|
||||||
|
tracing::debug!("Completed: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.state = ActionState::Progress;
|
|
||||||
tracing::debug!("Executing: {}", self.action.tracing_synopsis());
|
|
||||||
self.action.execute().await?;
|
|
||||||
self.state = ActionState::Completed;
|
|
||||||
tracing::debug!("Completed: {}", self.action.tracing_synopsis());
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
/// Perform any revert steps
|
/// Perform any revert steps
|
||||||
///
|
///
|
||||||
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
||||||
pub async fn try_revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub async fn try_revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if self.state == ActionState::Uncompleted {
|
match self.state {
|
||||||
tracing::trace!(
|
ActionState::Uncompleted => {
|
||||||
"Reverted: (Already done) {}",
|
tracing::trace!(
|
||||||
self.action.tracing_synopsis()
|
"Reverted: (Already done) {}",
|
||||||
);
|
self.action.tracing_synopsis()
|
||||||
return Ok(());
|
);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
ActionState::Skipped => {
|
||||||
|
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self.state = ActionState::Progress;
|
||||||
|
tracing::debug!("Reverting: {}", self.action.tracing_synopsis());
|
||||||
|
self.action.revert().await?;
|
||||||
|
tracing::debug!("Reverted: {}", self.action.tracing_synopsis());
|
||||||
|
self.state = ActionState::Uncompleted;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.state = ActionState::Progress;
|
|
||||||
tracing::debug!("Reverting: {}", self.action.tracing_synopsis());
|
|
||||||
self.action.revert().await?;
|
|
||||||
tracing::debug!("Reverted: {}", self.action.tracing_synopsis());
|
|
||||||
self.state = ActionState::Uncompleted;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,37 +130,53 @@ where
|
||||||
///
|
///
|
||||||
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
/// You should prefer this ([`try_execute`][StatefulAction::try_execute]) over [`execute`][Action::execute] as it handles [`ActionState`] and does tracing
|
||||||
pub async fn try_execute(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub async fn try_execute(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if self.state == ActionState::Completed {
|
match self.state {
|
||||||
tracing::trace!(
|
ActionState::Completed => {
|
||||||
"Completed: (Already done) {}",
|
tracing::trace!(
|
||||||
self.action.tracing_synopsis()
|
"Completed: (Already done) {}",
|
||||||
);
|
self.action.tracing_synopsis()
|
||||||
return Ok(());
|
);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
ActionState::Skipped => {
|
||||||
|
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self.state = ActionState::Progress;
|
||||||
|
tracing::debug!("Executing: {}", self.action.tracing_synopsis());
|
||||||
|
self.action.execute().await?;
|
||||||
|
self.state = ActionState::Completed;
|
||||||
|
tracing::debug!("Completed: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.state = ActionState::Progress;
|
|
||||||
tracing::debug!("Executing: {}", self.action.tracing_synopsis());
|
|
||||||
self.action.execute().await?;
|
|
||||||
self.state = ActionState::Completed;
|
|
||||||
tracing::debug!("Completed: {}", self.action.tracing_synopsis());
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
/// Perform any revert steps
|
/// Perform any revert steps
|
||||||
///
|
///
|
||||||
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
/// You should prefer this ([`try_revert`][StatefulAction::try_revert]) over [`revert`][Action::revert] as it handles [`ActionState`] and does tracing
|
||||||
pub async fn try_revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub async fn try_revert(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if self.state == ActionState::Uncompleted {
|
match self.state {
|
||||||
tracing::trace!(
|
ActionState::Uncompleted => {
|
||||||
"Reverted: (Already done) {}",
|
tracing::trace!(
|
||||||
self.action.tracing_synopsis()
|
"Reverted: (Already done) {}",
|
||||||
);
|
self.action.tracing_synopsis()
|
||||||
return Ok(());
|
);
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
ActionState::Skipped => {
|
||||||
|
tracing::trace!("Skipped: {}", self.action.tracing_synopsis());
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self.state = ActionState::Progress;
|
||||||
|
tracing::debug!("Reverting: {}", self.action.tracing_synopsis());
|
||||||
|
self.action.revert().await?;
|
||||||
|
tracing::debug!("Reverted: {}", self.action.tracing_synopsis());
|
||||||
|
self.state = ActionState::Uncompleted;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self.state = ActionState::Progress;
|
|
||||||
tracing::debug!("Reverting: {}", self.action.tracing_synopsis());
|
|
||||||
self.action.revert().await?;
|
|
||||||
tracing::debug!("Reverted: {}", self.action.tracing_synopsis());
|
|
||||||
self.state = ActionState::Uncompleted;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,4 +201,11 @@ pub enum ActionState {
|
||||||
on [`InstallPlan::uninstall`](crate::InstallPlan::uninstall) and executed on [`InstallPlan::install`](crate::InstallPlan::install)
|
on [`InstallPlan::uninstall`](crate::InstallPlan::uninstall) and executed on [`InstallPlan::install`](crate::InstallPlan::install)
|
||||||
*/
|
*/
|
||||||
Uncompleted,
|
Uncompleted,
|
||||||
|
/**
|
||||||
|
If [`Skipped`](ActionState::Skipped) an [`Action`](crate::action::Action) will be skipped
|
||||||
|
on [`InstallPlan::install`](crate::InstallPlan::install) and [`InstallPlan::uninstall`](crate::InstallPlan::uninstall)
|
||||||
|
|
||||||
|
Typically this is used by actions which detect they are already completed in their `plan` phase.
|
||||||
|
*/
|
||||||
|
Skipped,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue