Bug fixes and optimisations applied to package and link synchronization

- InstanceCache populate_from() function.
- Functional parity almost reached with pacwrap-bash.
This commit is contained in:
Xavier Moffett 2023-07-09 10:01:27 -04:00
parent 566796d174
commit 68af25e824
11 changed files with 370 additions and 189 deletions

View file

@ -15,17 +15,27 @@ pub struct InstanceCache {
impl InstanceCache {
pub fn new() -> Self {
let s = Self {
Self {
instances: HashMap::new(),
registered: Vec::new(),
containers_base: Vec::new(),
containers_dep: Vec::new(),
containers_root: Vec::new(),
};
s.populate()
}
}
fn populate(mut self) -> Self {
pub fn populate_from(&mut self, containers: &Vec<String>) {
for name in containers {
if self.map_instance(&name) {
self.registered.push(name.clone());
let deps = self.instances.get(name).unwrap().instance().dependencies().clone();
self.populate_from(&deps);
}
}
}
pub fn populate(&mut self) {
if let Ok(dir) = read_dir(format!("{}/root", LOCATION.get_data())) {
for f in dir {
if let Ok(file) = f {
@ -36,7 +46,6 @@ impl InstanceCache {
}
}
}
self
}
fn map_instance(&mut self, ins: &String) -> bool {

View file

@ -32,8 +32,8 @@ pub fn execute() {
.prefix("-E")
.switch("-r", "--root", &mut root)
.switch("-v", "--verbose", &mut verbose)
.switch("-c", "--cmd", &mut cmd)
.switch("-s", "-shell", &mut shell)
.switch("-c", "--command", &mut cmd)
.switch("-s", "--shell", &mut shell)
.parse_arguments();
let mut runtime = args.get_runtime().clone();

View file

@ -1,7 +1,6 @@
use std::env;
use std::process::Command;
use utils::arguments::Arguments;
use utils::print_help_msg;
use utils::arguments::{self, Arguments};
mod config;
mod exec;
@ -40,14 +39,7 @@ fn main() {
else if bash_create { execute_pacwrap_bash("pacwrap-create"); }
else if bash_proc { execute_pacwrap_bash("pacwrap-ps"); }
else if bash_help { execute_pacwrap_bash("pacwrap-man"); }
else {
let mut ar = String::new();
for arg in env::args().skip(1).collect::<Vec<_>>().iter() {
ar.push_str(&format!("{} ", &arg));
}
ar.truncate(ar.len()-1);
print_help_msg(&format!("Invalid arguments -- '{}'", ar));
}
else { arguments::invalid(); }
}
fn print_version() {

View file

@ -5,17 +5,16 @@ use console::style;
use lazy_static::lazy_static;
use pacmanconf;
use crate::{constants, utils};
use crate::constants;
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};
use crate::utils::{Arguments, test_root, print_help_msg};
use crate::config::InsVars;
use crate::config::cache::InstanceCache;
use crate::config::InstanceHandle;
lazy_static! {
static ref PACMAN_CONF: pacmanconf::Config = pacmanconf::Config::from_file(format!("{}/pacman/pacman.conf", constants::LOCATION.get_config())).unwrap();
}
@ -32,7 +31,6 @@ pub fn execute() {
let mut query = 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)
@ -41,42 +39,35 @@ pub fn execute() {
args = args.parse_arguments();
let targets = args.get_runtime().clone();
let cache: InstanceCache = InstanceCache::new();
let mut cache: InstanceCache = InstanceCache::new();
if sync && sync_count == 4 {
link(&cache, cache.registered());
if targets.len() > 0 {
cache.populate_from(&targets);
} else {
cache.populate();
}
if sync && sync_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 query {
if targets.len() < 1 {
utils::print_help_msg("Target not specified.");
print_help_msg("Target not specified.");
}
query_database(targets.get(0).unwrap(), explicit)
} else {
let mut u: Update = Update::new();
if sync {
synchronize_database(&cache, sync_count > 1);
}
if update {
u.update(&cache, &cache.containers_base());
u.update(&cache, &cache.containers_dep());
if u.updated().len() > 0 {
link(&cache, cache.registered());
}
u.update(&cache, &cache.containers_root());
}
println!("{} Transaction complete.",style("->").bold().green());
if update {
update::update(Update::new(), &cache);
}
}
}
fn link(cache: &InstanceCache, containers: &Vec<String>) {
let mut l: Linker = Linker::new(containers.len());
linker::wait_on(l.link(&cache, containers, Vec::new()));
l.finish();
}
fn query_database(instance: &String, explicit: bool) {
let instance_vars = InsVars::new(instance);
@ -129,15 +120,13 @@ fn register_remote(mut handle: Alpm) -> Alpm {
handle
}
fn synchronize_database(cache: &InstanceCache, force: bool) {
for i in cache.registered().iter() {
let ins: &InstanceHandle = cache.instances().get(i).unwrap();
if ins.instance().container_type() == "BASE" {
let mut handle = instantiate_alpm_syncdb(&ins);
println!("{} {} ",style("::").bold().green(), style("Synchronising package databases...").bold());
println!("{} {} ",style("::").bold().green(), style("Synchronising package databases...").bold());
handle.syncdbs_mut().update(force).unwrap();
Alpm::release(handle).unwrap();
break;

View file

@ -2,7 +2,7 @@ use std::collections::HashMap;
use alpm::{AnyDownloadEvent, DownloadEvent};
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use console::{Term, style};
use console::Term;
#[derive(Clone)]
pub struct DownloadCallback {
@ -44,7 +44,7 @@ pub fn download_event(filename: &str, download: AnyDownloadEvent, this: &mut Dow
let name: Vec<&str> = filename.split(".").collect();
let pb = this.progress.add(ProgressBar::new(progress.total.unsigned_abs()));
pb.set_style(this.style.clone());
pb.set_message(style(name[0].to_string()).bold().to_string());
pb.set_message(name[0].to_string());
this.prbar.insert(filename.to_string(), pb);
}
}
@ -58,7 +58,7 @@ pub fn download_event(filename: &str, download: AnyDownloadEvent, this: &mut Dow
let name: Vec<&str> = filename.split(".").collect();
let pb = this.progress.add(ProgressBar::new(0));
pb.set_style(this.finished.clone());
pb.set_message(format!("{} is up-to-date!", style(name[0].to_string()).bold().to_string()));
pb.set_message(format!("{} is up-to-date!", name[0].to_string()));
pb.finish();
this.prbar.insert(filename.to_string(), pb);
}

View file

@ -5,7 +5,7 @@ use std::sync::mpsc::{Sender, self, Receiver};
use std::thread::JoinHandle;
use indexmap::IndexMap;
use indicatif::{ProgressBar, ProgressStyle};
use indicatif::{ProgressBar, ProgressStyle, ProgressDrawTarget};
use serde::{Serialize, Deserialize};
use walkdir::WalkDir;
use std::collections::HashMap;
@ -41,13 +41,15 @@ pub struct Linker {
}
impl Linker {
pub fn new(length: usize) -> Self {
pub fn new() -> Self {
let size = Term::size(&Term::stdout());
let width = (size.1 / 2).to_string();
let width_str = " {spinner:.green} {msg:<".to_owned()+width.as_str();
let style = ProgressStyle::with_template(&(width_str+"} [{wide_bar}] {percent:<3}%"))
.unwrap().progress_chars("#-").tick_strings(&[">", ""]);
let pr = ProgressBar::new(progress_u64(length)).with_style(style);
let pr = ProgressBar::new(0).with_style(style);
pr.set_draw_target(ProgressDrawTarget::hidden());
Self {
progress: pr,
@ -58,6 +60,13 @@ impl Linker {
}
}
pub fn start(&mut self, length: usize) {
self.progress.set_draw_target(ProgressDrawTarget::stdout());
self.progress.set_message("Synhcronizing containers..");
self.progress.set_position(0);
self.progress.set_length(progress_u64(length));
}
pub fn finish(&mut self) {
self.progress.set_message("Synchronization complete.");
self.progress.finish();
@ -77,7 +86,6 @@ impl Linker {
pub fn link(&mut self, cache: &InstanceCache, containers: &Vec<String>, mut cached_threads: Vec<JoinHandle<()>>) -> Vec<JoinHandle<()>> {
let mut threads: Vec<_> = Vec::new();
let (tx, rx): (Sender<(String, HardLinkDS)>, Receiver<(String, HardLinkDS)>) = mpsc::channel();
for ins in containers.iter() {
@ -132,22 +140,17 @@ impl Linker {
if dep_depth == 0 {
return None;
}
let mut map = IndexMap::new();
let dephandle = cache.instances().get(&deps[dep_depth-1]).unwrap();
let dep = dephandle.vars().instance().clone();
let mut map = IndexMap::new();
for dep in deps {
let dephandle = cache.instances().get(dep).unwrap();
let dephandle = cache.instances().get(dep).unwrap();
let ds = match self.hlds.get(dep) {
Some(ds) => ds.clone(),
None => { HardLinkDS::new() }
};
//p.push(dephandle.vars().root().clone());
map.insert(dephandle.vars().root().clone(), ds);
}
@ -171,10 +174,10 @@ impl Linker {
let thread = std::thread::Builder::new().name(format!("PR-LINKER")).spawn(move ||{
//println!("{} Linking {} against {}", style("->").cyan(), style(instance).bold(), style(&dep).bold());
tx.send((dep, link_instance(ds, ds_res, root, map))).unwrap();
}).unwrap();
}).unwrap();
Some(thread)
}
}
}
fn link_instance(mut ds: HardLinkDS, ds_res: HardLinkDS, root: String, map: IndexMap<String,HardLinkDS>) -> HardLinkDS {
@ -205,17 +208,7 @@ fn link_instance(mut ds: HardLinkDS, ds_res: HardLinkDS, root: String, map: Inde
ds.files.insert(src_tr, (src,metadata.is_dir()));
}
} else {
for file in hpds.1.files.iter() {
if let Some(_) = ds.files.get(file.0) {
continue
}
let src_tr = file.0.clone();
let src = file.1.0.clone();
let is_dir = file.1.1;
ds.files.insert(src_tr, (src,is_dir));
}
ds.files.extend(hpds.1.files);
}
}
}

View file

@ -53,11 +53,12 @@ pub fn progress_event(progress: Progress, pkgname: &str, percent: i32, howmany:
}
}
let pos = current + 1;
let pos = style(current + 1).bold().white();
let total = style(howmany + 1).bold().white();
let progress_name: String = progress_name(progress,pkgname);
let pb = this.progress.add(ProgressBar::new(progress_u64(percent)));
pb.set_style(this.style.clone());
pb.set_message(format!("({}{}/{}) {}", whitespace, pos, howmany, style(progress_name).bold()));
pb.set_message(format!("({}{}/{}) {}", whitespace, pos, total, progress_name));
this.prbar.insert(progress_ident, pb);
}
}
@ -69,7 +70,12 @@ fn progress_name(progress: Progress, pkgname: &str) -> String {
Progress::IntegrityStart => "Checking integrity".into(),
Progress::LoadStart => "Loading packages".into(),
Progress::ConflictsStart => "Checking conflicts".into(),
_ => pkgname.into()
Progress::DiskspaceStart => "Checking available diskspace".into(),
Progress::UpgradeStart => format!("Upgrading {}", pkgname),
Progress::AddStart => format!("Installing {}", pkgname),
Progress::RemoveStart => format!("Removing {}", pkgname),
Progress::DowngradeStart => format!("Downgrading {}", pkgname),
Progress::ReinstallStart => format!("Reinstalling {}", pkgname)
}
}

View file

@ -1,6 +1,9 @@
#![allow(unused_variables)]
use alpm::{AnyQuestion, Question::*};
use console::style;
use crate::utils::prompt::prompt;
#[derive(Clone)]
pub struct QueryCallback;
@ -13,8 +16,24 @@ impl QueryCallback {
pub fn questioncb(question: AnyQuestion, this: &mut QueryCallback) {
match question.question() {
Conflict(x) => (),
Replace(x) => (),
Conflict(mut x) => {
let reason = x.conflict().reason();
let pkg_a = x.conflict().package1();
let pkg_b = x.conflict().package2();
let prompt_string = format!("Conflict between {} and {}: {}. Remove package?", pkg_a, pkg_b, reason);
let prompt = prompt("->", style(&prompt_string), false);
if let Ok(_) = prompt {
x.set_remove(true);
}
},
Replace(x) => {
let prompt_string = format!("Replace package {} with {}?", x.oldpkg().name(), x.newpkg().name());
let prompt = prompt("->", style(&prompt_string), false);
if let Ok(_) = prompt {
x.set_replace(true);
}
},
Corrupted(x) => (),
RemovePkgs(x) => (),
ImportKey(x) => (),

View file

@ -1,32 +1,39 @@
#![allow(dead_code)]
use alpm::{Alpm, PackageReason, Package, TransFlag};
use console::style;
use alpm::{Alpm,
TransFlag,
PrepareResult,
CommitResult,
FileConflictType};
use crate::sync;
use crate::sync::dl_event;
use crate::{sync, utils::print_error};
use crate::sync::{dl_event, linker};
use crate::sync::dl_event::DownloadCallback;
use crate::sync::progress_event;
use crate::sync::progress_event::ProgressCallback;
use crate::sync::linker::Linker;
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
}
impl Update {
impl Update {
pub fn new() -> Self {
Self {
queried: Vec::new(),
updated: Vec::new(),
linker: Linker::new()
}
}
pub fn linker(&mut self) -> &mut Linker {
&mut self.linker
}
pub fn updated(&self) -> &Vec<String> {
&self.updated
}
@ -38,102 +45,268 @@ impl Update {
}
let inshandle = cache.instances().get(ins).unwrap();
self.update(cache, inshandle.instance().dependencies());
self.update_instance(&cache, inshandle, false);
self.queried.push(ins.clone());
self.update(cache, inshandle.instance().dependencies());
self.update_instance(sync::instantiate_alpm(&inshandle), cache, inshandle, false)
.release()
.unwrap();
}
}
fn update_instance(&mut self, cache: &InstanceCache, inshandle: &InstanceHandle, dbonly: bool) {
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")));
}
let mut handle = sync::instantiate_alpm(&inshandle);
let mut local: Vec<Package> = Vec::new();
let mut remote: Vec<Package> = Vec::new();
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();
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;
}
if dep_depth > 0 {
if dbonly {
flags = flags | TransFlag::DB_ONLY;
for pkg in handle.localdb().pkgs() {
if pkg.reason() != PackageReason::Explicit {
continue;
}
ignored.push(pkg.name().into());
}
} else {
let dep_handle = sync::instantiate_alpm(cache.instances().get(&deps[dep_depth-1]).unwrap());
for pkg in dep_handle.localdb().pkgs() {
ignored.push(pkg.name().into());
}
Alpm::release(dep_handle).unwrap();
}
for ignore in ignored.iter() {
handle.add_ignorepkg(ignore.as_bytes()).unwrap();
}
let dep_handle = sync::instantiate_alpm(cache.instances().get(&deps[dep_depth-1]).unwrap());
ignored = enumerate_ignorelist(&handle, &dep_handle, dbonly);
} else if dbonly {
Alpm::release(handle).unwrap();
return;
return handle;
}
for pkg in handle.localdb().pkgs() {
for syncdb in handle.syncdbs() {
if let Ok(pkg_remote) = syncdb.pkg(pkg.name()) {
if pkg_remote.version() > pkg.version() && ! ignored.contains(&pkg.name().into()) {
local.push(pkg);
remote.push(pkg_remote);
}
}
if let Err(_) = out_of_date(&handle, &ignored) {
if ! dbonly {
println!("{} {} is up-to-date!", style("->").bold().green(), instance);
}
return handle;
}
if local.len() > 0 {
if ! dbonly {
self.update_instance(&cache, inshandle, true);
println!("{} {} \n",style("::").bold().red(), style("Package changes").bold());
for val in 0..local.len() {
let pkg_remote = remote[val];
let pkg = local[val];
println!("{} {} -> {}", style(pkg.name()).bold(), style(pkg.version()).bold().yellow(), style(pkg_remote.version()).bold().green());
} println!();
if let Err(_) = prompt("Proceed with installation?") {
return;
}
handle.set_progress_cb(ProgressCallback::new(true), progress_event::progress_event);
handle.set_dl_cb(DownloadCallback::new(true), dl_event::download_event);
}
handle.trans_init(flags).unwrap();
for val in 0..local.len() {
handle.trans_add_pkg(remote[val]).unwrap();
}
handle.trans_prepare().unwrap();
handle.trans_commit().unwrap();
handle.trans_release().unwrap();
self.updated.push(instance.clone());
} else if ! dbonly {
println!("{} {} is up-to-date!", style("->").bold().green(), instance);
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);
}
Alpm::release(handle).unwrap();
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_progress_cb(ProgressCallback::new(true), progress_event::progress_event);
handle.set_dl_cb(DownloadCallback::new(true), dl_event::download_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()));
}
}
pub fn update(mut update: Update, cache: &InstanceCache) {
update.update(&cache, &cache.containers_base());
update.update(&cache, &cache.containers_dep());
if update.updated().len() > 0 {
println!("{} {} ",style("::").bold().green(), style("Synchronising container filesystems...").bold());
update.linker().start(cache.registered().len());
linker::wait_on(update.linker().link(&cache, cache.registered(), Vec::new()));
update.linker().finish();
}
update.update(&cache, &cache.containers_root());
println!("{} Transaction complete.",style("->").bold().green());
}
fn confirm_transaction(handle: &Alpm) -> Result<(),()> {
println!("{} {} \n",style("::").bold().red(), style("Package changes").bold());
let mut installed_size_old: i64 = 0;
let mut installed_size: i64 = 0;
let mut download: i64 = 0;
for val in handle.trans_add() {
let pkg_sync = val;
let pkg = handle.localdb().pkg(pkg_sync.name()).unwrap();
installed_size_old += pkg.isize();
installed_size += pkg_sync.isize();
download += pkg_sync.download_size();
println!("{} {} -> {}", pkg.name(), style(pkg.version()).bold().yellow(), style(pkg_sync.version()).bold().green());
}
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 download > 0 {
println!("{}: {}", style("Total Download Size").bold(), format_unit(download));
}
println!();
prompt("::", style("Proceed with installation?").bold(), true)
}
fn handle_erroneous_transaction<'a>(result: CommitResult<'a>, error: alpm::Error) {
match result {
CommitResult::FileConflict(file) => {
print_error("Conflicting files in container filesystem:");
for conflict in file.iter() {
match conflict.conflict_type() {
FileConflictType::Filesystem => {
let file = conflict.file();
let target = conflict.target();
println!("{}: '{}' already exists.", target, file);
},
FileConflictType::Target => {
let file = conflict.file();
let target = style(conflict.target()).bold().white();
if let Some(conflicting) = conflict.conflicting_target() {
let conflicting = style(conflicting).bold().white();
println!("{}: '{}' is owned by {}", target, file, conflicting);
} else {
println!("{}: '{}' is owned by foreign target", target, file);
}
},
}
}
},
CommitResult::PkgInvalid(p) => {
let mut pkg_string = String::new();
for pkg in p.iter() {
let pkg = style(pkg).bold().white();
pkg_string.push_str(format!("{}, ", pkg).as_str());
}
pkg_string.truncate(pkg_string.len()-2);
print_error(format!("Invalid packages found: {}", pkg_string));
},
CommitResult::Ok => print_error(format!("{}", error)) //haha, this should **never** happen
}
println!("{} Transaction failed.", style("->").red());
std::process::exit(1);
}
fn handle_erroneous_preparation<'a>(result: PrepareResult<'a>, error: alpm::Error) {
match result {
PrepareResult::PkgInvalidArch(list) => {
for package in list.iter() {
print_error(format!("Invalid architecture {} for {}", style(package.arch().unwrap()).bold(), style(package.name()).bold()));
}
},
PrepareResult::UnsatisfiedDeps(list) => {
for missing in list.iter() {
print_error(format!("Unsatisifed dependency {} for target {}", style(missing.depend()).bold(), style(missing.target()).bold()));
}
},
PrepareResult::ConflictingDeps(list) => {
for conflict in list.iter() {
print_error(format!("Conflict between {} and {}: {}", style(conflict.package1()).bold(), style(conflict.package2()).bold(), conflict.reason()));
}
},
PrepareResult::Ok => print_error(format!("{}", error))
}
println!("{} Transaction failed.", style("->").red());
std::process::exit(1);
}
fn unit_suffix<'a>(i: i8) -> &'a str {
match i {
0 => "KB",
1 => "MB",
2 => "GB",
3 => "TB",
4 => "PB",
_ => "B"
}
}
fn format_unit(bytes: i64) -> String {
let conditional: f64 = if bytes > -1 { 1000.0 } else { -1000.0 };
let diviser: f64 = 1000.0;
let mut size: f64 = bytes as f64;
let mut idx: i8 = -1;
while if bytes > -1 { size > conditional } else { size < conditional } {
size = size / diviser;
idx += 1;
}
if idx == -1 {
format!("{:.0} {}", size, unit_suffix(idx))
} else {
format!("{:.2} {}", size, unit_suffix(idx))
}
}
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());
}
} else {
for pkg in dep_handle.localdb().pkgs() {
ignored.push(pkg.name().into());
}
}
ignored
}
fn out_of_date(handle: &Alpm, ignored: &Vec<String>) -> Result<(), ()> {
for pkg in handle.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
}
if pkg.sync_new_version(handle.syncdbs()).is_some() {
return Ok(());
}
}
Err(())
}
fn sync_new_packages(handle: &Alpm, ignored: &Vec<String>) {
for pkg in handle.localdb().pkgs() {
if ignored.contains(&pkg.name().into()) {
continue;
}
if let Some(pkg) = pkg.sync_new_version(handle.syncdbs()) {
handle.trans_add_pkg(pkg).unwrap();
}
}
}

View file

@ -3,6 +3,8 @@ use std::collections::HashMap;
use crate::utils;
use super::print_help_msg;
pub struct Arguments<'a> {
prefix: String,
runtime: Vec<String>,
@ -109,3 +111,12 @@ impl<'a> Arguments<'a> {
pub fn get_runtime(&self) -> &Vec<String> { &self.runtime }
pub fn get_prefix(&self) -> &String { &self.prefix }
}
pub fn invalid() {
let mut ar = String::new();
for arg in env::args().skip(1).collect::<Vec<_>>().iter() {
ar.push_str(&format!("{} ", &arg));
}
ar.truncate(ar.len()-1);
print_help_msg(&format!("Invalid arguments -- '{}'", ar));
}

View file

@ -1,11 +1,12 @@
#![allow(dead_code)]
use console::{style, Style};
use console::{style, Style, StyledObject};
use dialoguer::{theme::ColorfulTheme, Input};
pub fn prompt(prompt: &str) -> Result<(),()> {
if let Ok(value) = create_prompt(prompt, "[Y/n]") {
if value.to_lowercase() == "y" || value.is_empty() {
pub fn prompt(prefix: &str, prompt: StyledObject<&str>, yn_prompt: bool) -> Result<(),()> {
if let Ok(value) = create_prompt(prompt, prefix,
if yn_prompt { "[Y/n]" } else { "[N/y]" }) {
if value.to_lowercase() == "y" || (yn_prompt && value.is_empty()) {
Ok(())
} else {
Err(())
@ -15,32 +16,20 @@ pub fn prompt(prompt: &str) -> Result<(),()> {
}
}
pub fn prompt_no(prompt: &str) -> Result<(),()> {
if let Ok(value) = create_prompt(prompt, "[y/N]") {
if value.to_lowercase() == "y" {
Ok(())
} else {
Err(())
}
} else {
Err(())
}
}
fn create_prompt(message: &str, prompt: &str) -> Result<String, std::io::Error> {
fn create_prompt(message: StyledObject<&str>, prefix: &str, prompt: &str) -> Result<String, std::io::Error> {
let theme = ColorfulTheme {
success_prefix: style("::".to_string()).green().bold(),
prompt_prefix: style("::".to_string()).green().bold(),
error_prefix: style("::".to_string()).red().bold(),
success_prefix: style(prefix.into()).green().bold(),
prompt_prefix: style(prefix.into()).green().bold(),
error_prefix: style(prefix.into()).red().bold(),
prompt_suffix: style(prompt.to_string()).bold(),
success_suffix: style(prompt.to_string()).bold(),
prompt_style: Style::new().bold(),
prompt_style: Style::new(),
values_style: Style::new(),
..ColorfulTheme::default()
};
return Input::with_theme(&theme)
.with_prompt(message)
.with_prompt(message.to_string())
.allow_empty(true)
.interact_text();
}