fix: duplicate packages in installation
Signed-off-by: sisungo <[email protected]>
This commit is contained in:
@@ -26,6 +26,7 @@ tar = "0.4"
|
||||
tempfile = "3"
|
||||
thiserror = "2"
|
||||
toml = "1"
|
||||
itertools = "0.15"
|
||||
ureq = { version = "3", features = ["socks-proxy"] }
|
||||
url = { version = "2", features = ["serde"] }
|
||||
nix = { version = "0.31", features = ["fs"] }
|
||||
|
||||
@@ -11,6 +11,8 @@ path = "src/main.rs"
|
||||
anyhow = "1"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
console = "0.16"
|
||||
nix = { version = "0.31", features = ["sched"] }
|
||||
itertools = "0.15"
|
||||
packie = { path = "../" }
|
||||
rust-i18n = "4"
|
||||
indicatif = "0.18"
|
||||
|
||||
+2
-2
@@ -14,11 +14,11 @@ pub fn yesno(prompt: &str) -> bool {
|
||||
}
|
||||
|
||||
pub fn print_list(indent: u32, list: impl Iterator<Item = impl AsRef<str>>) {
|
||||
let (_, column) = Term::stdout().size();
|
||||
let (row, _) = Term::stdout().size();
|
||||
let mut line_used: usize = 0;
|
||||
for i in list {
|
||||
let mut i = i.as_ref().to_string();
|
||||
if line_used >= column as _ {
|
||||
if line_used >= row as _ {
|
||||
line_used = 0;
|
||||
println!();
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
use crate::common::format_size;
|
||||
use anyhow::anyhow;
|
||||
use clap::Parser;
|
||||
use packie::{PackieBuilder, package::PkgSpec};
|
||||
|
||||
use crate::common::format_size;
|
||||
use rust_i18n::t;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Cli {
|
||||
@@ -13,10 +13,10 @@ pub fn main(cli: Cli) -> anyhow::Result<()> {
|
||||
let mut packie = PackieBuilder::new().readonly(true).build()?;
|
||||
let mut found = packie.search_installation(&cli.pkgspec)?;
|
||||
if found.len() == 0 {
|
||||
return Err(anyhow!("no package found"));
|
||||
return Err(anyhow!("{}", t!("info.no_package_found")));
|
||||
}
|
||||
if found.len() != 1 {
|
||||
return Err(anyhow!("not unique package spec"));
|
||||
return Err(anyhow!("{}", t!("info.pkgspec_not_unique")));
|
||||
}
|
||||
let found = found.remove(0);
|
||||
|
||||
|
||||
+5
-1
@@ -1,6 +1,7 @@
|
||||
use crate::common::{format_size, print_list, yesno};
|
||||
use clap::Parser;
|
||||
use indicatif::ProgressBar;
|
||||
use itertools::Itertools;
|
||||
use packie::{
|
||||
PackieBuilder, install::InstallOptions, package::PkgSpec, repo::DownloadPackageEvent,
|
||||
};
|
||||
@@ -30,7 +31,10 @@ pub fn main(cli: Cli) -> anyhow::Result<()> {
|
||||
for i in cli.items {
|
||||
packages.append(&mut packie.calculate_depgraph(i.parse::<PkgSpec>()?)?);
|
||||
}
|
||||
packages.dedup_by_key(|x| x.repo_pkg.pkg_manifest.pkg_ident());
|
||||
let packages: Vec<_> = packages
|
||||
.into_iter()
|
||||
.unique_by(|x| x.repo_pkg.pkg_manifest.pkg_ident())
|
||||
.collect();
|
||||
|
||||
if packages.is_empty() {
|
||||
eprintln!("No packages to install.");
|
||||
|
||||
+10
-1
@@ -74,7 +74,16 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn chroot(new_root: &Path) -> std::io::Result<()> {
|
||||
nix::sched::unshare(nix::sched::CloneFlags::CLONE_NEWUSER)?;
|
||||
nix::sched::unshare(nix::sched::CloneFlags::CLONE_NEWNS)?;
|
||||
std::os::unix::fs::chroot(new_root)?;
|
||||
std::env::set_current_dir("/")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "unix", not(target_os = "linux")))]
|
||||
fn chroot(new_root: &Path) -> std::io::Result<()> {
|
||||
std::os::unix::fs::chroot(new_root)?;
|
||||
std::env::set_current_dir("/")?;
|
||||
|
||||
+31
-4
@@ -1,18 +1,45 @@
|
||||
use crate::common::{print_list, yesno};
|
||||
use anyhow::anyhow;
|
||||
use clap::Parser;
|
||||
use packie::{PackieBuilder, package::PkgSpec};
|
||||
use rust_i18n::t;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Cli {
|
||||
pkgspecs: Vec<PkgSpec>,
|
||||
#[arg(short, long)]
|
||||
yes: bool,
|
||||
|
||||
items: Vec<PkgSpec>,
|
||||
}
|
||||
|
||||
pub fn main(cli: Cli) -> anyhow::Result<()> {
|
||||
let mut packie = PackieBuilder::new().build()?;
|
||||
for pkgspec in cli.pkgspecs {
|
||||
let mut packages = Vec::with_capacity(cli.items.len());
|
||||
for pkgspec in cli.items {
|
||||
let mut found = packie.search_installation(&pkgspec)?;
|
||||
if found.is_empty() {
|
||||
return Err(anyhow!("{}", t!("remove.package_not_found")));
|
||||
}
|
||||
if found.len() != 1 {
|
||||
return Err(anyhow!("{}", t!("remove.pkgspec_not_unique")));
|
||||
}
|
||||
packages.push(found.remove(0));
|
||||
}
|
||||
println!("{}", t!("remove.prompt_to_remove"));
|
||||
print_list(4, packages.iter().map(|x| x.install_pkgspec.to_string()));
|
||||
if cli.yes {
|
||||
println!("y");
|
||||
} else if !yesno(&t!("remove.confirm_removal")) {
|
||||
println!("{}", t!("remove.aborting"));
|
||||
}
|
||||
for i in packages {
|
||||
println!(
|
||||
"{}",
|
||||
t!("remove.action_hint", package = i.pkg_manifest.pkg_ident())
|
||||
);
|
||||
packie
|
||||
.remove(&pkgspec)
|
||||
.map_err(|err| anyhow!("failed to remove {pkgspec}: {err}"))?;
|
||||
.remove(&i.pkg_manifest.pkg_ident().into())
|
||||
.map_err(|error| anyhow!("{}", t!("remove.action_failure", error = error)))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,3 +17,30 @@ install.confirm_installation:
|
||||
install.aborting:
|
||||
en: "Aborting."
|
||||
zh-CN: "中止。"
|
||||
info.no_package_found:
|
||||
en: "The specified package was not found."
|
||||
zh-CN: "找不到指定的包。"
|
||||
info.pkgspec_not_unique:
|
||||
en: "The specified package spec was not unique."
|
||||
zh-CN: "指定的包规范匹配了多个包。"
|
||||
remove.package_not_found:
|
||||
en: "The specified package was not found."
|
||||
zh-CN: "找不到指定的包。"
|
||||
remove.pkgspec_not_unique:
|
||||
en: "The specified package spec was not unique."
|
||||
zh-CN: "指定的包规范匹配了多个包。"
|
||||
remove.action_failure:
|
||||
en: "Failed to remove the specified package: %{error}"
|
||||
zh-CN: "无法移除指定的包:%{error}"
|
||||
remove.prompt_to_remove:
|
||||
en: "The following packages are to be removed:"
|
||||
zh-CN: "将要移除下面的包:"
|
||||
remove.confirm_removal:
|
||||
en: "Confirm to remove?"
|
||||
zh-CN: "确认移除?"
|
||||
remove.aborting:
|
||||
en: "Aborting."
|
||||
zh-CN: "中止。"
|
||||
remove.action_hint:
|
||||
en: "Removing package %{package} ..."
|
||||
zh-CN: "正在移除包 %{package} ..."
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::path::Path;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct InstallOptions {
|
||||
/// Package spec to record for this installation.
|
||||
pub install_pkgspec: Option<PkgSpec>,
|
||||
}
|
||||
impl InstallOptions {
|
||||
|
||||
+5
-2
@@ -2,6 +2,7 @@ use crate::{
|
||||
package::{AbsPkgIdent, PkgIdent, PkgManifest, PkgSpec},
|
||||
version::VersionFilter,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rusqlite::{OpenFlags, Row, params};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -27,8 +28,10 @@ impl super::Packie {
|
||||
for (_, provider) in abs {
|
||||
real.push(self.local_db.select_installation_by_ident(&provider)?);
|
||||
}
|
||||
real.dedup_by_key(|x| x.pkg_manifest.pkg_ident());
|
||||
Ok(real)
|
||||
Ok(real
|
||||
.into_iter()
|
||||
.unique_by(|x| x.pkg_manifest.pkg_ident())
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -4,6 +4,7 @@ mod serve;
|
||||
#[doc(inline)]
|
||||
pub use download::DownloadError;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
#[doc(inline)]
|
||||
pub use serve::RepoServeDir;
|
||||
@@ -389,8 +390,9 @@ impl QuerySession {
|
||||
all.push((name.into(), real));
|
||||
}
|
||||
}
|
||||
all.dedup_by_key(|(repo, pkg)| (repo.to_string(), pkg.pkg_manifest.pkg_ident()));
|
||||
all
|
||||
all.into_iter()
|
||||
.unique_by(|(repo, pkg)| (repo.to_string(), pkg.pkg_manifest.pkg_ident()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user