Improved metadata and error handling

This commit is contained in:
Warren Hood 2024-08-14 21:51:42 +02:00
parent 696e52bdef
commit 9d2817f721
4 changed files with 105 additions and 35 deletions

7
Cargo.lock generated
View file

@ -51,12 +51,6 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.15" version = "4.5.15"
@ -141,7 +135,6 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
name = "mcmpmgr" name = "mcmpmgr"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"clap", "clap",
"serde", "serde",
"toml", "toml",

View file

@ -4,7 +4,6 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.15", features = ["derive"] } clap = { version = "4.5.15", features = ["derive"] }
serde = { version = "1.0.207", features = ["derive"] } serde = { version = "1.0.207", features = ["derive"] }
toml = "0.8.19" toml = "0.8.19"

View file

@ -1,7 +1,8 @@
mod modpack; mod modpack;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use std::path::PathBuf; use modpack::{ModLoader, ModMeta, ModProvider, ModpackMeta};
use std::{error::Error, path::PathBuf};
/// A Minecraft Modpack Manager /// A Minecraft Modpack Manager
#[derive(Parser)] #[derive(Parser)]
@ -23,7 +24,7 @@ enum Commands {
}, },
} }
fn main() -> anyhow::Result<()> { fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse(); let cli = Cli::parse();
if let Some(command) = cli.command { if let Some(command) = cli.command {
@ -33,35 +34,22 @@ fn main() -> anyhow::Result<()> {
mc_version, mc_version,
modloader, modloader,
} => { } => {
let dir = if let Some(directory) = directory { let dir = directory.unwrap_or(std::env::current_dir()?);
directory let mc_modpack_meta = ModpackMeta::new(&mc_version, modloader);
} else {
std::env::current_dir()
.expect("You should have permissions to access the current directory")
};
let mc_modpack_meta = modpack::ModpackMeta {
mc_version: mc_version,
modloader: modloader,
mods: vec![],
};
let modpack_meta_file_path = dir.clone().join(PathBuf::from("mcmodpack.toml")); let modpack_meta_file_path = dir.clone().join(PathBuf::from("mcmodpack.toml"));
if modpack_meta_file_path.exists() { if modpack_meta_file_path.exists() {
anyhow::bail!( return Err(format!(
"mcmodpack.toml already exists at {}", "mcmodpack.toml already exists at {}",
modpack_meta_file_path.display() modpack_meta_file_path.display()
); )
.into());
} }
if let Err(e) = std::fs::write( std::fs::write(
modpack_meta_file_path, modpack_meta_file_path,
toml::to_string(&mc_modpack_meta) toml::to_string(&mc_modpack_meta)
.expect("MC Modpack Meta should be serializable"), .expect("MC Modpack Meta should be serializable"),
) { )?;
anyhow::bail!("Unable to initialize new MC modpack project at {}:\n{}", dir.display(), e);
};
println!("MC modpack project initialized at {}", dir.display()); println!("MC modpack project initialized at {}", dir.display());
} }

View file

@ -1,8 +1,72 @@
use std::borrow::BorrowMut;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
pub enum ModProvider {
/// Get mods from CurseForge
CurseForge,
/// Get mods from Modrinth
Modrinth,
/// Get mods from anywhere on the internet. Note: A download url is needed for this
Raw,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct ModMeta { pub struct ModMeta {
download_url: String, mod_name: String,
version: String,
providers: Option<Vec<ModProvider>>,
download_url: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct ModMetaBuilder {
mod_name: String,
version: String,
providers: Option<Vec<ModProvider>>,
download_url: Option<String>,
}
impl ModMeta {
pub fn new(mod_name: &str) -> Self {
Self {
mod_name: mod_name.into(),
..Default::default()
}
}
pub fn provider(mut self, provider: ModProvider) -> Self {
if let Some(providers) = self.providers.borrow_mut() {
if !providers.contains(&provider) {
providers.push(provider)
}
} else {
self.providers = Some(vec![provider]);
}
self
}
pub fn url(mut self, download_url: &str) -> Self {
self.download_url = Some(download_url.into());
self
}
pub fn version(mut self, version_constraint: &str) -> Self {
self.version = version_constraint.into();
self
}
}
impl Default for ModMeta {
fn default() -> Self {
Self {
mod_name: Default::default(),
version: "*".into(),
providers: None,
download_url: Default::default(),
}
}
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -35,9 +99,34 @@ impl std::str::FromStr for ModLoader {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct ModpackMeta { pub struct ModpackMeta {
pub mc_version: String, mc_version: String,
pub modloader: ModLoader, modloader: ModLoader,
pub mods: Vec<ModMeta>, mods: Vec<ModMeta>,
default_providers: Vec<ModProvider>,
}
impl ModpackMeta {
pub fn new(mc_version: &str, modloader: ModLoader) -> Self {
Self {
mc_version: mc_version.into(),
modloader: modloader,
..Default::default()
}
}
pub fn provider(mut self, provider: ModProvider) -> Self {
if !self.default_providers.contains(&provider) {
self.default_providers.push(provider);
}
self
}
pub fn add_mod(mut self, mod_meta: ModMeta) -> Self {
if !self.mods.contains(&mod_meta) {
self.mods.push(mod_meta);
}
self
}
} }
impl std::default::Default for ModpackMeta { impl std::default::Default for ModpackMeta {
@ -46,6 +135,7 @@ impl std::default::Default for ModpackMeta {
mc_version: "1.20.1".into(), mc_version: "1.20.1".into(),
modloader: ModLoader::Forge, modloader: ModLoader::Forge,
mods: Default::default(), mods: Default::default(),
default_providers: vec![ModProvider::Modrinth],
} }
} }
} }