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:
Xavier Moffett 2024-04-21 15:07:13 -04:00
parent 5c3b9bdd5d
commit 03d942ad22
Signed by: Sapphirus
GPG key ID: A6C061B2CEA1A7AC
8 changed files with 60 additions and 47 deletions

View file

@ -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>> {

View file

@ -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
}

View file

@ -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(()),
}?;

View file

@ -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,
@ -109,7 +111,7 @@ bitflags! {
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),
}
}
}

View file

@ -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")

View file

@ -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())

View file

@ -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() {

View file

@ -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)
}
}