Skip to content

Commit c5b49f3

Browse files
Implement adding pinned mods
1 parent 32d4e1c commit c5b49f3

11 files changed

Lines changed: 514 additions & 472 deletions

File tree

libium/src/add.rs

Lines changed: 353 additions & 351 deletions
Large diffs are not rendered by default.

libium/src/config/structs.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,77 @@ const fn is_false(b: &bool) -> bool {
175175
}
176176

177177
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
178-
pub enum ModIdentifier {
178+
pub enum ConfigModIdentifier {
179179
CurseForgeProject(i32),
180180
ModrinthProject(String),
181181
GitHubRepository(String, String),
182182

183183
PinnedCurseForgeProject(i32, i32),
184184
PinnedModrinthProject(String, String),
185-
PinnedGitHubRepository((String, String), i32),
185+
PinnedGitHubRepository((String, String), i64),
186+
}
187+
188+
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
189+
#[serde(from = "ConfigModIdentifier", into = "ConfigModIdentifier")]
190+
pub enum ModIdentifier {
191+
CurseForgeProject(i32, Option<i32>),
192+
ModrinthProject(String, Option<String>),
193+
GitHubRepository((String, String), Option<i64>),
194+
}
195+
196+
impl From<ConfigModIdentifier> for ModIdentifier {
197+
fn from(from: ConfigModIdentifier) -> Self {
198+
match from {
199+
ConfigModIdentifier::CurseForgeProject(p) => ModIdentifier::CurseForgeProject(p, None),
200+
ConfigModIdentifier::ModrinthProject(p) => ModIdentifier::ModrinthProject(p, None),
201+
ConfigModIdentifier::GitHubRepository(o, r) => {
202+
ModIdentifier::GitHubRepository((o, r), None)
203+
}
204+
ConfigModIdentifier::PinnedCurseForgeProject(p, v) => {
205+
ModIdentifier::CurseForgeProject(p, Some(v))
206+
}
207+
ConfigModIdentifier::PinnedModrinthProject(p, v) => {
208+
ModIdentifier::ModrinthProject(p, Some(v))
209+
}
210+
ConfigModIdentifier::PinnedGitHubRepository(p, v) => {
211+
ModIdentifier::GitHubRepository(p, Some(v))
212+
}
213+
}
214+
}
215+
}
216+
217+
impl From<ModIdentifier> for ConfigModIdentifier {
218+
fn from(from: ModIdentifier) -> Self {
219+
match from {
220+
ModIdentifier::CurseForgeProject(p, None) => ConfigModIdentifier::CurseForgeProject(p),
221+
ModIdentifier::ModrinthProject(p, None) => ConfigModIdentifier::ModrinthProject(p),
222+
ModIdentifier::GitHubRepository((o, r), None) => {
223+
ConfigModIdentifier::GitHubRepository(o, r)
224+
}
225+
ModIdentifier::CurseForgeProject(p, Some(v)) => {
226+
ConfigModIdentifier::PinnedCurseForgeProject(p, v)
227+
}
228+
ModIdentifier::ModrinthProject(p, Some(v)) => {
229+
ConfigModIdentifier::PinnedModrinthProject(p, v)
230+
}
231+
ModIdentifier::GitHubRepository(p, Some(v)) => {
232+
ConfigModIdentifier::PinnedGitHubRepository(p, v)
233+
}
234+
}
235+
}
236+
}
237+
238+
impl ModIdentifier {
239+
/// Checks if `self` and `other` refer to the same project,
240+
/// ignoring any differences in pinning.
241+
pub fn is_same_as(&self, other: &Self) -> bool {
242+
match (self, other) {
243+
(Self::CurseForgeProject(l0, _), Self::CurseForgeProject(r0, _)) => l0 == r0,
244+
(Self::ModrinthProject(l0, _), Self::ModrinthProject(r0, _)) => l0 == r0,
245+
(Self::GitHubRepository(l0, _), Self::GitHubRepository(r0, _)) => l0 == r0,
246+
_ => false,
247+
}
248+
}
186249
}
187250

188251
#[derive(Deserialize, Serialize, Debug, Display, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]

libium/src/upgrade/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub fn try_from_cf_file(
9999
.iter()
100100
.filter_map(|d| {
101101
if d.relation_type == CFFileRelationType::RequiredDependency {
102-
Some(ModIdentifier::CurseForgeProject(d.mod_id))
102+
Some(ModIdentifier::CurseForgeProject(d.mod_id, None))
103103
} else {
104104
None
105105
}
@@ -110,7 +110,7 @@ pub fn try_from_cf_file(
110110
.iter()
111111
.filter_map(|d| {
112112
if d.relation_type == CFFileRelationType::Incompatible {
113-
Some(ModIdentifier::CurseForgeProject(d.mod_id))
113+
Some(ModIdentifier::CurseForgeProject(d.mod_id, None))
114114
} else {
115115
None
116116
}
@@ -151,9 +151,11 @@ pub fn from_mr_version(version: MRVersion) -> (Metadata, DownloadData) {
151151
if d.dependency_type == MRDependencyType::Required {
152152
match (d.project_id, d.version_id) {
153153
(Some(proj_id), Some(ver_id)) => {
154-
Some(ModIdentifier::PinnedModrinthProject(proj_id, ver_id))
154+
Some(ModIdentifier::ModrinthProject(proj_id, Some(ver_id)))
155+
}
156+
(Some(proj_id), None) => {
157+
Some(ModIdentifier::ModrinthProject(proj_id, None))
155158
}
156-
(Some(proj_id), None) => Some(ModIdentifier::ModrinthProject(proj_id)),
157159
_ => {
158160
eprintln!("Project ID not available");
159161
None
@@ -171,9 +173,11 @@ pub fn from_mr_version(version: MRVersion) -> (Metadata, DownloadData) {
171173
if d.dependency_type == MRDependencyType::Incompatible {
172174
match (d.project_id, d.version_id) {
173175
(Some(proj_id), Some(ver_id)) => {
174-
Some(ModIdentifier::PinnedModrinthProject(proj_id, ver_id))
176+
Some(ModIdentifier::ModrinthProject(proj_id, Some(ver_id)))
177+
}
178+
(Some(proj_id), None) => {
179+
Some(ModIdentifier::ModrinthProject(proj_id, None))
175180
}
176-
(Some(proj_id), None) => Some(ModIdentifier::ModrinthProject(proj_id)),
177181
_ => {
178182
eprintln!("Project ID not available");
179183
None

libium/src/upgrade/mod_downloadable.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,15 @@ pub enum Error {
2929
type Result<T> = std::result::Result<T, Error>;
3030

3131
impl Mod {
32-
pub async fn fetch_download_file(
33-
&self,
34-
mut profile_filters: Vec<Filter>,
35-
) -> Result<DownloadData> {
32+
pub async fn fetch_download_file(&self, profile_filters: Vec<Filter>) -> Result<DownloadData> {
3633
match &self.identifier {
37-
ModIdentifier::PinnedCurseForgeProject(mod_id, pin) => {
34+
ModIdentifier::CurseForgeProject(mod_id, Some(pin)) => {
3835
Ok(try_from_cf_file(CURSEFORGE_API.get_mod_file(*mod_id, *pin).await?)?.1)
3936
}
40-
ModIdentifier::PinnedModrinthProject(_, pin) => {
37+
ModIdentifier::ModrinthProject(_, Some(pin)) => {
4138
Ok(from_mr_version(MODRINTH_API.version_get(pin).await?).1)
4239
}
43-
ModIdentifier::PinnedGitHubRepository((owner, repo), pin) => Ok(from_gh_asset(
40+
ModIdentifier::GitHubRepository((owner, repo), Some(pin)) => Ok(from_gh_asset(
4441
GITHUB_API
4542
.repos(owner, repo)
4643
.release_assets()
@@ -49,21 +46,21 @@ impl Mod {
4946
)),
5047
id => {
5148
let download_files = match &id {
52-
ModIdentifier::CurseForgeProject(id) => {
49+
ModIdentifier::CurseForgeProject(id, None) => {
5350
let mut files = CURSEFORGE_API.get_mod_files(*id).await?;
5451
files.sort_unstable_by_key(|f| Reverse(f.file_date));
5552
files
5653
.into_iter()
5754
.map(|f| try_from_cf_file(f).map_err(Into::into))
5855
.collect::<Result<Vec<_>>>()?
5956
}
60-
ModIdentifier::ModrinthProject(id) => MODRINTH_API
57+
ModIdentifier::ModrinthProject(id, None) => MODRINTH_API
6158
.version_list(id)
6259
.await?
6360
.into_iter()
6461
.map(from_mr_version)
6562
.collect_vec(),
66-
ModIdentifier::GitHubRepository(owner, repo) => GITHUB_API
63+
ModIdentifier::GitHubRepository((owner, repo), None) => GITHUB_API
6764
.repos(owner, repo)
6865
.releases()
6966
.list()
@@ -78,8 +75,7 @@ impl Mod {
7875
if self.override_filters {
7976
self.filters.clone()
8077
} else {
81-
profile_filters.extend(self.filters.clone());
82-
profile_filters
78+
[profile_filters.clone(), self.filters.clone().clone()].concat()
8379
},
8480
)
8581
.await?;

src/add.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use colored::Colorize as _;
2-
use libium::{add::Error, iter_ext::IterExt as _};
2+
use libium::{add::Error, config::structs::ModIdentifier, iter_ext::IterExt as _};
33
use std::collections::HashMap;
44

5-
pub fn display_successes_failures(successes: &[String], failures: Vec<(String, Error)>) -> bool {
5+
pub fn display_successes_failures(
6+
successes: &[(String, ModIdentifier)],
7+
failures: Vec<(String, Error)>,
8+
) -> bool {
69
if !successes.is_empty() {
710
println!(
811
"{} {}",
912
"Successfully added".green(),
10-
successes.iter().map(|s| s.bold()).display(", ")
13+
successes.iter().map(|(name, _)| name.bold()).display(", ")
1114
);
1215

1316
// No need to print the ID again if there is only one

src/cli.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ pub enum SubCommands {
5656
#[clap(long, short, visible_alias = "override")]
5757
force: bool,
5858

59-
/// Pin a mod to a specific version
60-
#[clap(long, short, visible_alias = "lock")]
61-
pin: Option<String>,
62-
6359
#[command(flatten)]
6460
filters: FilterArguments,
6561
},

src/main.rs

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,17 @@ async fn actual_main(mut cli_app: Ferium) -> Result<()> {
215215
println!("{} {}", "Unknown file:".yellow(), filename.dimmed());
216216
}
217217
(_, Some(mr_id), None) => {
218-
send_ids.push(ModIdentifier::ModrinthProject(mr_id));
218+
send_ids.push(ModIdentifier::ModrinthProject(mr_id, None));
219219
}
220220
(_, None, Some(cf_id)) => {
221-
send_ids.push(ModIdentifier::CurseForgeProject(cf_id));
221+
send_ids.push(ModIdentifier::CurseForgeProject(cf_id, None));
222222
}
223223
(_, Some(mr_id), Some(cf_id)) => match platform {
224224
cli::Platform::Modrinth => {
225-
send_ids.push(ModIdentifier::ModrinthProject(mr_id));
225+
send_ids.push(ModIdentifier::ModrinthProject(mr_id, None));
226226
}
227227
cli::Platform::Curseforge => {
228-
send_ids.push(ModIdentifier::CurseForgeProject(cf_id));
228+
send_ids.push(ModIdentifier::CurseForgeProject(cf_id, None));
229229
}
230230
},
231231
}
@@ -240,50 +240,23 @@ async fn actual_main(mut cli_app: Ferium) -> Result<()> {
240240
SubCommands::Add {
241241
identifiers,
242242
force,
243-
pin,
244243
filters,
245244
} => {
246245
let profile = get_active_profile(&mut config)?;
247246
let override_profile = filters.override_profile;
248247
let filters: Vec<_> = filters.into();
249248

249+
// TODO: conf multiple filters if the user sets the option
250250
ensure!(
251251
// If filters are specified, there should only be one mod
252252
filters.is_empty() || identifiers.len() == 1,
253253
"You can only configure filters when adding a single mod!"
254254
);
255-
ensure!(
256-
// If a pin is specified, there should only be one mod
257-
pin.is_none() || identifiers.len() == 1,
258-
"You can only pin a version when adding a single mod!"
259-
);
260255

261-
let identifiers = if let Some(pin) = pin {
262-
let id = libium::add::parse_id(identifiers[0].clone());
263-
vec![match id {
264-
ModIdentifier::CurseForgeProject(project_id) => {
265-
ModIdentifier::PinnedCurseForgeProject(
266-
project_id,
267-
pin.parse().context("Invalid file ID for CurseForge file")?,
268-
)
269-
}
270-
ModIdentifier::ModrinthProject(project_id) => {
271-
ModIdentifier::PinnedModrinthProject(project_id, pin)
272-
}
273-
ModIdentifier::GitHubRepository(owner, repo) => {
274-
ModIdentifier::PinnedGitHubRepository(
275-
(owner, repo),
276-
pin.parse().context("Invalid asset ID for GitHub")?,
277-
)
278-
}
279-
_ => unreachable!(),
280-
}]
281-
} else {
282-
identifiers
283-
.into_iter()
284-
.map(libium::add::parse_id)
285-
.collect_vec()
286-
};
256+
let identifiers = identifiers
257+
.into_iter()
258+
.map(libium::add::parse_id)
259+
.collect::<libium::add::Result<Vec<_>>>()?;
287260

288261
let (successes, failures) =
289262
libium::add(profile, identifiers, !force, override_profile, filters).await?;
@@ -317,21 +290,28 @@ async fn actual_main(mut cli_app: Ferium) -> Result<()> {
317290
);
318291
for mod_ in &profile.mods {
319292
println!(
320-
"{:20} {}",
293+
"{:20} {}{}",
321294
match &mod_.identifier {
322-
ModIdentifier::CurseForgeProject(id) =>
295+
ModIdentifier::CurseForgeProject(id, _) =>
323296
format!("{} {:8}", "CF".red(), id.to_string().dimmed()),
324-
ModIdentifier::ModrinthProject(id) =>
297+
ModIdentifier::ModrinthProject(id, _) =>
325298
format!("{} {:8}", "MR".green(), id.dimmed()),
326299
ModIdentifier::GitHubRepository(..) => "GH".purple().to_string(),
327-
_ => todo!(),
328300
},
329301
match &mod_.identifier {
330-
ModIdentifier::ModrinthProject(_)
331-
| ModIdentifier::CurseForgeProject(_) => mod_.name.bold().to_string(),
332-
ModIdentifier::GitHubRepository(owner, repo) =>
302+
ModIdentifier::ModrinthProject(..)
303+
| ModIdentifier::CurseForgeProject(..) => mod_.name.bold().to_string(),
304+
ModIdentifier::GitHubRepository((owner, repo), _) =>
333305
format!("{}/{}", owner.dimmed(), repo.bold()),
334-
_ => todo!(),
306+
},
307+
match &mod_.identifier {
308+
ModIdentifier::ModrinthProject(_, Some(pin)) =>
309+
format!("\n 📌 {}", pin.dimmed()),
310+
ModIdentifier::CurseForgeProject(_, Some(pin)) =>
311+
format!("\n 📌 {}", pin.to_string().dimmed()),
312+
ModIdentifier::GitHubRepository(_, Some(pin)) =>
313+
format!("\n 📌 {}", pin.to_string().dimmed()),
314+
_ => String::new(),
335315
},
336316
);
337317
}

0 commit comments

Comments
 (0)