Bug fixes for database resolution during composition
- Container::stamp function to set new timestamp with compose_handle. - Restructured and refactored trans_ready function. - Fixed bug with progress ticker during an aggregate transaction when one or more lines are printed to std[out|err]. - Do not print containers as up-to-date upon completion of container composition nor creation in aggregate, nor if a container was composed. - TransactionState::Skip state declared and implemented. - Check for UpdateSchema(..) instead of Prepare for marking a container as updated.
This commit is contained in:
parent
5c3b9bdd5d
commit
03d942ad22
8 changed files with 60 additions and 47 deletions
|
@ -105,7 +105,7 @@ pub fn compose_handle<'a>(instance: &'a str, path: Option<&'a str>) -> Result<Co
|
|||
err!(ConfigError::AlreadyExists(instance.into()))?
|
||||
}
|
||||
|
||||
Ok(handle(vars)?.create())
|
||||
Ok(handle(vars)?.stamp().create())
|
||||
}
|
||||
|
||||
pub fn provide_new_handle<'a>(instance: &'a str, instype: ContainerType, deps: Vec<&'a str>) -> Result<ContainerHandle<'a>> {
|
||||
|
|
|
@ -108,6 +108,11 @@ impl<'a> ContainerHandle<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn stamp(mut self) -> Self {
|
||||
self.inner.metadata.meta_version = *UNIX_TIMESTAMP;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &ContainerRuntime {
|
||||
&self.inner.runtime
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ pub enum SyncError {
|
|||
InvalidMagicNumber,
|
||||
SignalInterrupt,
|
||||
AgentVersionMismatch,
|
||||
NothingToDo(bool),
|
||||
NothingToDo,
|
||||
DependentContainerMissing(String),
|
||||
RecursionDepthExceeded(isize),
|
||||
TargetUpstream(String),
|
||||
|
@ -108,7 +108,7 @@ impl Display for SyncError {
|
|||
Self::SignalInterrupt => write!(fmter, "Signal interrupt was triggered."),
|
||||
Self::UnableToLocateKeyrings => write!(fmter, "Unable to locate pacman keyrings."),
|
||||
Self::RepoConfError(path, err) => write!(fmter, "'{}': {}", path, err),
|
||||
Self::NothingToDo(_) => write!(fmter, "Nothing to do."),
|
||||
Self::NothingToDo => write!(fmter, "Nothing to do."),
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
|
||||
|
|
|
@ -54,15 +54,16 @@ pub type Result<T> = crate::Result<T>;
|
|||
pub static MAGIC_NUMBER: u32 = 663445956;
|
||||
|
||||
pub enum TransactionState {
|
||||
Complete(bool),
|
||||
Prepare,
|
||||
UpdateSchema(Option<SchemaState>),
|
||||
UpToDate,
|
||||
PrepareForeign(bool),
|
||||
Stage,
|
||||
StageForeign,
|
||||
UpdateSchema(Option<SchemaState>),
|
||||
Commit(bool),
|
||||
CommitForeign,
|
||||
Skip,
|
||||
Complete(bool),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone)]
|
||||
|
@ -71,12 +72,13 @@ pub enum TransactionType {
|
|||
Remove(bool, bool, bool),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Copy, Clone)]
|
||||
pub enum TransactionMode {
|
||||
Foreign,
|
||||
Local,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum SyncState {
|
||||
Required,
|
||||
NotRequired,
|
||||
|
@ -97,19 +99,19 @@ pub trait Transaction {
|
|||
bitflags! {
|
||||
pub struct TransactionFlags: u8 {
|
||||
const NONE = 0;
|
||||
const TARGET_ONLY = 0b0000001;
|
||||
const PREVIEW = 0b0000010;
|
||||
const NO_CONFIRM = 0b0000100;
|
||||
const FORCE_DATABASE = 0b0001000;
|
||||
const DATABASE_ONLY = 0b0010000;
|
||||
const CREATE = 0b0100000;
|
||||
const FILESYSTEM_SYNC = 0b1000000;
|
||||
const TARGET_ONLY = 0b0000001;
|
||||
const PREVIEW = 0b0000010;
|
||||
const NO_CONFIRM = 0b0000100;
|
||||
const FORCE_DATABASE = 0b0001000;
|
||||
const DATABASE_ONLY = 0b0010000;
|
||||
const CREATE = 0b0100000;
|
||||
const FILESYSTEM_SYNC = 0b1000000;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TransactionHandle<'a> {
|
||||
meta: &'a mut TransactionMetadata<'a>,
|
||||
fail: bool,
|
||||
state: SyncState,
|
||||
agent: bool,
|
||||
config: Option<&'a Global>,
|
||||
alpm: Option<Alpm>,
|
||||
|
@ -159,7 +161,7 @@ impl TransactionState {
|
|||
Self::StageForeign => Stage::new(self, ag),
|
||||
Self::Commit(_) => Commit::new(self, ag),
|
||||
Self::CommitForeign => Commit::new(self, ag),
|
||||
Self::Complete(_) => unreachable!(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,7 @@ impl<'a> TransactionHandle<'a> {
|
|||
pub fn new(metadata: &'a mut TransactionMetadata<'a>) -> Self {
|
||||
Self {
|
||||
meta: metadata,
|
||||
fail: true,
|
||||
state: Required,
|
||||
agent: false,
|
||||
alpm: None,
|
||||
deps: None,
|
||||
|
@ -316,11 +318,9 @@ impl<'a> TransactionHandle<'a> {
|
|||
self.meta
|
||||
.queue
|
||||
.extend(self.meta.foreign_pkgs.iter().map(|p| p.to_owned().into()).collect::<Vec<_>>());
|
||||
self.fail = false;
|
||||
}
|
||||
|
||||
pub fn ignore(&mut self) {
|
||||
let mut fail = self.fail;
|
||||
let alpm = self.alpm.as_mut().unwrap();
|
||||
let config = match self.config {
|
||||
Some(config) => config,
|
||||
|
@ -355,7 +355,7 @@ impl<'a> TransactionHandle<'a> {
|
|||
{
|
||||
let new = match package.sync_new_version(alpm.syncdbs()) {
|
||||
Some(new) => {
|
||||
fail = false;
|
||||
self.state = NotRequired;
|
||||
|
||||
match self.agent {
|
||||
true => break,
|
||||
|
@ -373,8 +373,6 @@ impl<'a> TransactionHandle<'a> {
|
|||
*BOLD, *RESET, *BOLD_YELLOW, *RESET, *BOLD_GREEN, *RESET
|
||||
));
|
||||
}
|
||||
|
||||
self.fail = fail;
|
||||
}
|
||||
|
||||
pub fn prepare(&mut self, trans_type: &TransactionType, flags: &TransactionFlags) -> Result<()> {
|
||||
|
@ -496,15 +494,19 @@ impl<'a> TransactionHandle<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn trans_ready(&mut self, trans_type: &TransactionType) -> Result<()> {
|
||||
pub fn trans_ready(&mut self, trans_type: &TransactionType, trans_flags: &TransactionFlags) -> Result<SyncState> {
|
||||
if match trans_type {
|
||||
Upgrade(..) => self.alpm().trans_add().len(),
|
||||
Remove(..) => self.alpm().trans_remove().len(),
|
||||
} > 0
|
||||
{
|
||||
Ok(())
|
||||
Upgrade(..) => !self.alpm().trans_add().is_empty(),
|
||||
Remove(..) => !self.alpm().trans_remove().is_empty(),
|
||||
} {
|
||||
Ok(Required)
|
||||
} else if trans_flags.intersects(TransactionFlags::CREATE) {
|
||||
Ok(NotRequired)
|
||||
} else {
|
||||
err!(SyncError::NothingToDo(self.fail))
|
||||
match self.state {
|
||||
Required => err!(SyncError::NothingToDo),
|
||||
NotRequired => Ok(NotRequired),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ pub struct TransactionAggregator<'a> {
|
|||
action: TransactionType,
|
||||
cache: &'a ContainerCache<'a>,
|
||||
keyring: bool,
|
||||
tracted: bool,
|
||||
logger: &'a mut Logger,
|
||||
flags: TransactionFlags,
|
||||
targets: Option<Vec<&'a str>>,
|
||||
|
@ -89,6 +90,7 @@ impl<'a> TransactionAggregator<'a> {
|
|||
action: action_type,
|
||||
cache: inscache,
|
||||
keyring: false,
|
||||
tracted: false,
|
||||
logger: log,
|
||||
flags: TransactionFlags::NONE,
|
||||
lock: None,
|
||||
|
@ -249,7 +251,10 @@ impl<'a> TransactionAggregator<'a> {
|
|||
Ok(result) => {
|
||||
self.signal(&mut handle.alpm)?;
|
||||
|
||||
if let Complete(updated) = result {
|
||||
if let Skip = result {
|
||||
handle.release();
|
||||
return Ok(());
|
||||
} else if let Complete(updated) = result {
|
||||
if updated {
|
||||
self.updated.insert(inshandle.vars().instance());
|
||||
|
||||
|
@ -258,23 +263,24 @@ impl<'a> TransactionAggregator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
self.tracted = !updated;
|
||||
handle.release();
|
||||
return Ok(());
|
||||
} else if let Prepare = result {
|
||||
} else if let UpdateSchema(_) = result {
|
||||
self.updated.insert(inshandle.vars().instance());
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
Err(err) => {
|
||||
if let Some(progress) = &self.progress {
|
||||
progress.finish_and_clear();
|
||||
if let Some(progress) = self.progress.as_ref() {
|
||||
progress.set_draw_target(ProgressDrawTarget::hidden());
|
||||
progress.finish();
|
||||
}
|
||||
|
||||
handle.release();
|
||||
return match err.downcast::<SyncError>().map_err(|err| error!(SyncError::from(err)))? {
|
||||
SyncError::TransactionFailureAgent => exit(err.kind().code()),
|
||||
SyncError::NothingToDo(bool) => bool.then(|| Err(err)).unwrap_or_else(|| Ok(())),
|
||||
_ => Err(err),
|
||||
};
|
||||
}
|
||||
|
@ -286,7 +292,8 @@ impl<'a> TransactionAggregator<'a> {
|
|||
fn print_complete(&mut self, filesystem_sync: bool, target_amount: u64, target: Option<&&str>) {
|
||||
if let Some(_) = &self.progress {
|
||||
let are_multiple = target_amount > 1;
|
||||
let container = if filesystem_sync && self.queried.is_empty() {
|
||||
let flagged = self.flags.intersects(TransactionFlags::PREVIEW | TransactionFlags::CREATE);
|
||||
let container = if filesystem_sync && self.queried.is_empty() || flagged || self.tracted {
|
||||
None
|
||||
} else if are_multiple {
|
||||
Some("Containers")
|
||||
|
|
|
@ -46,6 +46,8 @@ use crate::{
|
|||
Result,
|
||||
};
|
||||
|
||||
use super::SyncState;
|
||||
|
||||
pub struct Commit {
|
||||
state: TransactionState,
|
||||
keyring: bool,
|
||||
|
@ -68,13 +70,12 @@ impl Transaction for Commit {
|
|||
inshandle: &ContainerHandle,
|
||||
) -> Result<TransactionState> {
|
||||
let instance = inshandle.vars().instance();
|
||||
let ready = handle.trans_ready(&ag.action());
|
||||
let state = self.state.as_str();
|
||||
|
||||
if let Err(_) = ready {
|
||||
if let SyncState::NotRequired = handle.trans_ready(&ag.action(), ag.flags())? {
|
||||
match ready_state(handle, ag.action(), &self.state) {
|
||||
Some(result) => return result,
|
||||
None => ready?,
|
||||
None => return Ok(TransactionState::Complete(false)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,9 +103,7 @@ impl Transaction for Commit {
|
|||
|
||||
handle.set_alpm(Some(sync::instantiate_alpm(inshandle)));
|
||||
handle.apply_configuration(inshandle, ag.flags().intersects(TransactionFlags::CREATE))?;
|
||||
ag.logger()
|
||||
.log(Info, &format!("container {instance}'s {state} transaction complete"))
|
||||
.ok();
|
||||
ag.logger().log(Info, &format!("container {instance}'s {state} transaction complete"))?;
|
||||
next_state(handle, ag.action(), &self.state, true)
|
||||
}
|
||||
}
|
||||
|
@ -116,11 +115,11 @@ fn confirm(
|
|||
) -> StdResult<(u64, u64), Result<TransactionState>> {
|
||||
let database = ag.flags().intersects(TransactionFlags::DATABASE_ONLY | TransactionFlags::FORCE_DATABASE);
|
||||
let foreign = !handle.get_mode().bool();
|
||||
let create_foreign = match handle.get_mode() {
|
||||
TransactionMode::Foreign => ag.flags().contains(TransactionFlags::CREATE),
|
||||
let create = match handle.get_mode() {
|
||||
TransactionMode::Foreign => ag.flags().intersects(TransactionFlags::CREATE),
|
||||
TransactionMode::Local => false,
|
||||
};
|
||||
let confirm = foreign || database && !create_foreign;
|
||||
let confirm = foreign || database && !create;
|
||||
let sum = Summary::new()
|
||||
.kind(CONFIG.config().summary(), confirm)
|
||||
.mode(handle.get_mode())
|
||||
|
|
|
@ -85,10 +85,10 @@ impl Transaction for Prepare {
|
|||
|
||||
if let Upgrade(upgrade, ..) = action {
|
||||
if !upgrade && handle.meta.queue.is_empty() {
|
||||
err!(SyncError::NothingToDo(true))?
|
||||
err!(SyncError::NothingToDo)?
|
||||
}
|
||||
} else if handle.meta.queue.is_empty() {
|
||||
err!(SyncError::NothingToDo(true))?
|
||||
err!(SyncError::NothingToDo)?
|
||||
}
|
||||
|
||||
if handle.meta.queue.is_empty() {
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
|||
Transaction,
|
||||
TransactionAggregator,
|
||||
TransactionHandle,
|
||||
TransactionState::{self, Complete},
|
||||
TransactionState::{self, Skip},
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
@ -52,6 +52,6 @@ impl Transaction for UpToDate {
|
|||
None => println!("{} {} is up-to-date!", *ARROW_GREEN, handle.vars().instance()),
|
||||
}
|
||||
|
||||
Ok(Complete(false))
|
||||
Ok(Skip)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue