Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine apt, pacman & dnf block to packages block #1988

Merged
merged 33 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8eb4a47
refactor: Add `packages` in block and remove apt,pacman
IshanGrover2004 Jan 19, 2024
36025ed
refactor: Remove `pacman.rs` file to add in `packages` block
IshanGrover2004 Jan 19, 2024
9a6bb88
refactor: Remove `apt.rs` file to add in `packages` block
IshanGrover2004 Jan 19, 2024
ba1dc95
feat: Add `packages` block to check updates for package managers
IshanGrover2004 Jan 19, 2024
76c829e
feat: Add `apt` package manager to `packages` block
IshanGrover2004 Jan 19, 2024
8d2b5f4
feat: Add `pacman` & `aur` package manager to `packages` block
IshanGrover2004 Jan 19, 2024
bd5b9d6
docs: Add examples to documentation for packages block
IshanGrover2004 Jan 19, 2024
d2f3037
Merge branch 'greshake:master' into 1964-list-update-packages
IshanGrover2004 Jan 19, 2024
b15ffe4
fix: Spelling check
IshanGrover2004 Jan 19, 2024
85eff45
feat: Add deleted old blocks
IshanGrover2004 Jan 19, 2024
0c4dee8
refactor: Re-arrange block list in alphabetical order
IshanGrover2004 Jan 19, 2024
3dcc9ef
refactor: Add function to `impl Apt` block
IshanGrover2004 Jan 19, 2024
9897b3a
docs: Remove documentation from submodules and add to `packages` block
IshanGrover2004 Jan 20, 2024
4c115cc
refactor: Use `Vec<Box<dyn Backend>>` for later use also and clean code
IshanGrover2004 Jan 20, 2024
762c3e6
refactor: Remove `setup` function and add in constructor in backends
IshanGrover2004 Jan 20, 2024
3ff1397
chore: clippy fixes
IshanGrover2004 Jan 20, 2024
b4f229b
feat: Add depreciation patches for apt & pacman blocks
IshanGrover2004 Jan 20, 2024
ad035f0
refactor: Remove vec of critical & warning updates regex and Add opti…
IshanGrover2004 Jan 21, 2024
7d61b37
refactor: Add parameters to Apt::new()
IshanGrover2004 Jan 21, 2024
12fc736
refactor: Add HashMap for getting updates in generic way
IshanGrover2004 Jan 21, 2024
b76fed9
feat: Re-use the code in `blocks/apt.rs` & `blocks/pacman.rs`
IshanGrover2004 Jan 21, 2024
2d6c702
feat: Add `dnf` to packages block and re-use code in `dnf.rs`
IshanGrover2004 Jan 21, 2024
94b6bea
chore: Clippy fixes
IshanGrover2004 Jan 21, 2024
1da106f
refactor: Update `get_update_list` to return `Vec<String>` and remove…
IshanGrover2004 Jan 21, 2024
d48d0f7
refactor: Move `has_matching_updates` function out of Backend trait
IshanGrover2004 Jan 21, 2024
142e701
fix: Remove tokio runtime usage
IshanGrover2004 Jan 21, 2024
61902f4
refactor: Inline backend match block
IshanGrover2004 Jan 21, 2024
bff8686
refactor: Use same hashmap while setting the values
IshanGrover2004 Jan 21, 2024
203de17
feat: Restore `tokio::try_join!` for parallel execution
IshanGrover2004 Jan 22, 2024
cd6abc2
feat: Add depreciation patches for `dnf` blocks
IshanGrover2004 Jan 23, 2024
8806b57
docs: Add Default value for `package_manager`
IshanGrover2004 Jan 24, 2024
94aad81
docs: Make less verbose by deleting repetitive info
IshanGrover2004 Jan 24, 2024
4ce8aba
fix: Swap `$both` with `$total` in docs
IshanGrover2004 Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ use crate::{BoxedFuture, Request, RequestCmd};

macro_rules! define_blocks {
{
$( $(#[cfg(feature = $feat: literal)])? $block: ident $(,)? )*
$(
$(#[cfg(feature = $feat: literal)])?
$(#[deprecated($($dep_k: ident = $dep_v: literal),+)])?
$block: ident $(,)?
)*
} => {
$(
$(#[cfg(feature = $feat)])?
$(#[cfg_attr(docsrs, doc(cfg(feature = $feat)))])?
$(#[deprecated($($dep_k = $dep_v),+)])?
pub mod $block;
)*

Expand All @@ -58,6 +63,7 @@ macro_rules! define_blocks {
$(
$(#[cfg(feature = $feat)])?
#[allow(non_camel_case_types)]
#[allow(deprecated)]
$block($block::Config),
)*
Err(&'static str, Error),
Expand All @@ -78,6 +84,7 @@ macro_rules! define_blocks {
match self {
$(
$(#[cfg(feature = $feat)])?
#[allow(deprecated)]
Self::$block(config) => futures.push(async move {
while let Err(err) = $block::run(&config, &api).await {
if api.set_error(err).is_err() {
Expand Down Expand Up @@ -114,6 +121,7 @@ macro_rules! define_blocks {
match block_name {
$(
$(#[cfg(feature = $feat)])?
#[allow(deprecated)]
stringify!($block) => match $block::Config::deserialize(table) {
Ok(config) => Ok(BlockConfig::$block(config)),
Err(err) => Ok(BlockConfig::Err(stringify!($block), crate::errors::Error::new(err.to_string()))),
Expand All @@ -136,6 +144,10 @@ macro_rules! define_blocks {

define_blocks!(
amd_gpu,
#[deprecated(
since = "0.33.0",
note = "The block has been deprecated in favor of the the packages block"
)]
apt,
backlight,
battery,
Expand All @@ -144,6 +156,10 @@ define_blocks!(
custom,
custom_dbus,
disk_space,
#[deprecated(
since = "0.33.0",
note = "The block has been deprecated in favor of the the packages block"
)]
dnf,
docker,
external_ip,
Expand All @@ -162,6 +178,11 @@ define_blocks!(
#[cfg(feature = "notmuch")]
notmuch,
nvidia_gpu,
packages,
#[deprecated(
since = "0.33.0",
note = "The block has been deprecated in favor of the the packages block"
)]
pacman,
pomodoro,
rofication,
Expand Down
123 changes: 10 additions & 113 deletions src/blocks/apt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,12 @@
//!
//! - `update`

use std::env;
use std::process::Stdio;

use regex::Regex;

use tokio::fs::{create_dir_all, File};
use tokio::process::Command;

use super::prelude::*;
use super::{
packages::{apt::Apt, has_matching_update, Backend},
prelude::*,
};

#[derive(Deserialize, Debug, SmartDefault)]
#[serde(deny_unknown_fields, default)]
Expand Down Expand Up @@ -100,45 +97,15 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
.transpose()
.error("invalid ignore updates regex")?;

let mut cache_dir = env::temp_dir();
cache_dir.push("i3rs-apt");
if !cache_dir.exists() {
create_dir_all(&cache_dir)
.await
.error("Failed to create temp dir")?;
}

let apt_config = format!(
"Dir::State \"{}\";\n
Dir::State::lists \"lists\";\n
Dir::Cache \"{}\";\n
Dir::Cache::srcpkgcache \"srcpkgcache.bin\";\n
Dir::Cache::pkgcache \"pkgcache.bin\";",
cache_dir.display(),
cache_dir.display(),
);

let mut config_file = cache_dir;
config_file.push("apt.conf");
let config_file = config_file.to_str().unwrap();

let mut file = File::create(&config_file)
.await
.error("Failed to create config file")?;
file.write_all(apt_config.as_bytes())
.await
.error("Failed to write to config file")?;
let backend = Apt::new(config.ignore_phased_updates).await?;

loop {
let mut widget = Widget::new();
let updates = get_updates_list(config_file).await?;
let count = get_update_count(
config_file,
config.ignore_phased_updates,
ignore_updates_regex.as_ref(),
&updates,
)
.await?;
let mut updates = backend.get_updates_list().await?;
if let Some(regex) = ignore_updates_regex.clone() {
updates.retain(|u| !regex.is_match(u));
}
let count = updates.len();

widget.set_format(match count {
0 => format_up_to_date.clone(),
Expand Down Expand Up @@ -177,73 +144,3 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
}
}
}

async fn get_updates_list(config_path: &str) -> Result<String> {
Command::new("apt")
.env("APT_CONFIG", config_path)
.args(["update"])
.stdout(Stdio::null())
.stdin(Stdio::null())
.spawn()
.error("Failed to run `apt update`")?
.wait()
.await
.error("Failed to run `apt update`")?;
let stdout = Command::new("apt")
.env("LANG", "C")
.env("APT_CONFIG", config_path)
.args(["list", "--upgradable"])
.output()
.await
.error("Problem running apt command")?
.stdout;
String::from_utf8(stdout).error("apt produced non-UTF8 output")
}

async fn get_update_count(
config_path: &str,
ignore_phased_updates: bool,
ignore_updates_regex: Option<&Regex>,
updates: &str,
) -> Result<usize> {
let mut cnt = 0;

for update_line in updates
.lines()
.filter(|line| line.contains("[upgradable"))
.filter(|line| ignore_updates_regex.map_or(true, |re| !re.is_match(line)))
{
if !ignore_phased_updates || !is_phased_update(config_path, update_line).await? {
cnt += 1;
}
}

Ok(cnt)
}

fn has_matching_update(updates: &str, regex: &Regex) -> bool {
updates.lines().any(|line| regex.is_match(line))
}

async fn is_phased_update(config_path: &str, package_line: &str) -> Result<bool> {
let package_name_regex = regex!(r#"(.*)/.*"#);
let package_name = &package_name_regex
.captures(package_line)
.error("Couldn't find package name")?[1];

let output = String::from_utf8(
Command::new("apt-cache")
.args(["-c", config_path, "policy", package_name])
.output()
.await
.error("Problem running apt-cache command")?
.stdout,
)
.error("Problem capturing apt-cache command output")?;

let phased_regex = regex!(r".*\(phased (\d+)%\).*");
Ok(match phased_regex.captures(&output) {
Some(matches) => &matches[1] != "100",
None => false,
})
}
32 changes: 9 additions & 23 deletions src/blocks/dnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@
//!
//! - `update`

use super::prelude::*;
use regex::Regex;
use tokio::process::Command;

use super::{
packages::{dnf::Dnf, has_matching_update, Backend},
prelude::*,
};

#[derive(Deserialize, Debug, SmartDefault)]
#[serde(deny_unknown_fields, default)]
Expand Down Expand Up @@ -77,11 +80,13 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
.transpose()
.error("invalid critical updates regex")?;

let backend = Dnf::new();

loop {
let mut widget = Widget::new();

let updates = get_updates_list().await?;
let count = get_update_count(&updates);
let updates = backend.get_updates_list().await?;
let count = updates.len();

widget.set_format(match count {
0 => format_up_to_date.clone(),
Expand Down Expand Up @@ -120,22 +125,3 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
}
}
}

async fn get_updates_list() -> Result<String> {
let stdout = Command::new("sh")
.env("LC_LANG", "C")
.args(["-c", "dnf check-update -q --skip-broken"])
.output()
.await
.error("Failed to run dnf check-update")?
.stdout;
String::from_utf8(stdout).error("dnf produced non-UTF8 output")
}

fn get_update_count(updates: &str) -> usize {
updates.lines().filter(|line| line.len() > 1).count()
}

fn has_matching_update(updates: &str, regex: &Regex) -> bool {
updates.lines().any(|line| regex.is_match(line))
}
Loading