#![doc = doc_self!()]
use std::sync::LazyLock;
use async_trait::async_trait;
use indoc::indoc;
use itertools::Itertools;
use tap::prelude::*;
use super::{NoCacheStrategy, Pm, PmHelper, PmMode, PromptStrategy, Strategy};
use crate::{config::Config, error::Result, exec::Cmd};
macro_rules! doc_self {
() => {
indoc! {"
The [Portage Package Manager](https://wiki.gentoo.org/wiki/Portage).
"}
};
}
use doc_self;
#[doc = doc_self!()]
#[derive(Debug)]
pub struct Emerge {
cfg: Config,
}
static STRAT_ASK: LazyLock<Strategy> = LazyLock::new(|| Strategy {
prompt: PromptStrategy::native_confirm(["--ask"]),
..Strategy::default()
});
static STRAT_INTERACTIVE: LazyLock<Strategy> = LazyLock::new(|| Strategy {
prompt: PromptStrategy::native_confirm(["--interactive"]),
..Strategy::default()
});
static STRAT_INSTALL: LazyLock<Strategy> = LazyLock::new(|| Strategy {
prompt: PromptStrategy::native_confirm(["--ask"]),
no_cache: NoCacheStrategy::Scc,
..Strategy::default()
});
impl Emerge {
#[must_use]
#[allow(missing_docs)]
pub const fn new(cfg: Config) -> Self {
Self { cfg }
}
}
#[async_trait]
impl Pm for Emerge {
fn name(&self) -> &'static str {
"emerge"
}
fn cfg(&self) -> &Config {
&self.cfg
}
async fn q(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.qs(kws, flags).await
}
async fn qi(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.si(kws, flags).await
}
async fn ql(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::new(["qlist"]).kws(kws).flags(flags)).await
}
async fn qo(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::new(["qfile"]).kws(kws).flags(flags)).await
}
async fn qs(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::new(["qlist", "-I"]).kws(kws).flags(flags))
.await
}
async fn qu(&self, _kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::new(["emerge", "-uDNp", "@world"]).flags(flags))
.await
}
async fn r(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
Cmd::with_sudo(["emerge", "--unmerge"])
.kws(kws)
.flags(flags)
.pipe(|cmd| self.run_with(cmd, PmMode::default(), &STRAT_ASK))
.await
}
async fn rs(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
Cmd::with_sudo(["emerge", "--depclean"])
.kws(kws)
.flags(flags)
.pipe(|cmd| self.run_with(cmd, PmMode::default(), &STRAT_ASK))
.await
}
async fn s(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
Cmd::with_sudo(["emerge"])
.kws(kws)
.flags(flags)
.pipe(|cmd| self.run_with(cmd, PmMode::default(), &STRAT_INSTALL))
.await
}
async fn sc(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
Cmd::with_sudo(["eclean-dist"])
.kws(kws)
.flags(flags)
.pipe(|cmd| self.run_with(cmd, PmMode::default(), &STRAT_INTERACTIVE))
.await
}
async fn scc(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.sc(kws, flags).await
}
async fn si(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
let kws = kws.iter().map(|kw| format!("^{kw}$")).collect_vec();
self.run(Cmd::new(["emerge", "-s"]).kws(kws).flags(flags))
.await
}
async fn ss(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::new(["qsearch"]).kws(kws).flags(flags)).await
}
async fn su(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
Cmd::with_sudo(["emerge", "-uDN"])
.kws(if kws.is_empty() { &["@world"][..] } else { kws })
.flags(flags)
.pipe(|cmd| self.run_with(cmd, PmMode::default(), &STRAT_INSTALL))
.await
}
async fn suy(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.sy(&[], flags).await?;
self.su(kws, flags).await
}
async fn sy(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
self.run(Cmd::with_sudo(["emerge", "--sync"]).flags(flags))
.await?;
if !kws.is_empty() {
self.s(kws, flags).await?;
}
Ok(())
}
}