From 608fd4dd8e2227fcf5b2a649fef4e96f0141366e Mon Sep 17 00:00:00 2001 From: Damian Bednarczyk Date: Sun, 25 Feb 2024 21:05:11 -0600 Subject: [PATCH] add primitive version check for upgrading --- README.md | 7 ----- assets/Makefile | 3 ++ assets/pap.tape | 22 ++++++++++---- src/project/actions.rs | 67 ++++++++++++++++++++++++++++++++---------- src/project/mod.rs | 2 +- 5 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 assets/Makefile diff --git a/README.md b/README.md index 6e0c8dc..f58b879 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,6 @@ This is a spiritual successor to the original, now abandoned (?) [pap](https://g The current MSRV is the latest nightly toolchain. -## Why `pap`? - -Instead of browsing for server modpacks, or even downloading mods and server jarfiles them one-by-one, -`pap` can set up a server from scratch in just a few commands. Here's a video example: - -https://github.com/dxbednarczyk/pap-ng/assets/54457902/1a0c8266-cbf8-48b1-bec8-aa04f1f0eb5d - ## Goals - [x] Easily set up a new Minecraft server from scratch, including mod and plugin support - [x] Produce easily reproducible, portable server configuration diff --git a/assets/Makefile b/assets/Makefile new file mode 100644 index 0000000..d4bd970 --- /dev/null +++ b/assets/Makefile @@ -0,0 +1,3 @@ +build: + rm -rf my-server + vhs pap.tape \ No newline at end of file diff --git a/assets/pap.tape b/assets/pap.tape index 86818e6..a5adf4a 100644 --- a/assets/pap.tape +++ b/assets/pap.tape @@ -60,7 +60,7 @@ Output pap.mp4 Require pap Set Shell "bash" -Set FontSize 24 +Set FontSize 18 Set Width 1200 Set Height 600 @@ -78,7 +78,7 @@ Sleep 1s Type "pap server init --minecraft-version 1.20.4 --loader fabric" Enter -Sleep 3s +Sleep 5s Type "# Then, add the plugins / mods you want:" Enter @@ -106,11 +106,11 @@ Sleep 5s Ctrl+C Ctrl+L -Type "# If you already have a server and want to host it on a different machine, pap can do that too!" +Type "# If you already have a server and want to move it to a different machine, pap can do that!" Enter Sleep 1s -Type "# Let's just use the server we just set up as an example:" +Type "# Let's use the server we just set up as an example:" Enter Sleep 1s @@ -122,7 +122,19 @@ Type "cp ../pap.lock ." Enter Sleep 1s -Type "pap server install" +Type "# To see what pap is doing under the hood, use the --verbose flag" +Enter +Sleep 1s + +Type "pap --verbose server install" +Enter +Sleep 5s + +Type "# pap can also update existing dependencies. +Enter +Sleep 1s + +Type "pap project update" Enter Sleep 5s diff --git a/src/project/actions.rs b/src/project/actions.rs index 2f84d00..221e01a 100644 --- a/src/project/actions.rs +++ b/src/project/actions.rs @@ -3,7 +3,7 @@ use std::{cmp::Ordering, fs, path::PathBuf}; use anyhow::anyhow; -use log::info; +use log::{error, info, warn}; use pap::{download_with_checksum, FAKE_USER_AGENT}; use serde::Deserialize; use sha2::Sha512; @@ -171,30 +171,69 @@ pub fn remove(lockfile: &mut Lockfile, id: &str, keep_jarfile: bool) -> Result<( Ok(()) } -pub fn update(lockfile: &mut Lockfile) -> Result<(), anyhow::Error> { +pub fn update(lockfile: &mut Lockfile) { for dep in &mut lockfile.project { - let latest = get_latest_version( + let Ok(latest) = get_latest_version( &dep.slug, &lockfile.loader.minecraft_version, &lockfile.loader.name, - )?; + ) else { + error!("failed to get latest version of {}", dep.slug); + return; + }; - let latest_parsed = Versioning::new(&latest.number).unwrap(); - let current_parsed = Versioning::new(&dep.version_number).unwrap(); + let latest_version = Versioning::new(&latest.number).unwrap(); + let current_version = Versioning::new(&dep.version_number).unwrap(); - match current_parsed.cmp(&latest_parsed) { + match current_version.cmp(&latest_version) { Ordering::Equal => continue, Ordering::Greater => { - return Err(anyhow!( - "version mismatch: current version is higher than latest modrinth version" - )) + warn!("version mismatch: current version is higher than latest modrinth version"); + return; } Ordering::Less => (), } - let (project_file, path) = save(&lockfile.loader.project_path(), &latest)?; + let semver_error = format!( + "cannot compare versions for {}: versioning scheme is not semver", + dep.slug + ); - fs::remove_file(dep.path.clone())?; + let incompatible_error = |current: u32, latest: u32, version_type: &str| { + format!( + "potentially incompatible upgrade for {}: {version_type} version {current} to {latest}, not updating", dep.slug + ) + }; + + if let Versioning::Ideal(current) = current_version { + let Versioning::Ideal(latest) = latest_version else { + error!("{semver_error}"); + return; + }; + + if latest.major > current.major { + warn!( + "{}", + incompatible_error(current.major, latest.major, "major") + ); + return; + } + + if latest.minor > current.minor && current.major == 0 { + warn!( + "{}", + incompatible_error(current.minor, latest.minor, "minor with major version 0",) + ); + return; + } + } else { + error!("{}", semver_error); + return; + }; + + let (project_file, path) = save(&lockfile.loader.project_path(), &latest).unwrap(); + + fs::remove_file(dep.path.clone()).unwrap(); dep.installed_version = latest.id; dep.version_number = latest.number; @@ -203,9 +242,7 @@ pub fn update(lockfile: &mut Lockfile) -> Result<(), anyhow::Error> { dep.sha512 = project_file.hashes.sha512; } - lockfile.save()?; - - Ok(()) + lockfile.save().unwrap(); } fn save(project_path: &str, version: &Version) -> Result<(ProjectFile, PathBuf), anyhow::Error> { diff --git a/src/project/mod.rs b/src/project/mod.rs index 5deb592..bfb8deb 100644 --- a/src/project/mod.rs +++ b/src/project/mod.rs @@ -54,7 +54,7 @@ pub fn action(project: &Project) -> Result<(), anyhow::Error> { no_deps, } => actions::add(&mut lf, id, version_id.as_ref(), *optional_deps, *no_deps)?, Project::Remove { id, keep_jarfile } => actions::remove(&mut lf, id, *keep_jarfile)?, - Project::Update => actions::update(&mut lf)?, + Project::Update => actions::update(&mut lf), } Ok(())