mirror of
https://github.com/WarrenHood/MCModpackManager.git
synced 2025-04-30 00:04:59 +01:00
Automatically pin transitive deps
This commit is contained in:
parent
844350ab09
commit
72407055ca
|
@ -80,15 +80,15 @@ impl ModpackMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_mod(mut self, mod_meta: &ModMeta) -> Self {
|
pub fn add_mod(mut self, mod_meta: &ModMeta) -> Self {
|
||||||
if let Some(old_mod_meta) = self.mods.get(&mod_meta.name) {
|
// if let Some(old_mod_meta) = self.mods.get(&mod_meta.name) {
|
||||||
println!("Updating {} version constraints: {} -> {}", mod_meta.name, old_mod_meta.version, mod_meta.version);
|
// println!("Updating {} version constraints: {} -> {}", mod_meta.name, old_mod_meta.version, mod_meta.version);
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
println!(
|
// println!(
|
||||||
"Adding {}@{} to modpack '{}'...",
|
// "Adding {}@{} to modpack '{}'...",
|
||||||
mod_meta.name, mod_meta.version, self.pack_name
|
// mod_meta.name, mod_meta.version, self.pack_name
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
self.mods.insert(mod_meta.name.to_string(), mod_meta.clone());
|
self.mods.insert(mod_meta.name.to_string(), mod_meta.clone());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ impl ModpackMeta {
|
||||||
path,
|
path,
|
||||||
toml::to_string(self).expect("MC Modpack Meta should be serializable"),
|
toml::to_string(self).expect("MC Modpack Meta should be serializable"),
|
||||||
)?;
|
)?;
|
||||||
println!("Saved modpack metadata to {}", path.display());
|
// println!("Saved modpack metadata to {}", path.display());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::path::PathBuf;
|
use std::{collections::HashSet, path::PathBuf};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::mod_meta::ModMeta;
|
use crate::mod_meta::ModMeta;
|
||||||
|
|
||||||
|
@ -18,5 +18,5 @@ pub struct PinnedMod {
|
||||||
/// Version of mod
|
/// Version of mod
|
||||||
pub version: semver::Version,
|
pub version: semver::Version,
|
||||||
/// Pinned dependencies of a pinned mod
|
/// Pinned dependencies of a pinned mod
|
||||||
pub deps: Option<Vec<ModMeta>>
|
pub deps: Option<HashSet<ModMeta>>
|
||||||
}
|
}
|
|
@ -1,13 +1,43 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::error::Error;
|
use std::{collections::HashSet, error::Error};
|
||||||
|
|
||||||
use super::PinnedMod;
|
use super::PinnedMod;
|
||||||
use crate::{mod_meta::ModMeta, modpack::ModpackMeta, providers::FileSource};
|
use crate::{
|
||||||
|
mod_meta::{ModMeta, ModProvider},
|
||||||
|
modpack::ModpackMeta,
|
||||||
|
providers::FileSource,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Modrinth {
|
pub struct Modrinth {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct DonationUrls1 {
|
||||||
|
id: String,
|
||||||
|
platform: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct Gallery1 {
|
||||||
|
created: String,
|
||||||
|
description: String,
|
||||||
|
featured: bool,
|
||||||
|
ordering: i64,
|
||||||
|
title: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct License1 {
|
||||||
|
id: String,
|
||||||
|
name: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct ModrinthProject {
|
||||||
|
slug: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct VersionDeps {
|
struct VersionDeps {
|
||||||
dependency_type: String,
|
dependency_type: String,
|
||||||
|
@ -40,8 +70,9 @@ struct ModrinthProjectVersion {
|
||||||
// downloads: i64,
|
// downloads: i64,
|
||||||
files: Vec<VersionFiles>,
|
files: Vec<VersionFiles>,
|
||||||
// loaders: Vec<String>,
|
// loaders: Vec<String>,
|
||||||
// name: String,
|
name: String,
|
||||||
// project_id: String,
|
project_id: String,
|
||||||
|
id: String,
|
||||||
version_number: semver::Version,
|
version_number: semver::Version,
|
||||||
// version_type: String,
|
// version_type: String,
|
||||||
}
|
}
|
||||||
|
@ -53,15 +84,49 @@ impl Modrinth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_project_slug(&self, project_id: &str) -> Result<String, Box<dyn Error>> {
|
||||||
|
let mut project: ModrinthProject = self
|
||||||
|
.client
|
||||||
|
.get(format!("https://api.modrinth.com/v2/project/{project_id}"))
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(project.slug)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_mod_meta(
|
||||||
|
&self,
|
||||||
|
project_id: &str,
|
||||||
|
project_version: Option<&str>,
|
||||||
|
pack_meta: &ModpackMeta,
|
||||||
|
) -> Result<ModMeta, Box<dyn Error>> {
|
||||||
|
let project_versions = self.get_project_versions(project_id, pack_meta).await?;
|
||||||
|
let project_slug = self.get_project_slug(project_id).await?;
|
||||||
|
|
||||||
|
for version in project_versions.into_iter() {
|
||||||
|
if project_version.is_none() || project_version.unwrap_or("*") == version.id {
|
||||||
|
return Ok(ModMeta::new(&project_slug)?
|
||||||
|
.provider(ModProvider::Modrinth)
|
||||||
|
.version(&version.version_number.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(format!(
|
||||||
|
"Couldn't find project '{}' with version '{}'",
|
||||||
|
project_id,
|
||||||
|
project_version.unwrap_or("*")
|
||||||
|
)
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolve a list of mod candidates in order of newest to oldest
|
/// Resolve a list of mod candidates in order of newest to oldest
|
||||||
pub async fn resolve(
|
pub async fn resolve(
|
||||||
&self,
|
&self,
|
||||||
mod_meta: &ModMeta,
|
mod_meta: &ModMeta,
|
||||||
pack_meta: &ModpackMeta,
|
pack_meta: &ModpackMeta,
|
||||||
) -> Result<PinnedMod, Box<dyn Error>> {
|
) -> Result<PinnedMod, Box<dyn Error>> {
|
||||||
let mut versions = self.get_project_versions(&mod_meta.name, pack_meta).await?;
|
let versions = self.get_project_versions(&mod_meta.name, pack_meta).await?;
|
||||||
versions.sort_by_key(|v| v.version_number.clone());
|
|
||||||
versions.reverse();
|
|
||||||
|
|
||||||
let package = if mod_meta.version == "*" {
|
let package = if mod_meta.version == "*" {
|
||||||
versions.last().ok_or(format!(
|
versions.last().ok_or(format!(
|
||||||
|
@ -82,6 +147,18 @@ impl Modrinth {
|
||||||
))?
|
))?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut deps_meta = HashSet::new();
|
||||||
|
for dep in package
|
||||||
|
.dependencies
|
||||||
|
.iter()
|
||||||
|
.filter(|dep| dep.dependency_type == "required")
|
||||||
|
{
|
||||||
|
deps_meta.insert(
|
||||||
|
self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta)
|
||||||
|
.await?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(PinnedMod {
|
Ok(PinnedMod {
|
||||||
source: package
|
source: package
|
||||||
.files
|
.files
|
||||||
|
@ -93,7 +170,11 @@ impl Modrinth {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
version: package.version_number.clone(),
|
version: package.version_number.clone(),
|
||||||
deps: None, // TODO: Get deps
|
deps: if package.dependencies.len() > 0 {
|
||||||
|
Some(deps_meta)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +183,7 @@ impl Modrinth {
|
||||||
mod_id: &str,
|
mod_id: &str,
|
||||||
pack_meta: &ModpackMeta,
|
pack_meta: &ModpackMeta,
|
||||||
) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> {
|
) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> {
|
||||||
let project_Versions: Vec<ModrinthProjectVersion> = self
|
let mut project_versions: Vec<ModrinthProjectVersion> = self
|
||||||
.client
|
.client
|
||||||
.get(format!(
|
.get(format!(
|
||||||
"https://api.modrinth.com/v2/project/{mod_id}/version"
|
"https://api.modrinth.com/v2/project/{mod_id}/version"
|
||||||
|
@ -119,7 +200,10 @@ impl Modrinth {
|
||||||
.json()
|
.json()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(project_Versions)
|
project_versions.sort_by_key(|v| v.version_number.clone());
|
||||||
|
project_versions.reverse();
|
||||||
|
|
||||||
|
Ok(project_versions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,19 @@ impl PinnedPackMeta {
|
||||||
let mut deps =
|
let mut deps =
|
||||||
HashSet::from_iter(self.pin_mod(mod_metadata, pack_metadata).await?.into_iter());
|
HashSet::from_iter(self.pin_mod(mod_metadata, pack_metadata).await?.into_iter());
|
||||||
|
|
||||||
|
let pinned_version = self
|
||||||
|
.mods
|
||||||
|
.get(&mod_metadata.name)
|
||||||
|
.expect("should be in pinned mods")
|
||||||
|
.version
|
||||||
|
.clone();
|
||||||
|
|
||||||
while !deps.is_empty() {
|
while !deps.is_empty() {
|
||||||
let mut next_deps = HashSet::new();
|
let mut next_deps = HashSet::new();
|
||||||
for dep in deps.iter() {
|
for dep in deps.iter() {
|
||||||
println!(
|
println!(
|
||||||
"Adding mod {}@{} (dependency of {}@{})",
|
"Adding mod {}@{} (dependency of {}@{})",
|
||||||
dep.name, dep.version, mod_metadata.name, mod_metadata.version
|
dep.name, dep.version, mod_metadata.name, pinned_version
|
||||||
);
|
);
|
||||||
next_deps.extend(self.pin_mod(dep, &pack_metadata).await?);
|
next_deps.extend(self.pin_mod(dep, &pack_metadata).await?);
|
||||||
}
|
}
|
||||||
|
@ -129,7 +136,7 @@ impl PinnedPackMeta {
|
||||||
path,
|
path,
|
||||||
toml::to_string(self).expect("Pinned pack meta should be serializable"),
|
toml::to_string(self).expect("Pinned pack meta should be serializable"),
|
||||||
)?;
|
)?;
|
||||||
println!("Saved modpack.lock to {}", path.display());
|
// println!("Saved modpack.lock to {}", path.display());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue