Skip to content

Commit

Permalink
feat(oma-pm): impl BrokenPackage struct ...
Browse files Browse the repository at this point in the history
... to make pretty dependency issue output
  • Loading branch information
eatradish committed Aug 17, 2024
1 parent 4201485 commit 4aedb1c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 35 deletions.
88 changes: 55 additions & 33 deletions oma-pm/src/apt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
borrow::Cow,
fmt,
io::{self, ErrorKind, Write},
path::{Path, PathBuf},
process::Command,
Expand Down Expand Up @@ -71,7 +72,7 @@ pub struct OmaApt {
select_pkgs: Vec<String>,
tokio: Runtime,
connection: Option<Connection>,
unmet: Vec<String>,
unmet: Vec<BrokenPackage>,
}

#[derive(Debug, thiserror::Error)]
Expand All @@ -87,7 +88,7 @@ pub enum OmaAptError {
#[error("Failed to mark reinstall pkg: {0}")]
MarkReinstallError(String, String),
#[error("Find Dependency problem")]
DependencyIssue(Vec<String>),
DependencyIssue(Vec<BrokenPackage>),
#[error("Package: {0} is essential.")]
PkgIsEssential(String),
#[error("Package: {0} is no candidate.")]
Expand Down Expand Up @@ -633,7 +634,7 @@ impl OmaApt {
if let Err(e) = self.cache.resolve(!no_fixbroken) {
debug!("{e:#?}");
for pkg in self.cache.iter() {
let res = show_broken_pkg(&self.cache, &pkg, false);
let res = broken_pkg(&self.cache, &pkg, false);
if !res.is_empty() {
self.unmet.extend(res);
}
Expand Down Expand Up @@ -1306,30 +1307,55 @@ fn also_install_recommends(ver: &Version, cache: &Cache) {
#[cfg(not(feature = "aosc"))]
fn also_install_recommends(_ver: &Version, _cache: &Cache) {}

fn show_broken_pkg(cache: &Cache, pkg: &Package, now: bool) -> Vec<String> {
#[derive(Debug, Clone)]
pub struct BrokenPackage {
pub name: String,
pub why: (String, String),
pub reson: Option<BrokenPackageReson>,
pub or: bool,
}

#[derive(Debug, Clone)]
pub enum BrokenPackageReson {
ToBeInstall(String),
NotGoingToBeInstall,
VirtualPkg,
NotInstallable,
}

impl fmt::Display for BrokenPackageReson {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BrokenPackageReson::ToBeInstall(version) => {
write!(f, "but {version} is to be installed")
}
BrokenPackageReson::NotGoingToBeInstall => {
write!(f, "but it is not going to be installed")
}
BrokenPackageReson::VirtualPkg => write!(f, "but it is a virtual package"),
BrokenPackageReson::NotInstallable => write!(f, "but it is not installable"),
}
}
}

fn broken_pkg(cache: &Cache, pkg: &Package, now: bool) -> Vec<BrokenPackage> {
let mut result = vec![];
// If the package isn't broken for the state Return None
if (now && !pkg.is_now_broken()) || (!now && !pkg.is_inst_broken()) {
return result;
};

let mut line = String::new();

line += &format!("{} :", pkg.fullname(true));
let name = pkg.fullname(true);

// Pick the proper version based on now status.
// else Return with just the package name like Apt does.
let Some(ver) = (match now {
true => pkg.installed(),
false => pkg.install_version(),
}) else {
result.push(line);
return result;
};

let indent = pkg.fullname(false).len() + 3;
let mut first = true;

// ShowBrokenDeps
for dep in ver.depends_map().values().flatten() {
for (i, base_dep) in dep.iter().enumerate() {
Expand All @@ -1347,42 +1373,38 @@ fn show_broken_pkg(cache: &Cache, pkg: &Package, now: bool) -> Vec<String> {
continue;
}

if !first {
line += &" ".repeat(indent);
}
first = false;
let mut dep_reson = base_dep.target_package().fullname(true);

// If it's the first or Dep
if i > 0 {
line += &" ".repeat(base_dep.dep_type().as_ref().len() + 3);
} else {
line += &format!(" {}: ", base_dep.dep_type())
if let (Ok(ver_str), Some(comp)) = (base_dep.target_ver(), base_dep.comp_type()) {
dep_reson += &format!(" ({comp} {ver_str})");
}

line += &base_dep.target_package().fullname(true);
let why = (base_dep.dep_type().to_string(), dep_reson);

if let (Ok(ver_str), Some(comp)) = (base_dep.target_ver(), base_dep.comp_type()) {
line += &format!(" ({comp} {ver_str})");
}
let mut reson = None;

let target = base_dep.target_package();
if !target.has_provides() {
if let Some(target_ver) = target.install_version() {
line += &format!(" but {target_ver} is to be installed")
reson = Some(BrokenPackageReson::ToBeInstall(
target_ver.version().to_string(),
));
} else if target.candidate().is_some() {
line += " but it is not going to be installed";
reson = Some(BrokenPackageReson::NotGoingToBeInstall);
} else if target.has_provides() {
line += " but it is a virtual package";
// TODO: (By upstream ???)
reson = Some(BrokenPackageReson::VirtualPkg);
} else {
line += " but it is not installable";
reson = Some(BrokenPackageReson::NotInstallable);
}
}

if i + 1 != dep.len() {
line += " or"
}
result.push(line.clone());
line.clear();
result.push(BrokenPackage {
name: name.to_string(),
why,
reson,
or: i + 1 != dep.len(),
});
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::fmt::Display;
use std::io::{self, ErrorKind};

use oma_console::due_to;
use oma_console::writer::gen_prefix;
use oma_contents::OmaContentsError;
use oma_fetch::checksum::ChecksumError;
use oma_fetch::DownloadError;
Expand Down Expand Up @@ -661,7 +660,14 @@ pub fn oma_apt_error_to_output(err: OmaAptError) -> OutputError {
info!("{}", fl!("dep-issue-2"));
println!();
for i in v {
println!("{}{i}", gen_prefix("", 10));
println!("{}:", i.name);
println!(" {}: {}", i.why.0, i.why.1);
if let Some(v) = &i.reson {
println!(" {}", v);
}
if i.or {
println!(" or:");
}
}
println!();
}
Expand Down

0 comments on commit 4aedb1c

Please sign in to comment.