mirror of
https://github.com/WarrenHood/MCModpackManager.git
synced 2025-04-30 00:04:59 +01:00
Add support for ignoring transitive dep versions
This commit is contained in:
parent
6a18ac39bb
commit
86fa34d9a2
14
src/main.rs
14
src/main.rs
|
@ -59,6 +59,9 @@ enum Commands {
|
||||||
/// URL to download the mod from
|
/// URL to download the mod from
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
url: Option<String>,
|
url: Option<String>,
|
||||||
|
/// Whether to ignore exact transitive mod versions
|
||||||
|
#[arg(long, short, action)]
|
||||||
|
ignore_transitive_versions: bool,
|
||||||
},
|
},
|
||||||
/// Remove a mod from the modpack
|
/// Remove a mod from the modpack
|
||||||
Remove {
|
Remove {
|
||||||
|
@ -103,7 +106,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
mc_modpack_meta = mc_modpack_meta.provider(provider);
|
mc_modpack_meta = mc_modpack_meta.provider(provider);
|
||||||
}
|
}
|
||||||
mc_modpack_meta.init_project(&dir)?;
|
mc_modpack_meta.init_project(&dir)?;
|
||||||
let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir).await?;
|
let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir, false).await?;
|
||||||
modpack_lock.save_to_dir(&dir)?;
|
modpack_lock.save_to_dir(&dir)?;
|
||||||
}
|
}
|
||||||
Commands::New {
|
Commands::New {
|
||||||
|
@ -126,13 +129,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
mc_modpack_meta.init_project(&dir)?;
|
mc_modpack_meta.init_project(&dir)?;
|
||||||
|
|
||||||
let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir).await?;
|
let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir, false).await?;
|
||||||
modpack_lock.save_to_dir(&dir)?;
|
modpack_lock.save_to_dir(&dir)?;
|
||||||
}
|
}
|
||||||
Commands::Add {
|
Commands::Add {
|
||||||
name,
|
name,
|
||||||
providers,
|
providers,
|
||||||
url,
|
url,
|
||||||
|
ignore_transitive_versions,
|
||||||
} => {
|
} => {
|
||||||
let mut modpack_meta = ModpackMeta::load_from_current_directory()?;
|
let mut modpack_meta = ModpackMeta::load_from_current_directory()?;
|
||||||
let old_modpack_meta = modpack_meta.clone();
|
let old_modpack_meta = modpack_meta.clone();
|
||||||
|
@ -155,10 +159,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
panic!("Reverted modpack meta:\n{}", e);
|
panic!("Reverted modpack meta:\n{}", e);
|
||||||
};
|
};
|
||||||
|
|
||||||
match resolver::PinnedPackMeta::load_from_current_directory().await {
|
match resolver::PinnedPackMeta::load_from_current_directory(ignore_transitive_versions).await {
|
||||||
Ok(mut modpack_lock) => {
|
Ok(mut modpack_lock) => {
|
||||||
let pin_result = modpack_lock
|
let pin_result = modpack_lock
|
||||||
.pin_mod_and_deps(&mod_meta, &modpack_meta)
|
.pin_mod_and_deps(&mod_meta, &modpack_meta, ignore_transitive_versions)
|
||||||
.await;
|
.await;
|
||||||
if let Err(e) = pin_result {
|
if let Err(e) = pin_result {
|
||||||
revert_modpack_meta(e);
|
revert_modpack_meta(e);
|
||||||
|
@ -188,7 +192,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
panic!("Reverted modpack meta:\n{}", e);
|
panic!("Reverted modpack meta:\n{}", e);
|
||||||
};
|
};
|
||||||
|
|
||||||
match resolver::PinnedPackMeta::load_from_current_directory().await {
|
match resolver::PinnedPackMeta::load_from_current_directory(false).await {
|
||||||
Ok(mut modpack_lock) => {
|
Ok(mut modpack_lock) => {
|
||||||
let remove_result = modpack_lock.remove_mod(&name, &modpack_meta);
|
let remove_result = modpack_lock.remove_mod(&name, &modpack_meta);
|
||||||
if let Err(e) = remove_result {
|
if let Err(e) = remove_result {
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct PinnedMod {
|
||||||
/// Source of the files for the mod
|
/// Source of the files for the mod
|
||||||
source: Vec<FileSource>,
|
source: Vec<FileSource>,
|
||||||
/// Version of mod
|
/// Version of mod
|
||||||
pub version: semver::Version,
|
pub version: String,
|
||||||
/// Pinned dependencies of a pinned mod
|
/// Pinned dependencies of a pinned mod
|
||||||
pub deps: Option<HashSet<ModMeta>>
|
pub deps: Option<HashSet<ModMeta>>
|
||||||
}
|
}
|
|
@ -64,16 +64,16 @@ struct VersionFiles {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct ModrinthProjectVersion {
|
struct ModrinthProjectVersion {
|
||||||
author_id: String,
|
// author_id: String,
|
||||||
date_published: String,
|
// date_published: String,
|
||||||
dependencies: Vec<VersionDeps>,
|
dependencies: Option<Vec<VersionDeps>>,
|
||||||
// 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,
|
id: String,
|
||||||
version_number: semver::Version,
|
version_number: String,
|
||||||
// version_type: String,
|
// version_type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,10 +102,12 @@ impl Modrinth {
|
||||||
project_version: Option<&str>,
|
project_version: Option<&str>,
|
||||||
pack_meta: &ModpackMeta,
|
pack_meta: &ModpackMeta,
|
||||||
) -> Result<ModMeta, Box<dyn Error>> {
|
) -> Result<ModMeta, Box<dyn Error>> {
|
||||||
let project_versions = self.get_project_versions(project_id, pack_meta).await?;
|
let project_versions = self
|
||||||
|
.get_project_versions(project_id, pack_meta, true)
|
||||||
|
.await?;
|
||||||
let project_slug = self.get_project_slug(project_id).await?;
|
let project_slug = self.get_project_slug(project_id).await?;
|
||||||
|
|
||||||
for version in project_versions.into_iter() {
|
for version in project_versions.iter() {
|
||||||
if project_version.is_none() || project_version.unwrap_or("*") == version.id {
|
if project_version.is_none() || project_version.unwrap_or("*") == version.id {
|
||||||
return Ok(ModMeta::new(&project_slug)?
|
return Ok(ModMeta::new(&project_slug)?
|
||||||
.provider(ModProvider::Modrinth)
|
.provider(ModProvider::Modrinth)
|
||||||
|
@ -126,20 +128,21 @@ impl Modrinth {
|
||||||
mod_meta: &ModMeta,
|
mod_meta: &ModMeta,
|
||||||
pack_meta: &ModpackMeta,
|
pack_meta: &ModpackMeta,
|
||||||
) -> Result<PinnedMod, Box<dyn Error>> {
|
) -> Result<PinnedMod, Box<dyn Error>> {
|
||||||
let versions = self.get_project_versions(&mod_meta.name, pack_meta).await?;
|
let versions = self
|
||||||
|
.get_project_versions(&mod_meta.name, pack_meta, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let package = if mod_meta.version == "*" {
|
let package = if mod_meta.version == "*" {
|
||||||
versions.last().ok_or(format!(
|
versions.first().ok_or(format!(
|
||||||
"Cannot find package {} for loader={} and mc version={}",
|
"Cannot find package {} for loader={} and mc version={}",
|
||||||
mod_meta.name,
|
mod_meta.name,
|
||||||
pack_meta.modloader.to_string().to_lowercase(),
|
pack_meta.modloader.to_string().to_lowercase(),
|
||||||
pack_meta.mc_version
|
pack_meta.mc_version
|
||||||
))?
|
))?
|
||||||
} else {
|
} else {
|
||||||
let expected_version = semver::Version::parse(&mod_meta.version)?;
|
|
||||||
versions
|
versions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v| v.version_number == expected_version)
|
.filter(|v| v.version_number == mod_meta.version)
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.ok_or(format!(
|
.ok_or(format!(
|
||||||
"Cannot find package {}@{}",
|
"Cannot find package {}@{}",
|
||||||
|
@ -148,15 +151,13 @@ impl Modrinth {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut deps_meta = HashSet::new();
|
let mut deps_meta = HashSet::new();
|
||||||
for dep in package
|
if let Some(deps) = &package.dependencies {
|
||||||
.dependencies
|
for dep in deps.iter().filter(|dep| dep.dependency_type == "required") {
|
||||||
.iter()
|
deps_meta.insert(
|
||||||
.filter(|dep| dep.dependency_type == "required")
|
self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta)
|
||||||
{
|
.await?,
|
||||||
deps_meta.insert(
|
);
|
||||||
self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta)
|
}
|
||||||
.await?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PinnedMod {
|
Ok(PinnedMod {
|
||||||
|
@ -170,7 +171,11 @@ impl Modrinth {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
version: package.version_number.clone(),
|
version: package.version_number.clone(),
|
||||||
deps: if package.dependencies.len() > 0 {
|
deps: if package
|
||||||
|
.dependencies
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|deps| deps.len() > 0)
|
||||||
|
{
|
||||||
Some(deps_meta)
|
Some(deps_meta)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -182,19 +187,26 @@ impl Modrinth {
|
||||||
&self,
|
&self,
|
||||||
mod_id: &str,
|
mod_id: &str,
|
||||||
pack_meta: &ModpackMeta,
|
pack_meta: &ModpackMeta,
|
||||||
|
ignore_game_version_and_loader: bool, // For deps we might as well let them use anything
|
||||||
) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> {
|
) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> {
|
||||||
let mut project_versions: Vec<ModrinthProjectVersion> = self
|
let query_vec = if ignore_game_version_and_loader {
|
||||||
.client
|
&vec![]
|
||||||
.get(format!(
|
} else {
|
||||||
"https://api.modrinth.com/v2/project/{mod_id}/version"
|
&vec![
|
||||||
))
|
|
||||||
.query(&[
|
|
||||||
(
|
(
|
||||||
"loaders",
|
"loaders",
|
||||||
format!("[\"{}\"]", pack_meta.modloader.to_string().to_lowercase()),
|
format!("[\"{}\"]", pack_meta.modloader.to_string().to_lowercase()),
|
||||||
),
|
),
|
||||||
("game_versions", format!("[\"{}\"]", pack_meta.mc_version)),
|
("game_versions", format!("[\"{}\"]", pack_meta.mc_version)),
|
||||||
])
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut project_versions: Vec<ModrinthProjectVersion> = self
|
||||||
|
.client
|
||||||
|
.get(format!(
|
||||||
|
"https://api.modrinth.com/v2/project/{mod_id}/version"
|
||||||
|
))
|
||||||
|
.query(query_vec)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.json()
|
.json()
|
||||||
|
|
|
@ -32,11 +32,10 @@ impl PinnedPackMeta {
|
||||||
&mut self,
|
&mut self,
|
||||||
mod_metadata: &ModMeta,
|
mod_metadata: &ModMeta,
|
||||||
pack_metadata: &ModpackMeta,
|
pack_metadata: &ModpackMeta,
|
||||||
|
ignore_transitive_versions: bool,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
if let Some(mod_meta) = self.mods.get(&mod_metadata.name) {
|
if let Some(mod_meta) = self.mods.get(&mod_metadata.name) {
|
||||||
if mod_metadata.version != "*"
|
if mod_metadata.version != "*" && mod_metadata.version == mod_meta.version {
|
||||||
&& semver::Version::parse(&mod_metadata.version)? == mod_meta.version
|
|
||||||
{
|
|
||||||
// Skip already pinned mods
|
// Skip already pinned mods
|
||||||
// TODO: Replace * with the current mod version in the modpack meta so this doesn't get called twice for the first mod created
|
// TODO: Replace * with the current mod version in the modpack meta so this doesn't get called twice for the first mod created
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -45,6 +44,11 @@ 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());
|
||||||
|
|
||||||
|
if ignore_transitive_versions {
|
||||||
|
// Ignore transitive dep versions
|
||||||
|
deps = deps.iter().map(|d| d.clone().version("*")).collect();
|
||||||
|
}
|
||||||
|
|
||||||
let pinned_version = self
|
let pinned_version = self
|
||||||
.mods
|
.mods
|
||||||
.get(&mod_metadata.name)
|
.get(&mod_metadata.name)
|
||||||
|
@ -183,9 +187,14 @@ impl PinnedPackMeta {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init(&mut self, modpack_meta: &ModpackMeta) -> Result<(), Box<dyn Error>> {
|
pub async fn init(
|
||||||
|
&mut self,
|
||||||
|
modpack_meta: &ModpackMeta,
|
||||||
|
ignore_transitive_versions: bool,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
for mod_meta in modpack_meta.iter_mods() {
|
for mod_meta in modpack_meta.iter_mods() {
|
||||||
self.pin_mod_and_deps(mod_meta, modpack_meta).await?;
|
self.pin_mod_and_deps(mod_meta, modpack_meta, ignore_transitive_versions)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -210,12 +219,18 @@ impl PinnedPackMeta {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_from_directory(directory: &PathBuf) -> Result<Self, Box<dyn Error>> {
|
pub async fn load_from_directory(
|
||||||
|
directory: &PathBuf,
|
||||||
|
ignore_transitive_versions: bool,
|
||||||
|
) -> Result<Self, Box<dyn Error>> {
|
||||||
let modpack_lock_file_path = directory.clone().join(PathBuf::from(MODPACK_LOCK_FILENAME));
|
let modpack_lock_file_path = directory.clone().join(PathBuf::from(MODPACK_LOCK_FILENAME));
|
||||||
if !modpack_lock_file_path.exists() {
|
if !modpack_lock_file_path.exists() {
|
||||||
let mut new_modpack_lock = Self::new();
|
let mut new_modpack_lock = Self::new();
|
||||||
new_modpack_lock
|
new_modpack_lock
|
||||||
.init(&ModpackMeta::load_from_directory(directory)?)
|
.init(
|
||||||
|
&ModpackMeta::load_from_directory(directory)?,
|
||||||
|
ignore_transitive_versions,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(new_modpack_lock);
|
return Ok(new_modpack_lock);
|
||||||
};
|
};
|
||||||
|
@ -223,7 +238,9 @@ impl PinnedPackMeta {
|
||||||
Ok(toml::from_str(&modpack_lock_contents)?)
|
Ok(toml::from_str(&modpack_lock_contents)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn load_from_current_directory() -> Result<Self, Box<dyn Error>> {
|
pub async fn load_from_current_directory(
|
||||||
Self::load_from_directory(&std::env::current_dir()?).await
|
ignore_transitive_versions: bool,
|
||||||
|
) -> Result<Self, Box<dyn Error>> {
|
||||||
|
Self::load_from_directory(&std::env::current_dir()?, ignore_transitive_versions).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue