Refactoring and transformation of update routine into a state machine

alongside dependency resolution.

- In Addition target parameterisation to the arguments parser with --target/-t
- Bug fixes to the progress event.
This commit is contained in:
Xavier Moffett 2023-07-14 01:17:04 -04:00
parent 8943e77fed
commit 81482c20f0
4 changed files with 532 additions and 162 deletions

View file

@ -9,8 +9,9 @@ use crate::constants::{self, LOCATION};
use crate::sync::dl_event::DownloadCallback;
use crate::sync::linker::Linker;
use crate::sync::progress_event::ProgressCallback;
use crate::sync::update::Update;
use crate::utils::{Arguments, test_root, print_help_msg};
use crate::sync::update::TransactionAggregator;
use crate::sync::update::TransactionType;
use crate::utils::{Arguments, arguments::invalid, test_root, print_help_msg};
use crate::config::InsVars;
use crate::config::cache::InstanceCache;
use crate::config::InstanceHandle;
@ -27,17 +28,21 @@ mod linker;
mod update;
pub fn execute() {
let mut sync = false;
let mut update = false;
let mut explicit = false;
let mut sync_count = 0;
let mut args = Arguments::new().prefix("-S")
.switch("-y", "--sync", &mut sync).count(&mut sync_count)
.switch("-u", "--upgrade", &mut update)
.switch("-e", "--explicit", &mut explicit);
let mut search = false;
let mut refresh = false;
let mut upgrade = false;
let mut preview = false;
let mut y_count = 0;
let mut args = Arguments::new().prefix("-S").ignore("--sync")
.switch("-y", "--refresh", &mut refresh).count(&mut y_count)
.switch("-u", "--upgrade", &mut upgrade)
.switch("-s", "--search", &mut search)
.switch("-p", "--preview", &mut preview);
args = args.parse_arguments();
let targets = args.get_runtime().clone();
let mut targets = args.targets().clone();
let runtime = args.get_runtime().clone();
let mut cache: InstanceCache = InstanceCache::new();
if targets.len() > 0 {
@ -46,14 +51,31 @@ pub fn execute() {
cache.populate();
}
if sync && sync_count == 4 {
if refresh && y_count == 4 {
let mut l: Linker = Linker::new();
l.start(cache.registered().len());
linker::wait_on(l.link(&cache, cache.registered(), Vec::new()));
l.finish();
} else if search {
print_help_msg("Functionality is currently unimplemented.");
} else if refresh || preview || upgrade {
if refresh {
synchronize_database(&cache, y_count == 2);
}
if preview && upgrade || upgrade {
let mut update: TransactionAggregator = TransactionAggregator::new(TransactionType::UpgradeSync, &cache, preview, y_count > 2);
if targets.len() > 0 {
update.queue(targets.remove(0), runtime);
}
update::update(update, &cache);
} else if ! refresh {
invalid();
}
} else {
if sync { synchronize_database(&cache, sync_count > 1); }
if update { update::update(Update::new(), &cache); }
invalid();
}
}

View file

@ -44,13 +44,13 @@ pub fn progress_event(progress: Progress, pkgname: &str, percent: i32, howmany:
}
},
None => {
let whitespace = whitespace(howmany.to_string().len(), current.to_string().len());
let pos = style(current + 1).bold().white();
let total = style(howmany + 1).bold().white();
let pos = current + 1;
let total = howmany + 1;
let progress_name: String = progress_name(progress,pkgname);
let pb = this.progress.add(ProgressBar::new(progress_u64(percent)));
let pb = this.progress.add(ProgressBar::new(100));
let whitespace = whitespace(total.to_string().len(), pos.to_string().len());
pb.set_style(this.style.clone());
pb.set_message(format!("({}{}/{}) {}", whitespace, pos, total, progress_name));
pb.set_message(format!("({}{}/{}) {}", whitespace, style(pos).bold().white(), style(total).bold().white(), progress_name));
this.prbar.insert(progress_ident, pb);
}
}
@ -83,5 +83,5 @@ fn progress_ident(progress: Progress, pkgname: &str) -> String {
}
fn progress_u64(u: i32) -> u64 {
match u.try_into() { Ok(i) => i, Err(_) => 0 }
match u.try_into() { Ok(i) => i, Err(_) => { 0 }}
}

View file

@ -1,9 +1,12 @@
use console::style;
use std::collections::HashMap;
use std::process::exit;
use console::{style, Term};
use alpm::{Alpm,
TransFlag,
PrepareResult,
CommitResult,
FileConflictType};
FileConflictType, Package};
use crate::{sync, utils::print_error};
use crate::sync::{dl_event, linker};
@ -15,18 +18,35 @@ use crate::utils::prompt::prompt;
use crate::config::cache::InstanceCache;
use crate::config::InstanceHandle;
pub struct Update {
queried: Vec<String>,
updated: Vec<String>,
linker: Linker
pub enum TransactionType {
Upgrade,
UpgradeSync,
Remove,
}
impl Update {
pub fn new() -> Self {
pub struct TransactionAggregator<'a> {
queried: Vec<String>,
updated: Vec<String>,
pkg_queue: HashMap<String, Vec<String>>,
action: TransactionType,
linker: Linker,
syncdb: bool,
preview: bool,
cache: &'a InstanceCache
}
impl <'a>TransactionAggregator<'a> {
pub fn new(t: TransactionType, icache: &'a InstanceCache, pre: bool, dbsync: bool) -> Self {
Self {
queried: Vec::new(),
updated: Vec::new(),
linker: Linker::new()
pkg_queue: HashMap::new(),
linker: Linker::new(),
action: t,
preview: pre,
syncdb: dbsync,
cache: icache,
}
}
@ -38,99 +58,385 @@ impl Update {
&self.updated
}
pub fn update(&mut self, cache: &InstanceCache, containers: &Vec<String>) {
pub fn queue(&mut self, ins: String, install: Vec<String>) {
self.pkg_queue.insert(ins, install);
}
pub fn transaction(&mut self, containers: &Vec<String>) {
for ins in containers.iter() {
if self.queried.contains(ins) {
continue;
}
let cache = self.cache;
let inshandle = cache.instances().get(ins).unwrap();
self.transaction(inshandle.instance().dependencies());
self.queried.push(ins.clone());
self.update(cache, inshandle.instance().dependencies());
self.update_instance(sync::instantiate_alpm(&inshandle), cache, inshandle, false)
.release()
.unwrap();
let queue = match self.pkg_queue.get(inshandle.vars().instance()) {
Some(some) => some.clone(), None => Vec::new(),
};
let alpm = sync::instantiate_alpm(&inshandle);
let mut handle = TransactionHandle::new(alpm, queue);
let mut act: Transaction = Transaction::new(inshandle, &mut handle);
loop {
if let Some(result) = act.transact(self, self.syncdb) {
match result {
Ok(_) => handle.release(),
Err(_) => handle.release_on_fail()
}
break;
}
}
}
}
fn update_instance(&mut self, mut handle: Alpm, cache: &InstanceCache, inshandle: &InstanceHandle, dbonly: bool) -> Alpm {
let mut flags = TransFlag::NO_DEP_VERSION;
let mut ignored: Vec<String> = Vec::new();
let config = inshandle.instance();
let deps = config.dependencies();
let dep_depth = deps.len();
let instance = inshandle.vars().instance();
if ! dbonly {
println!("{} {}",style("::").bold().cyan(), style(format!("Checking {} for updates...", inshandle.vars().instance())).bold());
} else {
println!("{} {}",style("->").bold().cyan(), style(format!("Synchronizing foreign packages...")));
flags = flags | TransFlag::DB_ONLY;
fn link_filesystem(&mut self, inshandle: &InstanceHandle) {
if inshandle.instance().container_type() == "ROOT" {
return;
}
if dep_depth > 0 {
let dep_handle = sync::instantiate_alpm(cache.instances().get(&deps[dep_depth-1]).unwrap());
ignored = enumerate_ignorelist(&handle, &dep_handle, dbonly);
} else if dbonly {
return handle;
}
if let Err(_) = out_of_date(&handle, &ignored) {
if ! dbonly {
println!("{} {} is up-to-date!", style("->").bold().green(), instance);
}
return handle;
}
if ! dbonly && self.updated
.iter()
.find(|ins| inshandle
.instance()
.dependencies()
.contains(ins))
.is_some() {
self.link_filesystem(instance, cache);
handle = self.update_instance(handle, cache, inshandle, true);
}
handle.trans_init(flags).unwrap();
handle.sync_sysupgrade(false).unwrap();
sync_new_packages(&handle, &ignored);
if ! dbonly {
if confirm_transaction(&handle).is_err() {
handle.trans_release().unwrap();
return handle;
}
handle.set_question_cb(QueryCallback, query_event::questioncb);
handle.set_progress_cb(ProgressCallback::new(true), progress_event::progress_event);
}
if let Err(e) = handle.trans_prepare() {
handle_erroneous_preparation(e.0, e.1);
}
if let Err(e) = handle.trans_commit() {
handle_erroneous_transaction(e.0, e.1);
}
self.updated.push(instance.clone());
handle.trans_release().unwrap();
handle
}
fn link_filesystem(&mut self, ins: &String, cache: &InstanceCache) {
println!("{} {}",style("->").bold().cyan(), style(format!("Synchronizing container filesystem...")));
linker::wait_on(self.linker.link(cache, &vec![ins.clone()], Vec::new()));
linker::wait_on(self.linker.link(self.cache, &vec![inshandle.vars().instance().into()], Vec::new()));
}
}
pub fn update(mut update: Update, cache: &InstanceCache) {
update.update(&cache, &cache.containers_base());
update.update(&cache, &cache.containers_dep());
enum TransactionState {
Prepare,
UpToDate,
PrepareForeignDatabase,
Commit(bool),
Result(Result<(),()>),
CommitForeignDb,
}
pub struct Transaction<'a> {
inshandle: &'a InstanceHandle,
handle: &'a mut TransactionHandle,
state: TransactionState
}
impl <'a>Transaction<'a> {
pub fn new(ins: &'a InstanceHandle, than: &'a mut TransactionHandle) -> Self {
Self {
handle: than,
inshandle: ins,
state: TransactionState::Prepare
}
}
fn transact(&mut self, ag: &mut TransactionAggregator, dbonly: bool) -> Option<Result<(),()>> {
let instance = self.inshandle.vars().instance();
match self.state {
TransactionState::Prepare => {
println!("{} {}",style("::").bold().cyan(), style(format!("Checking {} for updates...", instance)));
self.state = self.prepare(ag, dbonly);
None?
},
TransactionState::UpToDate => {
println!("{} {} is up-to-date!", style("->").bold().green(), instance);
Some(Ok(()))
},
TransactionState::PrepareForeignDatabase => {
ag.link_filesystem(self.inshandle);
self.state = self.prepare_db();
None?
},
TransactionState::CommitForeignDb => {
if let Err(_) = self.commit(ag,true) {
return Some(Err(()));
}
self.state = TransactionState::Commit(false);
None?
},
TransactionState::Commit(db) => {
self.handle.db(db);
Some(self.commit(ag,db))
},
TransactionState::Result(res) => Some(res)
}
}
fn prepare_db(&mut self) -> TransactionState {
println!("{} Synchronizing foreign packages",style("->").bold().cyan());
let config = self.inshandle.instance();
if config.dependencies().len() > 0 {
self.handle.db(true);
} else {
return TransactionState::Commit(false);
}
if let Err(_) = self.handle.out_of_date() {
return TransactionState::Commit(false);
}
return TransactionState::CommitForeignDb;
}
fn prepare(&mut self, ag: &mut TransactionAggregator, dbonly: bool) -> TransactionState {
let deps = self.inshandle.instance().dependencies();
let dep_depth = deps.len();
if dep_depth > 0 {
let dep_instance = ag.cache.instances().get(&deps[dep_depth-1]).unwrap();
let dep_alpm = sync::instantiate_alpm(dep_instance);
self.handle.enumerate_ignorelist(&dep_alpm);
} else if dbonly {
return TransactionState::UpToDate;
}
if let Err(_) = self.handle.out_of_date() {
if self.handle.queue.len() == 0 {
return TransactionState::UpToDate;
}
}
if ! dbonly {
if let Some(_) = ag.updated
.iter()
.find(|ins| self.inshandle
.instance()
.dependencies()
.contains(ins)) {
return TransactionState::PrepareForeignDatabase;
}
}
TransactionState::Commit(false)
}
fn commit(&mut self, ag: &mut TransactionAggregator, dbonly: bool) -> Result<(),()> {
let instance = self.inshandle.vars().instance();
let flags = match dbonly {
false => TransFlag::NO_DEP_VERSION,
true => TransFlag::NO_DEP_VERSION | TransFlag::DB_ONLY
};
self.handle.alpm().trans_init(flags).unwrap();
match ag.action {
TransactionType::UpgradeSync => {
self.handle.alpm().sync_sysupgrade(false).unwrap();
self.handle.sync_packages();
self.handle.resolve_packages();
},
TransactionType::Upgrade => self.handle.resolve_packages(),
TransactionType::Remove => self.handle.resolve_packages(),
}
if ! dbonly {
if confirm_transaction(&self.handle.alpm(), ag.preview).is_err() {
self.handle.alpm_mut().trans_release().unwrap();
return Ok(());
}
self.handle.alpm().set_question_cb(QueryCallback, query_event::questioncb);
self.handle.alpm().set_progress_cb(ProgressCallback::new(true), progress_event::progress_event);
}
if let Err(_) = handle_preparation(self.handle.alpm_mut().trans_prepare()) {
return Err(())
}
if let Err(_) = handle_transaction(self.handle.alpm_mut().trans_commit()) {
return Err(())
}
ag.updated.push(instance.clone());
self.handle.alpm_mut().trans_release().unwrap();
Ok(())
}
}
pub struct TransactionHandle {
ignore: Vec<String>,
ignore_dep: Vec<String>,
queue: Vec<String>,
dbonly: bool,
alpm: Alpm
}
impl TransactionHandle {
pub fn new(al: Alpm, q: Vec<String>) -> Self {
Self {
ignore: Vec::new(),
ignore_dep: Vec::new(),
dbonly: false,
queue: q,
alpm: al,
}
}
fn db(&mut self, dbonly: bool) {
self.dbonly = dbonly;
}
fn release_on_fail(mut self) {
println!("{} Transaction failed.",style("->").bold().red());
self.alpm.trans_release().ok();
self.alpm.release().ok();
exit(1);
}
fn release(mut self) {
self.alpm.trans_release().ok();
self.alpm.release().unwrap();
}
fn alpm_mut(&mut self) -> &mut Alpm {
&mut self.alpm
}
fn alpm(&mut self) -> &Alpm {
&self.alpm
}
fn out_of_date(&mut self) -> Result<(), ()> {
let ignored = if self.dbonly {
&self.ignore_dep
} else {
&self.ignore
};
for pkg in self.alpm.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
}
if pkg.sync_new_version(self.alpm.syncdbs()).is_some() {
return Ok(());
}
}
Err(())
}
fn enumerate_ignorelist(&mut self, dep_handle: &Alpm) {
for pkg in self.alpm.localdb().pkgs() {
if let Ok(_) = dep_handle.localdb().pkg(pkg.name()) {
continue;
}
self.ignore_dep.push(pkg.name().into());
}
for pkg in dep_handle.localdb().pkgs() {
self.ignore.push(pkg.name().into());
}
}
fn resolve_packages(&mut self) {
let ignor = if self.dbonly {
&self.ignore_dep
} else {
&self.ignore
};
let ignored = ignor.iter().map(|i| i.as_str()) .collect::<Vec<_>>();
let queued = self.queue.iter().map(|i| i.as_str()) .collect::<Vec<_>>();
let packages = DependencyResolver::new(&self.alpm, &ignored).enumerate(&queued);
for pkg in packages {
self.alpm.trans_add_pkg(pkg).unwrap();
}
}
fn sync_packages(&mut self) {
let ignored = if self.dbonly {
&self.ignore_dep
} else {
&self.ignore
};
for pkg in self.alpm.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
}
if let Some(pkg) = pkg.sync_new_version(self.alpm.syncdbs()) {
self.alpm.trans_add_pkg(pkg).unwrap();
}
}
for pkg in self.alpm.trans_add() {
let deps = pkg.depends().iter().map(|p| p.name()).collect::<Vec<&str>>();
for dep in deps {
if let None = get_local_package(&self.alpm, dep) {
self.queue.push(dep.into());
}
}
}
}
}
struct DependencyResolver<'a> {
resolved: Vec<&'a str>,
packages: Vec<Package<'a>>,
ignored: &'a Vec<&'a str>,
handle: &'a Alpm,
depth: i8,
}
impl <'a>DependencyResolver<'a> {
pub fn new(alpm: &'a Alpm, ignorelist: &'a Vec<&'a str>) -> Self {
Self {
resolved: Vec::new(),
packages: Vec::new(),
ignored: ignorelist,
depth: 0,
handle: alpm,
}
}
fn check_depth(&mut self) {
if self.depth == 15 {
print_error("Recursion depth exceeded maximum.");
exit(2);
}
}
fn enumerate(mut self, packages: &Vec<&'a str>) -> Vec<Package<'a>> {
let mut synchronize: Vec<&'a str> = Vec::new();
self.check_depth();
for pkg in packages {
if self.resolved.contains(&pkg) || self.ignored.contains(&pkg) {
continue;
}
if let Some(pkg) = get_package(&self.handle, pkg) {
self.resolved.push(pkg.name());
self.packages.push(pkg);
let deps = pkg.depends().iter().map(|p| p.name()).collect::<Vec<&str>>();
for dep in deps {
if let None = get_local_package(&self.handle, dep) {
synchronize.push(dep);
}
}
}
}
if synchronize.len() > 0 {
self.depth += 1;
self.enumerate(&synchronize)
} else {
self.packages
}
}
}
pub fn update(mut update: TransactionAggregator, cache: &InstanceCache) {
update.transaction(&cache.containers_base());
update.transaction(&cache.containers_dep());
if update.updated().len() > 0 {
println!("{} {} ",style("::").bold().green(), style("Synchronising container filesystems...").bold());
update.linker().start(cache.registered().len());
@ -138,28 +444,35 @@ pub fn update(mut update: Update, cache: &InstanceCache) {
update.linker().finish();
}
update.update(&cache, &cache.containers_root());
update.transaction(&cache.containers_root());
println!("{} Transaction complete.",style("->").bold().green());
}
fn confirm_transaction(handle: &Alpm) -> Result<(),()> {
println!("{} {} \n",style("::").bold().red(), style("Package changes").bold());
fn confirm_transaction(handle: &Alpm, preview: bool) -> Result<(),()> {
let size = Term::size(&Term::stdout());
let mut installed_size_old: i64 = 0;
let mut installed_size: i64 = 0;
let mut download: i64 = 0;
let mut files_to_download: usize = 0;
let preface = format!("Packages ({}) ", handle.trans_add().len());
let mut print_string: String = String::new();
let line_delimiter = size.1 as isize - preface.len() as isize;
let mut current_line_len: isize = 0;
print!("\n{}", style(format!("{}", preface)).bold());
for val in handle.trans_add() {
let pkg_sync = val;
let pkg;
let pkg;
if let Ok(p) = handle.localdb().pkg(pkg_sync.name()) {
pkg = p;
} else {
pkg = pkg_sync;
pkg = pkg_sync;
}
let output = format!("{}-{} ", pkg.name(), style(pkg_sync.version()).dim());
installed_size_old += pkg.isize();
installed_size += pkg_sync.isize();
download += pkg_sync.download_size();
@ -168,14 +481,29 @@ fn confirm_transaction(handle: &Alpm) -> Result<(),()> {
files_to_download += 1;
}
println!("{} {} -> {}", pkg.name(), style(pkg.version()).bold().yellow(), style(pkg_sync.version()).bold().green());
current_line_len += print_string.len() as isize;
print_string.push_str(&output);
if current_line_len >= line_delimiter {
print!("{}\n", print_string);
print_string = " ".repeat(preface.len());
current_line_len = 0;
}
}
if print_string.len() > 0 {
print!("{} \n", print_string);
}
let net = installed_size-installed_size_old;
println!("\n{}: {}", style("Total Installed Size").bold(), format_unit(installed_size));
println!("{}: {}", style("Net Upgrade Size").bold(), format_unit(net));
if net != 0 {
println!("{}: {}", style("Net Upgrade Size").bold(), format_unit(net));
}
if download > 0 {
println!("{}: {}", style("Total Download Size").bold(), format_unit(download));
handle.set_dl_cb(DownloadCallback::new(download.try_into().unwrap(), files_to_download), dl_event::download_event);
@ -183,11 +511,22 @@ fn confirm_transaction(handle: &Alpm) -> Result<(),()> {
}
println!();
prompt("::", style("Proceed with installation?").bold(), true)
if preview {
Err(())
} else {
prompt("::", style("Proceed with installation?").bold(), true)
}
}
fn handle_erroneous_transaction<'a>(result: CommitResult<'a>, error: alpm::Error) {
fn handle_transaction<'a>(result: Result<(),(CommitResult<'a>, alpm::Error)>) -> Result<(),()> {
match result {
Ok(_) => Ok(()),
Err(result) => { handle_erroneous_transaction(result); Err(()) }
}
}
fn handle_erroneous_transaction<'a>(result: (CommitResult<'a>, alpm::Error)) {
match result.0 {
CommitResult::FileConflict(file) => {
print_error("Conflicting files in container filesystem:");
for conflict in file.iter() {
@ -206,7 +545,7 @@ fn handle_erroneous_transaction<'a>(result: CommitResult<'a>, error: alpm::Error
} else {
println!("{}: '{}' is owned by foreign target", target, file);
}
},
},
}
}
},
@ -217,18 +556,22 @@ fn handle_erroneous_transaction<'a>(result: CommitResult<'a>, error: alpm::Error
pkg_string.push_str(format!("{}, ", pkg).as_str());
}
pkg_string.truncate(pkg_string.len()-2);
print_error(format!("Invalid packages found: {}", pkg_string));
print_error(format!("Invalid packages: {}", pkg_string));
},
CommitResult::Ok => print_error(format!("{}", error)) //haha, this should **never** happen
CommitResult::Ok => print_error(format!("{}", result.1))
}
println!("{} Transaction failed.", style("->").red());
std::process::exit(1);
}
fn handle_erroneous_preparation<'a>(result: PrepareResult<'a>, error: alpm::Error) {
fn handle_preparation<'a>(result: Result<(), (PrepareResult<'a>, alpm::Error)>) -> Result<(),()> {
match result {
Ok(_) => Ok(()),
Err(result) => { handle_erroneous_preparation(result); Err(()) }
}
}
fn handle_erroneous_preparation<'a>(result: (PrepareResult<'a>, alpm::Error)) {
match result.0 {
PrepareResult::PkgInvalidArch(list) => {
for package in list.iter() {
print_error(format!("Invalid architecture {} for {}", style(package.arch().unwrap()).bold(), style(package.name()).bold()));
@ -244,11 +587,8 @@ fn handle_erroneous_preparation<'a>(result: PrepareResult<'a>, error: alpm::Erro
print_error(format!("Conflict between {} and {}: {}", style(conflict.package1()).bold(), style(conflict.package2()).bold(), conflict.reason()));
}
},
PrepareResult::Ok => print_error(format!("{}", error))
PrepareResult::Ok => print_error(format!("{}", result.1))
}
println!("{} Transaction failed.", style("->").red());
std::process::exit(1);
}
fn unit_suffix<'a>(i: i8) -> &'a str {
@ -280,47 +620,41 @@ fn format_unit(bytes: i64) -> String {
}
}
fn enumerate_ignorelist(handle: &Alpm, dep_handle: &Alpm, dbonly: bool) -> Vec<String> {
let mut ignored = Vec::new();
if dbonly {
for pkg in handle.localdb().pkgs() {
if let Ok(_) = dep_handle.localdb().pkg(pkg.name()) {
continue;
}
ignored.push(pkg.name().into());
}
fn get_local_package<'a>(handle: &'a Alpm, pkg: &'a str) -> Option<Package<'a>> {
if let Ok(pkg) = handle.localdb().pkg(pkg) {
return Some(pkg);
} else {
for pkg in dep_handle.localdb().pkgs() {
ignored.push(pkg.name().into());
for pkgs in handle.localdb().pkgs() {
let is_present = pkgs.provides().iter().filter(|d| pkg == d.name()).collect::<Vec<_>>().len() > 0;
if is_present {
if let Ok(pkg) = handle.localdb().pkg(pkgs.name()) {
return Some(pkg);
}
}
}
}
ignored
None
}
fn out_of_date(handle: &Alpm, ignored: &Vec<String>) -> Result<(), ()> {
for pkg in handle.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
fn get_package<'a>(handle: &'a Alpm, pkg: &'a str) -> Option<Package<'a>> {
for sync in handle.syncdbs() {
if let Ok(pkg) = sync.pkg(pkg) {
return Some(pkg);
} else {
for pkgs in sync.pkgs() {
let is_present = pkgs.provides().iter().filter(|d| pkg == d.name()).collect::<Vec<_>>().len() > 0;
if is_present {
return Some(pkgs);
}
}
}
if pkg.sync_new_version(handle.syncdbs()).is_some() {
return Ok(());
}
}
Err(())
None
}
fn sync_new_packages(handle: &Alpm, ignored: &Vec<String>) {
for pkg in handle.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
}
fn handle_failure(mut handle: Alpm) {
handle.trans_release().ok();
handle.release().unwrap();
exit(1);
if let Some(pkg) = pkg.sync_new_version(handle.syncdbs()) {
handle.trans_add_pkg(pkg).unwrap();
}
}
}

View file

@ -8,6 +8,7 @@ use super::print_help_msg;
pub struct Arguments<'a> {
prefix: String,
runtime: Vec<String>,
targets: Vec<String>,
prefixes: HashMap<String, i8>,
amalgamation: HashMap<String, i8>,
bool_map: HashMap<i8, &'a mut bool>,
@ -19,7 +20,8 @@ pub struct Arguments<'a> {
impl<'a> Arguments<'a> {
pub fn new() -> Self {
Self {
Self {
targets: Vec::new(),
prefix: String::new(),
runtime: Vec::new(),
prefixes: HashMap::new(),
@ -33,7 +35,15 @@ impl<'a> Arguments<'a> {
}
pub fn parse_arguments(mut self) -> Arguments<'a> {
let mut target = false;
for string in env::args().skip(1) {
if target {
self.targets.push(string);
target = false;
continue;
}
match string {
string if self.prefixes.contains_key(&string) => {
let key = self.prefixes.get(&string).unwrap();
@ -60,6 +70,9 @@ impl<'a> Arguments<'a> {
}
}
},
string if string.starts_with("-t") || string.starts_with("--target") => {
target = true;
},
_ => self.runtime.push(string),
}
}
@ -116,6 +129,7 @@ impl<'a> Arguments<'a> {
self
}
pub fn targets(&self) -> &Vec<String> { &self.targets }
pub fn get_runtime(&self) -> &Vec<String> { &self.runtime }
pub fn get_prefix(&self) -> &String { &self.prefix }
}