1#![doc = doc_self!()]
2
3use std::sync::LazyLock;
4
5use async_trait::async_trait;
6use indoc::indoc;
7use itertools::Itertools;
8
9use super::{NoCacheStrategy, Pm, PmHelper, PromptStrategy, Strategy};
10use crate::{config::Config, error::Result, exec::Cmd};
11
12macro_rules! doc_self {
13 () => {
14 indoc! {"
15 The [Portage Package Manager](https://wiki.gentoo.org/wiki/Portage).
16 "}
17 };
18}
19use doc_self;
20
21#[doc = doc_self!()]
22#[derive(Debug)]
23pub struct Emerge {
24 cfg: Config,
25}
26
27static STRAT_ASK: LazyLock<Strategy> = LazyLock::new(|| Strategy {
28 prompt: PromptStrategy::native_confirm(["--ask"]),
29 ..Strategy::default()
30});
31
32static STRAT_INTERACTIVE: LazyLock<Strategy> = LazyLock::new(|| Strategy {
33 prompt: PromptStrategy::native_confirm(["--interactive"]),
34 ..Strategy::default()
35});
36
37static STRAT_INSTALL: LazyLock<Strategy> = LazyLock::new(|| Strategy {
38 prompt: PromptStrategy::native_confirm(["--ask"]),
39 no_cache: NoCacheStrategy::Scc,
40 ..Strategy::default()
41});
42
43impl Emerge {
44 #[must_use]
45 #[allow(missing_docs)]
46 pub const fn new(cfg: Config) -> Self {
47 Self { cfg }
48 }
49}
50
51#[async_trait]
52impl Pm for Emerge {
53 fn name(&self) -> &'static str {
55 "emerge"
56 }
57
58 fn cfg(&self) -> &Config {
59 &self.cfg
60 }
61
62 async fn q(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
64 self.qs(kws, flags).await
65 }
66
67 async fn qi(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
69 self.si(kws, flags).await
70 }
71
72 async fn ql(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
74 self.run(Cmd::new(["qlist"]).kws(kws).flags(flags)).await
75 }
76
77 async fn qo(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
79 self.run(Cmd::new(["qfile"]).kws(kws).flags(flags)).await
80 }
81
82 async fn qs(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
87 self.run(Cmd::new(["qlist", "-I"]).kws(kws).flags(flags))
88 .await
89 }
90
91 async fn qu(&self, _kws: &[&str], flags: &[&str]) -> Result<()> {
93 self.run(Cmd::new(["emerge", "-uDNp", "@world"]).flags(flags))
94 .await
95 }
96
97 async fn r(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
99 self.run_with(
100 Cmd::with_sudo(["emerge", "--unmerge"])
101 .kws(kws)
102 .flags(flags),
103 self.default_mode(),
104 &STRAT_ASK,
105 )
106 .await
107 }
108
109 async fn rs(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
112 self.run_with(
113 Cmd::with_sudo(["emerge", "--depclean"])
114 .kws(kws)
115 .flags(flags),
116 self.default_mode(),
117 &STRAT_ASK,
118 )
119 .await
120 }
121
122 async fn s(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
124 self.run_with(
125 Cmd::with_sudo(["emerge"]).kws(kws).flags(flags),
126 self.default_mode(),
127 &STRAT_INSTALL,
128 )
129 .await
130 }
131
132 async fn sc(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
135 self.run_with(
136 Cmd::with_sudo(["eclean-dist"]).kws(kws).flags(flags),
137 self.default_mode(),
138 &STRAT_INTERACTIVE,
139 )
140 .await
141 }
142
143 async fn scc(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
145 self.sc(kws, flags).await
146 }
147
148 async fn si(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
150 let kws = kws.iter().map(|kw| format!("^{kw}$")).collect_vec();
151 self.run(Cmd::new(["emerge", "-s"]).kws(kws).flags(flags))
152 .await
153 }
154
155 async fn ss(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
158 self.run(Cmd::new(["qsearch"]).kws(kws).flags(flags)).await
159 }
160
161 async fn su(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
163 self.run_with(
164 Cmd::with_sudo(["emerge", "-uDN"])
165 .kws(if kws.is_empty() { &["@world"][..] } else { kws })
166 .flags(flags),
167 self.default_mode(),
168 &STRAT_INSTALL,
169 )
170 .await
171 }
172
173 async fn suy(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
176 self.sy(&[], flags).await?;
177 self.su(kws, flags).await
178 }
179
180 async fn sy(&self, kws: &[&str], flags: &[&str]) -> Result<()> {
182 self.run(Cmd::with_sudo(["emerge", "--sync"]).flags(flags))
183 .await?;
184 if !kws.is_empty() {
185 self.s(kws, flags).await?;
186 }
187 Ok(())
188 }
189}