Few bug fixes, minor improvements and cleanup.

- Container creation in sync module now only syncs targets as required
- More robust validation for --target parameters
- Targets marked for reinitialization can now accept a configuration
  from a file if specified.
- Cleaned up process module
- Prompt module no longer emboldens listed targets for confirmation
This commit is contained in:
Xavier Moffett 2024-03-09 23:56:06 -05:00
parent 68594a28e7
commit 264e9cec1f
11 changed files with 148 additions and 128 deletions

View file

@ -77,9 +77,9 @@ fn delete_containers<'a>(
let message = format!("Deleting existing container{}?", if delete.len() > 1 { "s" } else { "" });
if flags.contains(TransactionFlags::NO_CONFIRM) {
println!("{} {}{}...{}", *BAR_GREEN, *BOLD, message, *RESET);
println!("{} {}{}...{}", *BAR_GREEN, *BOLD, &message, *RESET);
delete_roots(cache, logger, delete, force)?;
} else if let Ok(_) = prompt_targets(&delete, message, false) {
} else if let Ok(_) = prompt_targets(&delete, &message, false) {
delete_roots(cache, logger, delete, force)?;
}
@ -153,9 +153,8 @@ fn engage_aggregator<'a>(args: &mut Arguments) -> Result<()> {
while let Some(arg) = args.next() {
match arg {
Op::Short('t') | Op::Long("target") | Op::Long("from-config") => continue,
Op::Long("from-config") => continue,
Op::Long("noconfirm") => flags = flags | TransactionFlags::NO_CONFIRM,
Op::Long("force") => force = true,
Op::Long("reinitialize-all") =>
for instance in cache.registered() {
if let Some(handle) = cache.get_instance_option(instance) {
@ -166,32 +165,43 @@ fn engage_aggregator<'a>(args: &mut Arguments) -> Result<()> {
compose.insert(instance, None);
}
},
Op::Short('f') | Op::Long("force") => force = true,
Op::Short('r') | Op::Long("reinitialize") => reinitialize = true,
Op::ShortPos('t', target) | Op::LongPos("target", target) =>
if !reinitialize {
current_target = Some(target);
} else {
Op::Short('t') | Op::Long("target") => match args.next() {
Some(arg) => match arg {
Op::ShortPos('t', t) | Op::LongPos("target", t) => current_target = Some(t),
_ => args.invalid_operand()?,
},
None => err!(TargetUnspecified)?,
},
Op::LongPos(_, config) | Op::ShortPos(_, config) | Op::Value(config) => {
let target = match current_target {
Some(target) => target,
None => match config.char_indices().filter(|a| a.1 == '.').last() {
Some((index, ..)) => config.split_at(index).0,
None => config,
},
};
let config = if reinitialize {
let handle = cache.get_instance(target)?;
if Path::new(handle.vars().root()).exists() {
delete.push(target);
}
compose.insert(target, None);
reinitialize = false;
},
Op::LongPos(_, target) | Op::ShortPos(_, target) | Op::Value(target) => {
if !target.ends_with(".yml") {
err!(ErrorKind::Message("Unsupported file extension."))?;
}
if let Some(cur_target) = current_target {
compose.insert(cur_target, Some(target));
current_target = None;
} else {
Path::new(target).try_exists().prepend_io(|| target.into())?;
compose.insert(target.split_at(target.len() - 4).0, Some(target));
}
match current_target {
Some(_) => Some(config),
None => None,
}
} else {
Some(config)
};
compose.insert(target, config);
current_target = None;
reinitialize = false;
}
_ => args.invalid_operand()?,
}

View file

@ -358,7 +358,7 @@ fn create_placeholder(path: &str) -> Result<()> {
fn cleanup() -> Result<()> {
if Path::new(&*DBUS_SOCKET).exists() {
remove_file(&*DBUS_SOCKET).prepend_io(|| DBUS_SOCKET.to_string())?;
}
}
Ok(())
}

View file

@ -21,13 +21,14 @@ use std::{
str::FromStr,
};
use indexmap::IndexMap;
use nix::{
sys::signal::{kill, Signal},
unistd::Pid,
};
use pacwrap_core::{
config::cache,
constants::{ARROW_GREEN, BOLD, RESET},
constants::{ARROW_GREEN, BOLD, DIM, RESET},
err,
impl_error,
process::{self, Process},
@ -243,6 +244,7 @@ fn process_kill(args: &mut Arguments) -> Result<()> {
err!(InvalidArgument::TargetUnspecified)?
}
let mut instances = IndexMap::new();
let cache = cache::populate()?;
let list = process::list(&cache)?;
let list = match all {
@ -265,11 +267,18 @@ fn process_kill(args: &mut Arguments) -> Result<()> {
if process.fork() {
fork_warn(process);
}
match instances.get(process.instance()) {
Some(value) => instances.insert(process.instance(), value + 1),
None => instances.insert(process.instance(), 1),
};
}
let instances: Vec<String> = instances.iter().map(|a| format!("{} ({}{}{})", a.0, *DIM, a.1, *RESET)).collect();
if no_confirm {
kill_processes(&list, sigint)
} else if let Ok(_) = prompt_targets(&list.iter().map(|a| a.instance()).collect(), "Kill processes?", false) {
} else if let Ok(_) = prompt_targets(&instances.iter().map(|a| a.as_ref()).collect(), "Kill container processes?", false) {
kill_processes(&list, sigint)
} else {
Ok(())

View file

@ -26,7 +26,7 @@ use pacwrap_core::{
log::Logger,
sync::transaction::{TransactionAggregator, TransactionFlags, TransactionType},
utils::{
arguments::{Arguments, InvalidArgument, Operand as Op},
arguments::{Arguments, InvalidArgument::*, Operand as Op},
check_root,
},
};
@ -62,7 +62,7 @@ fn engage_aggregator<'a>(action_type: TransactionType, args: &'a mut Arguments,
let mut current_target = None;
if let Op::Nothing = args.next().unwrap_or_default() {
err!(InvalidArgument::OperationUnspecified)?
err!(OperationUnspecified)?
}
while let Some(arg) = args.next() {
@ -72,18 +72,23 @@ fn engage_aggregator<'a>(action_type: TransactionType, args: &'a mut Arguments,
| Op::Long("recursive")
| Op::Short('R')
| Op::Short('c')
| Op::Short('s')
| Op::Short('t') => continue,
| Op::Short('s') => continue,
Op::Long("dbonly") => flags = flags | TransactionFlags::DATABASE_ONLY,
Op::Long("noconfirm") => flags = flags | TransactionFlags::NO_CONFIRM,
Op::Long("force-foreign") => flags = flags | TransactionFlags::FORCE_DATABASE,
Op::Short('p') | Op::Long("preview") => flags = flags | TransactionFlags::PREVIEW,
Op::Short('f') | Op::Long("filesystem") => flags = flags | TransactionFlags::FILESYSTEM_SYNC,
Op::ShortPos('t', target) | Op::LongPos("target", target) => {
cache.get_instance(target)?;
current_target = Some(target);
targets.push(target);
}
Op::Short('t') | Op::Long("target") => match args.next() {
Some(arg) => match arg {
Op::ShortPos('t', target) | Op::LongPos("target", target) => {
cache.get_instance(target)?;
current_target = Some(target);
targets.push(target);
}
_ => args.invalid_operand()?,
},
None => err!(TargetUnspecified)?,
},
Op::LongPos(_, package) | Op::ShortPos(_, package) | Op::Value(package) =>
if let Some(target) = current_target {
match queue.get_mut(target) {
@ -98,7 +103,7 @@ fn engage_aggregator<'a>(action_type: TransactionType, args: &'a mut Arguments,
}
if let None = current_target {
err!(InvalidArgument::TargetUnspecified)?
err!(TargetUnspecified)?
}
Ok(TransactionAggregator::new(&cache, log, action_type)

View file

@ -117,12 +117,18 @@ fn acquire_depends<'a>(args: &mut Arguments<'a>) -> Result<IndexMap<&'a str, (Co
}
None => err!(TargetUnspecified)?,
},
Op::ShortPos('t', target) | Op::LongPos("target", target) => match instype {
Some(instype) => {
current_target = target;
deps.insert(current_target, (instype, vec![]));
}
None => err!(ErrorKind::Message("Container type not specified."))?,
Op::Short('t') | Op::Long("target") => match args.next() {
Some(arg) => match arg {
Op::ShortPos('t', target) | Op::LongPos("target", target) => match instype {
Some(instype) => {
current_target = target;
deps.insert(current_target, (instype, vec![]));
}
None => err!(ErrorKind::Message("Container type not specified."))?,
},
_ => args.invalid_operand()?,
},
None => err!(TargetUnspecified)?,
},
_ => continue,
}
@ -224,14 +230,12 @@ fn engage_aggregator<'a>(
Op::Short('a')
| Op::Short('s')
| Op::Short('d')
| Op::Short('t')
| Op::Short('y')
| Op::Short('u')
| Op::Short('c')
| Op::Long("aggregate")
| Op::Long("slice")
| Op::Long("dep")
| Op::Long("target")
| Op::Long("refresh")
| Op::Long("upgrade")
| Op::Long("create")
@ -243,16 +247,22 @@ fn engage_aggregator<'a>(
Op::Long("dbonly") => flags = flags | TransactionFlags::DATABASE_ONLY,
Op::Long("force-foreign") => flags = flags | TransactionFlags::FORCE_DATABASE,
Op::Long("noconfirm") => flags = flags | TransactionFlags::NO_CONFIRM,
Op::ShortPos('t', target) | Op::LongPos("target", target) => {
cache.get_instance(target)?;
current_target = target;
targets.insert(target);
Op::Short('t') | Op::Long("target") => match args.next() {
Some(arg) => match arg {
Op::ShortPos('t', target) | Op::LongPos("target", target) => {
cache.get_instance(target)?;
current_target = target;
targets.insert(target);
if base {
queue.insert(current_target.into(), vec!["base"]);
base = false;
}
}
if base {
queue.insert(current_target.into(), vec!["base"]);
base = false;
}
}
_ => args.invalid_operand()?,
},
None => err!(TargetUnspecified)?,
},
Op::LongPos(_, package) | Op::ShortPos(_, package) | Op::Value(package) =>
if current_target != "" {
if let Some(vec) = queue.get_mut(current_target) {
@ -265,18 +275,18 @@ fn engage_aggregator<'a>(
}
}
if flags.contains(TransactionFlags::CREATE) {
for cache in cache.registered_handles().iter().filter(|a| a.is_creation()) {
targets.extend(cache.metadata().dependencies());
}
}
let targets: Option<Vec<&str>> = match flags.contains(TransactionFlags::TARGET_ONLY) {
let targets: Option<Vec<&str>> = match flags.intersects(TransactionFlags::TARGET_ONLY | TransactionFlags::CREATE) {
true => {
if current_target == "" && !flags.contains(TransactionFlags::FILESYSTEM_SYNC) {
err!(TargetUnspecified)?
}
if flags.contains(TransactionFlags::CREATE) {
for cache in cache.registered_handles().iter().filter(|a| a.is_creation()) {
targets.extend(cache.metadata().dependencies());
}
}
match flags.contains(TransactionFlags::FILESYSTEM_SYNC) {
false => Some(targets.into_iter().collect()),
true => None,

View file

@ -20,15 +20,17 @@
use std::{
fmt::{Display, Formatter},
fs::remove_dir_all,
path::Path,
};
use pacwrap_core::{
config::{cache, ContainerCache},
constants::{ARROW_GREEN, BOLD, RESET},
constants::{ARROW_GREEN, BOLD, DATA_DIR, RESET},
err,
impl_error,
log::{Level::Info, Logger},
process,
sync::filesystem::create_blank_state,
utils::{arguments::Operand, prompt::prompt_targets, Arguments},
Error,
ErrorGeneric,
@ -58,7 +60,7 @@ pub fn remove_containers(args: &mut Arguments) -> Result<()> {
let mut targets = vec![];
let mut no_confirm = false;
let mut force = false;
let mut logger = Logger::new("pacwrap-utils");
let mut logger = Logger::new("pacwrap-utils").init()?;
while let Some(arg) = args.next() {
match arg {
@ -103,8 +105,13 @@ pub fn delete_roots(cache: &ContainerCache<'_>, logger: &mut Logger, targets: &V
for container in containers {
let root = container.vars().root();
let instance = container.vars().instance();
let state = &format!("{}/state/{instance}.dat", *DATA_DIR);
remove_dir_all(root).prepend(|| format!("Failed to delete container root '{root}':"))?;
if Path::new(state).exists() {
create_blank_state(instance)?;
}
eprintln!("{} Deleted container {}{}{} successfully.", *ARROW_GREEN, *BOLD, instance, *RESET);
logger.log(Info, &format!("Deleted container {instance}"))?;
}