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:
parent
8943e77fed
commit
81482c20f0
4 changed files with 532 additions and 162 deletions
50
src/sync.rs
50
src/sync.rs
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue