mirror of
https://github.com/WarrenHood/MCModpackManager.git
synced 2025-04-29 19:04:57 +01:00
Add ability to download a modpack from git or from any local path
This commit is contained in:
parent
08eff7ea2a
commit
753c9d6417
68
Cargo.lock
generated
68
Cargo.lock
generated
|
@ -138,6 +138,8 @@ version = "1.1.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
|
@ -365,6 +367,21 @@ version = "0.29.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
|
||||
[[package]]
|
||||
name = "git2"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"libgit2-sys",
|
||||
"log",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.5"
|
||||
|
@ -553,6 +570,15 @@ version = "1.0.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.70"
|
||||
|
@ -574,6 +600,46 @@ version = "0.2.156"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.17.0+1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libssh2-sys",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libssh2-sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
|
@ -601,11 +667,13 @@ name = "mcmpmgr"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"git2",
|
||||
"lhash",
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"sha2",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"toml",
|
||||
]
|
||||
|
|
|
@ -5,10 +5,12 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.15", features = ["derive"] }
|
||||
git2 = "0.19.0"
|
||||
lhash = { version = "1.1.0", features = ["sha1", "sha512"] }
|
||||
reqwest = { version = "0.12.5", features = ["json"] }
|
||||
semver = { version = "1.0.23", features = ["serde"] }
|
||||
serde = { version = "1.0.207", features = ["derive"] }
|
||||
sha2 = "0.10.8"
|
||||
tempfile = "3.12.0"
|
||||
tokio = { version = "1.39.2", features = ["full"] }
|
||||
toml = "0.8.19"
|
||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -90,6 +90,12 @@ enum Commands {
|
|||
/// Side to download for
|
||||
#[arg(long, short, default_value_t = DownloadSide::Both)]
|
||||
side: DownloadSide,
|
||||
/// Download mods from a remote modpack in a git repo
|
||||
#[arg(long)]
|
||||
git: Option<String>,
|
||||
/// Download mods from a local modpack
|
||||
#[arg(long)]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
/// Update all mods to the latest possible version
|
||||
Update {
|
||||
|
@ -288,8 +294,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
};
|
||||
}
|
||||
Commands::Download { mods_dir, side } => {
|
||||
let pack_lock = resolver::PinnedPackMeta::load_from_current_directory(true).await?;
|
||||
Commands::Download {
|
||||
mods_dir,
|
||||
side,
|
||||
git,
|
||||
path,
|
||||
} => {
|
||||
let pack_lock = if let Some(git_url) = git {
|
||||
resolver::PinnedPackMeta::load_from_git_repo(&git_url, true).await?
|
||||
} else if let Some(local_path) = path {
|
||||
resolver::PinnedPackMeta::load_from_directory(&local_path, true).await?
|
||||
} else {
|
||||
resolver::PinnedPackMeta::load_from_current_directory(true).await?
|
||||
};
|
||||
|
||||
pack_lock.download_mods(&mods_dir, side).await?;
|
||||
println!("Mods updated");
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
error::Error,
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
const MODPACK_FILENAME: &str = "modpack.toml";
|
||||
|
@ -38,7 +38,7 @@ impl std::str::FromStr for ModLoader {
|
|||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ModpackMeta {
|
||||
pack_name: String,
|
||||
pub pack_name: String,
|
||||
pub mc_version: String,
|
||||
pub modloader: ModLoader,
|
||||
pub mods: HashMap<String, ModMeta>,
|
||||
|
@ -60,8 +60,8 @@ impl ModpackMeta {
|
|||
self.mods.values().into_iter()
|
||||
}
|
||||
|
||||
pub fn load_from_directory(directory: &PathBuf) -> Result<Self, Box<dyn Error>> {
|
||||
let modpack_meta_file_path = directory.clone().join(PathBuf::from(MODPACK_FILENAME));
|
||||
pub fn load_from_directory(directory: &Path) -> Result<Self, Box<dyn Error>> {
|
||||
let modpack_meta_file_path = directory.join(PathBuf::from(MODPACK_FILENAME));
|
||||
if !modpack_meta_file_path.exists() {
|
||||
return Err(format!(
|
||||
"Directory '{}' does not seem to be a valid modpack project directory.",
|
||||
|
@ -104,8 +104,8 @@ impl ModpackMeta {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn init_project(&self, directory: &PathBuf) -> Result<(), Box<dyn Error>> {
|
||||
let modpack_meta_file_path = directory.clone().join(PathBuf::from(MODPACK_FILENAME));
|
||||
pub fn init_project(&self, directory: &Path) -> Result<(), Box<dyn Error>> {
|
||||
let modpack_meta_file_path = directory.join(PathBuf::from(MODPACK_FILENAME));
|
||||
if modpack_meta_file_path.exists() {
|
||||
return Err(format!(
|
||||
"{MODPACK_FILENAME} already exists at {}",
|
||||
|
|
|
@ -65,7 +65,7 @@ impl Modrinth {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn get_project(&self, project_id: &str) -> Result<ModrinthProject, Box<dyn Error>> {
|
||||
async fn get_project(&self, project_id: &str) -> Result<ModrinthProject, Box<dyn Error>> {
|
||||
let project: ModrinthProject = self
|
||||
.client
|
||||
.get(format!("https://api.modrinth.com/v2/project/{project_id}"))
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
|||
collections::{HashMap, HashSet},
|
||||
error::Error,
|
||||
ffi::{OsStr, OsString},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -61,7 +61,7 @@ impl PinnedPackMeta {
|
|||
match filesource {
|
||||
crate::providers::FileSource::Download {
|
||||
url,
|
||||
sha1,
|
||||
sha1: _,
|
||||
sha512,
|
||||
filename,
|
||||
} => {
|
||||
|
@ -90,10 +90,10 @@ impl PinnedPackMeta {
|
|||
tokio::fs::write(mods_dir.join(filename), file_contents).await?;
|
||||
}
|
||||
crate::providers::FileSource::Local {
|
||||
path,
|
||||
sha1,
|
||||
sha512,
|
||||
filename,
|
||||
path: _,
|
||||
sha1: _,
|
||||
sha512: _,
|
||||
filename: _,
|
||||
} => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,12 @@ impl PinnedPackMeta {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn file_is_pinned(&self, file_name: &OsStr, mod_side: DownloadSide, cache: &mut HashSet<OsString>) -> bool {
|
||||
pub fn file_is_pinned(
|
||||
&self,
|
||||
file_name: &OsStr,
|
||||
mod_side: DownloadSide,
|
||||
cache: &mut HashSet<OsString>,
|
||||
) -> bool {
|
||||
if cache.contains(file_name) {
|
||||
return true;
|
||||
}
|
||||
|
@ -114,9 +119,9 @@ impl PinnedPackMeta {
|
|||
for filesource in pinned_mod.source.iter() {
|
||||
match filesource {
|
||||
crate::providers::FileSource::Download {
|
||||
url,
|
||||
sha1,
|
||||
sha512,
|
||||
url: _,
|
||||
sha1: _,
|
||||
sha512: _,
|
||||
filename,
|
||||
} => {
|
||||
let pinned_filename = OsStr::new(filename);
|
||||
|
@ -126,9 +131,9 @@ impl PinnedPackMeta {
|
|||
}
|
||||
}
|
||||
crate::providers::FileSource::Local {
|
||||
path,
|
||||
sha1,
|
||||
sha512,
|
||||
path: _,
|
||||
sha1: _,
|
||||
sha512: _,
|
||||
filename,
|
||||
} => {
|
||||
let pinned_filename = OsStr::new(filename);
|
||||
|
@ -353,10 +358,10 @@ impl PinnedPackMeta {
|
|||
}
|
||||
|
||||
pub async fn load_from_directory(
|
||||
directory: &PathBuf,
|
||||
directory: &Path,
|
||||
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.join(PathBuf::from(MODPACK_LOCK_FILENAME));
|
||||
if !modpack_lock_file_path.exists() {
|
||||
let mut new_modpack_lock = Self::new();
|
||||
new_modpack_lock
|
||||
|
@ -376,4 +381,34 @@ impl PinnedPackMeta {
|
|||
) -> Result<Self, Box<dyn Error>> {
|
||||
Self::load_from_directory(&std::env::current_dir()?, ignore_transitive_versions).await
|
||||
}
|
||||
|
||||
pub async fn load_from_git_repo(
|
||||
git_url: &str,
|
||||
ignore_transitive_versions: bool,
|
||||
) -> Result<Self, Box<dyn Error>> {
|
||||
// TODO: Refactor the way this works since temp dirs will be deleted before we get to access local mods
|
||||
// That is a problem for the future
|
||||
|
||||
let pack_dir = tempfile::tempdir()?;
|
||||
println!(
|
||||
"Cloning modpack from git repo {} to {:#?}...",
|
||||
git_url,
|
||||
pack_dir.path()
|
||||
);
|
||||
let _repo = git2::Repository::clone(git_url, pack_dir.path())?;
|
||||
|
||||
let modpack_meta = ModpackMeta::load_from_directory(pack_dir.path())?;
|
||||
let pinned_pack_meta =
|
||||
PinnedPackMeta::load_from_directory(pack_dir.path(), ignore_transitive_versions)
|
||||
.await?;
|
||||
|
||||
println!(
|
||||
"Loaded modpack '{}' (MC {} - {}) from git",
|
||||
modpack_meta.pack_name,
|
||||
modpack_meta.mc_version,
|
||||
modpack_meta.modloader.to_string()
|
||||
);
|
||||
|
||||
Ok(pinned_pack_meta)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue