diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-15 00:49:58 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-15 00:49:58 +0300 |
| commit | c91348e68b9e438159ffecc3e26bc6f971e0fa2a (patch) | |
| tree | 30d2abbe5c001d044e66436effa5470783571d77 /src/app/api/plugins | |
| parent | 3015ce0f9d120df7583f838d1a47cb469fe5a727 (diff) | |
fix: require plugin min herdr version
Diffstat (limited to 'src/app/api/plugins')
| -rw-r--r-- | src/app/api/plugins/manifest.rs | 35 | ||||
| -rw-r--r-- | src/app/api/plugins/mod.rs | 74 |
2 files changed, 109 insertions, 0 deletions
diff --git a/src/app/api/plugins/manifest.rs b/src/app/api/plugins/manifest.rs index 92799aae..92ab4754 100644 --- a/src/app/api/plugins/manifest.rs +++ b/src/app/api/plugins/manifest.rs @@ -13,6 +13,8 @@ struct RawPluginManifest { name: String, version: String, #[serde(default)] + min_herdr_version: Option<String>, + #[serde(default)] description: Option<String>, #[serde(default)] platforms: Option<Vec<RawPlatform>>, @@ -133,6 +135,7 @@ pub(crate) fn load_plugin_manifest( "invalid_plugin_version", "plugin version is required", )?; + let min_herdr_version = validate_min_herdr_version(raw.min_herdr_version.as_deref())?; let description = raw .description .map(|description| description.trim().to_string()) @@ -180,6 +183,7 @@ pub(crate) fn load_plugin_manifest( plugin_id, name, version, + min_herdr_version, description, manifest_path: manifest_path.display().to_string(), plugin_root: plugin_root.display().to_string(), @@ -195,6 +199,37 @@ pub(crate) fn load_plugin_manifest( }) } +fn validate_min_herdr_version(value: Option<&str>) -> Result<String, (&'static str, String)> { + let Some(value) = value else { + return Err(( + "invalid_plugin_min_herdr_version", + "plugin min_herdr_version is required".to_string(), + )); + }; + let value = non_empty_trimmed( + value, + "invalid_plugin_min_herdr_version", + "plugin min_herdr_version is required", + )?; + let required = crate::update::Version::parse(&value).ok_or_else(|| { + ( + "invalid_plugin_min_herdr_version", + format!( + "plugin min_herdr_version must be a semantic version like {}", + crate::build_info::BASE_VERSION + ), + ) + })?; + let current = crate::update::Version::current(); + if required > current { + return Err(( + "plugin_requires_newer_herdr", + format!("plugin requires Herdr {required} or newer; current Herdr is {current}"), + )); + } + Ok(required.to_string()) +} + fn normalize_manifest_build( build: RawPluginManifestBuild, ) -> Result<PluginManifestBuild, (&'static str, String)> { diff --git a/src/app/api/plugins/mod.rs b/src/app/api/plugins/mod.rs index 89f7a23d..1938589c 100644 --- a/src/app/api/plugins/mod.rs +++ b/src/app/api/plugins/mod.rs @@ -704,6 +704,7 @@ mod tests { id = "example.worktree-bootstrap" name = "Worktree Bootstrap" version = "0.1.0" +min_herdr_version = "0.6.10" description = "Prepare new worktrees" platforms = ["linux", "macos", "windows"] @@ -772,6 +773,7 @@ action = "bootstrap" id = "example.config-dirs" name = "Config Dirs" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] "#, ); @@ -806,6 +808,7 @@ platforms = ["linux", "macos", "windows"] id = "example.legacy-config" name = "Legacy Config" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] "#, ); @@ -925,6 +928,56 @@ platforms = ["linux", "macos", "windows"] } #[test] + fn link_rejects_invalid_min_herdr_versions() { + let cases = [ + ( + "plugin-missing-min-herdr", + r#" +id = "example.missing-min-herdr" +name = "Missing Min Herdr" +version = "0.1.0" +platforms = ["linux", "macos", "windows"] +"#, + "invalid_plugin_min_herdr_version", + ), + ( + "plugin-invalid-min-herdr", + r#" +id = "example.invalid-min-herdr" +name = "Invalid Min Herdr" +version = "0.1.0" +min_herdr_version = "soon" +platforms = ["linux", "macos", "windows"] +"#, + "invalid_plugin_min_herdr_version", + ), + ( + "plugin-future-min-herdr", + r#" +id = "example.future-min-herdr" +name = "Future Min Herdr" +version = "0.1.0" +min_herdr_version = "999.0.0" +platforms = ["linux", "macos", "windows"] +"#, + "plugin_requires_newer_herdr", + ), + ]; + + for (name, manifest, expected_code) in cases { + let root = unique_temp_path(name); + write_manifest_content(&root, manifest); + + let result = load_plugin_manifest(&root.display().to_string(), true); + assert!( + matches!(result, Err((code, _)) if code == expected_code), + "{name}: expected {expected_code}, got {result:?}" + ); + let _ = std::fs::remove_dir_all(root); + } + } + + #[test] fn link_rejects_duplicate_action_ids() { let root = unique_temp_path("plugin-duplicate-action"); write_manifest_content( @@ -933,6 +986,7 @@ platforms = ["linux", "macos", "windows"] id = "example.duplicate" name = "Duplicate" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -961,6 +1015,7 @@ command = ["echo", "b"] id = "example.dotted-action" name = "Dotted Action" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -984,6 +1039,7 @@ command = ["echo", "build"] id = "example.duplicate-pane" name = "Duplicate Pane" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[panes]] @@ -1099,6 +1155,7 @@ command = ["echo", "b"] id = "example.pane" name = "Pane Plugin" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[panes]] @@ -1205,6 +1262,7 @@ command = ["sh", "-c", "printf '%s\n%s\n%s\n%s\n%s\n%s\n%s\n' \"$PWD\" \"$HERDR_ id = "example.path-env" name = "Path Env" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[panes]] @@ -1310,6 +1368,7 @@ command = ["sh", "-c", "printf '%s\n%s\n%s\n' \"$HERDR_PLUGIN_ROOT\" \"$HERDR_PL id = "example.tab" name = "Tab Plugin" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[panes]] @@ -1514,6 +1573,7 @@ command = ["sh", "-c", "sleep 1"] id = "example.runner" name = "Runner" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[actions]] @@ -1580,6 +1640,7 @@ command = ["sh", "-c", "printf '%s' \"$HERDR_PLUGIN_ACTION_ID\""] id = "example.action-paths" name = "Action Paths" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[actions]] @@ -1702,6 +1763,7 @@ command = ["sh", "-c", "printf '%s\n%s\n%s' \"$HERDR_PLUGIN_ROOT\" \"$HERDR_PLUG id = "example.event-context" name = "Event Context" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[events]] @@ -1851,6 +1913,7 @@ command = ["sh", "-c", "printf '%s' \"$HERDR_PLUGIN_CONTEXT_JSON\" > {}"] id = "example.links" name = "Links" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[actions]] @@ -1918,6 +1981,7 @@ action = "open" id = "example.link-order" name = "Link Order" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -1964,6 +2028,7 @@ action = "generic" id = "example.bad-links" name = "Bad Links" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -2006,6 +2071,7 @@ action = "open" id = "example.bad-link-action" name = "Bad Link Action" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -2079,6 +2145,7 @@ action = "missing" id = "example.context" name = "Context" version = "0.1.0" +min_herdr_version = "0.6.10" [[actions]] id = "show" @@ -2175,6 +2242,7 @@ command = ["show-ctx"] id = "example.bad-event" name = "Bad Event Plugin" version = "0.1.0" +min_herdr_version = "0.6.10" [[events]] on = "worktree.craeted" @@ -2458,6 +2526,7 @@ command = ["sh", "-c", "echo ok"] id = "example.platforms" name = "Platforms" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[actions]] @@ -2540,6 +2609,7 @@ command = ["run.bat"] id = "example.reject" name = "Reject" version = "0.1.0" +min_herdr_version = "0.6.10" {excluded_platforms} [[actions]] @@ -2604,6 +2674,7 @@ command = ["act"] id = "example.override" name = "Override" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos", "windows"] [[actions]] @@ -2654,6 +2725,7 @@ command = ["act"] id = "example.nodecl" name = "No Decl" version = "0.1.0" +min_herdr_version = "0.6.10" [[actions]] id = "act" @@ -2711,6 +2783,7 @@ command = ["act"] id = "example.badplatform" name = "Bad Platform" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "beos"] [[actions]] @@ -2742,6 +2815,7 @@ command = ["act"] id = "example.platform-rt" name = "Platform RT" version = "0.1.0" +min_herdr_version = "0.6.10" platforms = ["linux", "macos"] [[actions]] |
