From 1858f767669d5722a41ef1a592cd219364cc1259 Mon Sep 17 00:00:00 2001 From: pleb Date: Sun, 5 Jul 2026 14:24:58 -0700 Subject: [PATCH] Refactor plugin registry into separate files per plugin --- docs/DESIGN.md | 16 +- registry/README.md | 18 + registry/plugins.toml | 965 ------------------ registry/plugins/accsaber-reloaded.toml | 6 + registry/plugins/adblocker.toml | 9 + registry/plugins/assetbundleloadingtools.toml | 13 + registry/plugins/beatleader.toml | 14 + registry/plugins/beatsabermarkuplanguage.toml | 9 + registry/plugins/beatsaberplaylistslib.toml | 12 + registry/plugins/beatsaberplus.toml | 9 + registry/plugins/beatsaverdownloader.toml | 15 + registry/plugins/beatsaversharp.toml | 6 + registry/plugins/beatsaverupdater.toml | 13 + registry/plugins/beatsavervoting.toml | 12 + registry/plugins/bettersonglist.toml | 6 + registry/plugins/bs-utils.toml | 10 + registry/plugins/bsipa.toml | 6 + registry/plugins/camerautils.toml | 9 + registry/plugins/chroma.toml | 11 + registry/plugins/customjsondata.toml | 9 + registry/plugins/ditails.toml | 13 + registry/plugins/easyoffset.toml | 6 + registry/plugins/failbutton.toml | 6 + registry/plugins/gottagofast.toml | 6 + registry/plugins/heck.toml | 10 + registry/plugins/hidethelogo.toml | 6 + registry/plugins/highlightbombs.toml | 10 + registry/plugins/hitscorevisualizer.toml | 10 + registry/plugins/hitsoundtweaks.toml | 6 + registry/plugins/imagesharp.toml | 6 + registry/plugins/iniparser.toml | 6 + registry/plugins/introskip.toml | 11 + registry/plugins/jdfixer.toml | 11 + registry/plugins/keepmyoverridespls.toml | 6 + registry/plugins/keyremapper.toml | 11 + registry/plugins/leaderboardcore.toml | 11 + registry/plugins/lookupid.toml | 6 + registry/plugins/naluluna.toml | 9 + registry/plugins/noodleextensions.toml | 10 + registry/plugins/pitchblack.toml | 10 + registry/plugins/playlistmanager.toml | 16 + registry/plugins/protobuf-net.toml | 6 + registry/plugins/reecamera.toml | 10 + registry/plugins/scoresaber.toml | 12 + registry/plugins/scoresabersharp.toml | 5 + registry/plugins/setlist.toml | 10 + registry/plugins/sirautil.toml | 9 + registry/plugins/songchartvisualizer.toml | 11 + registry/plugins/songcore.toml | 11 + registry/plugins/songdetailscache.toml | 9 + registry/plugins/songrankedbadge.toml | 12 + registry/plugins/soundreplacer.toml | 11 + registry/plugins/squattobegin.toml | 9 + .../system-io-compression-filesystem.toml | 8 + registry/plugins/system-io-compression.toml | 5 + registry/plugins/vivify.toml | 12 + src/plugin_helper/cli.py | 12 +- src/plugin_helper/models.py | 62 +- src/plugin_helper/operations.py | 4 +- src/plugin_helper/planner.py | 26 +- src/plugin_helper/tui.py | 2 +- tests/test_plugin_helper.py | 138 ++- 62 files changed, 730 insertions(+), 1008 deletions(-) create mode 100644 registry/README.md delete mode 100644 registry/plugins.toml create mode 100644 registry/plugins/accsaber-reloaded.toml create mode 100644 registry/plugins/adblocker.toml create mode 100644 registry/plugins/assetbundleloadingtools.toml create mode 100644 registry/plugins/beatleader.toml create mode 100644 registry/plugins/beatsabermarkuplanguage.toml create mode 100644 registry/plugins/beatsaberplaylistslib.toml create mode 100644 registry/plugins/beatsaberplus.toml create mode 100644 registry/plugins/beatsaverdownloader.toml create mode 100644 registry/plugins/beatsaversharp.toml create mode 100644 registry/plugins/beatsaverupdater.toml create mode 100644 registry/plugins/beatsavervoting.toml create mode 100644 registry/plugins/bettersonglist.toml create mode 100644 registry/plugins/bs-utils.toml create mode 100644 registry/plugins/bsipa.toml create mode 100644 registry/plugins/camerautils.toml create mode 100644 registry/plugins/chroma.toml create mode 100644 registry/plugins/customjsondata.toml create mode 100644 registry/plugins/ditails.toml create mode 100644 registry/plugins/easyoffset.toml create mode 100644 registry/plugins/failbutton.toml create mode 100644 registry/plugins/gottagofast.toml create mode 100644 registry/plugins/heck.toml create mode 100644 registry/plugins/hidethelogo.toml create mode 100644 registry/plugins/highlightbombs.toml create mode 100644 registry/plugins/hitscorevisualizer.toml create mode 100644 registry/plugins/hitsoundtweaks.toml create mode 100644 registry/plugins/imagesharp.toml create mode 100644 registry/plugins/iniparser.toml create mode 100644 registry/plugins/introskip.toml create mode 100644 registry/plugins/jdfixer.toml create mode 100644 registry/plugins/keepmyoverridespls.toml create mode 100644 registry/plugins/keyremapper.toml create mode 100644 registry/plugins/leaderboardcore.toml create mode 100644 registry/plugins/lookupid.toml create mode 100644 registry/plugins/naluluna.toml create mode 100644 registry/plugins/noodleextensions.toml create mode 100644 registry/plugins/pitchblack.toml create mode 100644 registry/plugins/playlistmanager.toml create mode 100644 registry/plugins/protobuf-net.toml create mode 100644 registry/plugins/reecamera.toml create mode 100644 registry/plugins/scoresaber.toml create mode 100644 registry/plugins/scoresabersharp.toml create mode 100644 registry/plugins/setlist.toml create mode 100644 registry/plugins/sirautil.toml create mode 100644 registry/plugins/songchartvisualizer.toml create mode 100644 registry/plugins/songcore.toml create mode 100644 registry/plugins/songdetailscache.toml create mode 100644 registry/plugins/songrankedbadge.toml create mode 100644 registry/plugins/soundreplacer.toml create mode 100644 registry/plugins/squattobegin.toml create mode 100644 registry/plugins/system-io-compression-filesystem.toml create mode 100644 registry/plugins/system-io-compression.toml create mode 100644 registry/plugins/vivify.toml diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 7adc42b..690f137 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -59,7 +59,9 @@ plugin-helper/ DESIGN.md README.md registry/ - plugins.toml + plugins/ + songcore.toml + bsipa.toml locks/ 1.40.8.lock.toml src/plugin_helper/ @@ -124,21 +126,15 @@ Artifact source preference: Example: ```toml -[[plugins]] id = "songcore" name = "SongCore" repo = "Kylemc1413/SongCore" asset_patterns = ["*SongCore*.zip"] install_strategy = "bsipa-zip" category = "library" - -[plugins.compatibility] -source = "metadata-or-release-notes" - -[[plugins.dependencies]] -id = "bs-utils" -constraint = ">=1.0" -required = true +dependencies = [ + { id = "bs-utils", constraint = ">=1.0" }, +] ``` Important fields: diff --git a/registry/README.md b/registry/README.md new file mode 100644 index 0000000..2d2afed --- /dev/null +++ b/registry/README.md @@ -0,0 +1,18 @@ +# Plugin Registry + +Each plugin lives in its own TOML file under `plugins/`. + +```toml +id = "example" +name = "Example" +repo = "owner/example" +asset_patterns = ["Example-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] +``` + +Dependencies are inline arrays on the plugin that owns them, so there is no +implicit relationship with a preceding TOML table. diff --git a/registry/plugins.toml b/registry/plugins.toml deleted file mode 100644 index 5056f6d..0000000 --- a/registry/plugins.toml +++ /dev/null @@ -1,965 +0,0 @@ -# Human-maintained plugin registry. -# -# Example: -# [[plugins]] -# id = "songcore" -# name = "SongCore" -# repo = "Kylemc1413/SongCore" -# asset_patterns = ["*SongCore*.zip"] -# install_strategy = "bsipa-zip" -# category = "library" -# -# [[plugins.dependencies]] -# id = "bs-utils" -# constraint = ">=1.0" -# required = true - -[[plugins]] -id = "accsaber-reloaded" -name = "AccSaber Reloaded" -repo = "not-dexter/accsaber-reloaded-plugin" -asset_patterns = ["1.40.8.zip"] -install_strategy = "bsipa-zip" -category = "leaderboard" - -[[plugins]] -id = "bsipa" -name = "BSIPA" -repo = "nike4613/BeatSaber-IPA-Reloaded" -asset_patterns = ["BSIPA-net472-x64.zip"] -install_strategy = "root-zip" -category = "core" - -[[plugins]] -id = "beatsabermarkuplanguage" -name = "BeatSaberMarkupLanguage" -repo = "monkeymanboy/BeatSaberMarkupLanguage" -asset_patterns = ["*RELEASE.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "bettersonglist" -name = "BetterSongList" -repo = "kinsi55/BeatSaber_BetterSongList" -asset_patterns = ["BetterSongList.dll"] -install_strategy = "dll-to-plugins" -category = "ui" - -[[plugins]] -id = "hitscorevisualizer" -name = "HitScoreVisualizer" -repo = "ErisApps/HitScoreVisualizer" -asset_patterns = ["HitScoreVisualizer-*.zip"] -install_strategy = "bsipa-zip" -category = "ui" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "ditails" -name = "DiTails" -repo = "Auros/DiTails" -asset_patterns = ["DiTails-*.zip"] -install_strategy = "bsipa-zip" -category = "ui" - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "beatsaversharp" -constraint = ">=3.4.5" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "hidethelogo" -name = "HideTheLogo" -repo = "TheBlackParrot/HideTheLogo" -asset_patterns = ["HideTheLogo-*.zip"] -install_strategy = "bsipa-zip" -category = "ui" - -[[plugins]] -id = "songchartvisualizer" -name = "SongChartVisualizer" -repo = "NuggoDEV/SongChartVisualizer" -asset_patterns = ["SongChartVisualizer-*.zip"] -install_strategy = "bsipa-zip" -category = "ui" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "sirautil" -name = "SiraUtil" -repo = "Auros/SiraUtil" -asset_patterns = ["SiraUtil-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "songcore" -name = "SongCore" -repo = "Kylemc1413/SongCore" -asset_patterns = ["SongCore-*.zip"] -install_strategy = "bsipa-zip" -category = "core" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins]] -id = "customjsondata" -name = "CustomJSONData" -repo = "Aeroluna/CustomJSONData" -asset_patterns = ["CustomJSONData-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "heck" -name = "Heck" -repo = "Aeroluna/Heck" -asset_patterns = ["Heck-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "customjsondata" -constraint = ">=2.6.8" -required = true - -[[plugins]] -id = "lookupid" -name = "LookupID" -repo = "Aeroluna/Heck" -asset_patterns = ["LookupID-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "chroma" -name = "Chroma" -repo = "Aeroluna/Heck" -asset_patterns = ["Chroma-*.zip"] -install_strategy = "bsipa-zip" -category = "mapping" - -[[plugins.dependencies]] -id = "heck" -constraint = ">=1.8.3" -required = true - -[[plugins.dependencies]] -id = "customjsondata" -constraint = ">=2.6.8" -required = true - -[[plugins.dependencies]] -id = "lookupid" -constraint = ">=1.0.1" -required = true - -[[plugins]] -id = "noodleextensions" -name = "Noodle Extensions" -repo = "Aeroluna/Heck" -asset_patterns = ["NoodleExtensions-*.zip"] -install_strategy = "bsipa-zip" -category = "mapping" - -[[plugins.dependencies]] -id = "heck" -constraint = ">=1.8.3" -required = true - -[[plugins.dependencies]] -id = "customjsondata" -constraint = ">=2.6.8" -required = true - -[[plugins]] -id = "camerautils" -name = "CameraUtils" -repo = "Reezonate/CameraUtils" -asset_patterns = ["CameraUtils-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "assetbundleloadingtools" -name = "AssetBundleLoadingTools" -repo = "nicoco007/AssetBundleLoadingTools" -asset_patterns = ["AssetBundleLoadingTools-*.zip"] -install_strategy = "root-zip" -category = "library" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "system-io-compression" -constraint = ">=4.6.57" -required = true - -[[plugins.dependencies]] -id = "system-io-compression-filesystem" -constraint = ">=4.7.3056" -required = true - -[[plugins]] -id = "vivify" -name = "Vivify" -repo = "Aeroluna/Vivify" -asset_patterns = ["Vivify-*.zip"] -install_strategy = "bsipa-zip" -category = "mapping" - -[[plugins.dependencies]] -id = "heck" -constraint = ">=1.8.3" -required = true - -[[plugins.dependencies]] -id = "customjsondata" -constraint = ">=2.6.8" -required = true - -[[plugins.dependencies]] -id = "camerautils" -constraint = ">=1.0.8" -required = true - -[[plugins.dependencies]] -id = "assetbundleloadingtools" -constraint = ">=1.1.13" -required = true - -[[plugins]] -id = "iniparser" -name = "Ini Parser" -repo = "rickyah/ini-parser" -asset_patterns = ["IniParser-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "bs-utils" -name = "BS Utils" -repo = "Kylemc1413/Beat-Saber-Utils" -asset_patterns = ["BSUtils-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "iniparser" -constraint = ">=2.5.9" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "system-io-compression" -name = "System.IO.Compression" -asset_patterns = ["System.IO.Compression-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "system-io-compression-filesystem" -name = "System.IO.Compression.FileSystem" -asset_patterns = ["System.IO.Compression.FileSystem-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "system-io-compression" -constraint = ">=4.6.57" -required = true - -[[plugins]] -id = "imagesharp" -name = "ImageSharp" -repo = "SixLabors/ImageSharp" -asset_patterns = ["ImageSharp-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "beatsaberplaylistslib" -name = "BeatSaberPlaylistsLib" -repo = "Meivyn/BeatSaberPlaylistsLib" -asset_patterns = ["BeatSaberPlaylistsLib-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "imagesharp" -constraint = ">=2.0.0" -required = true - -[[plugins.dependencies]] -id = "system-io-compression" -constraint = ">=4.6.57" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "beatsaversharp" -name = "BeatSaverSharp" -repo = "Auros/BeatSaverSharper" -asset_patterns = ["BeatSaverSharp-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "scoresabersharp" -name = "ScoreSaberSharp" -asset_patterns = ["ScoreSaberSharp-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "scoresaber" -name = "ScoreSaber" -repo = "ScoreSaber/pc-mod" -asset_patterns = ["ScoreSaber-*.zip"] -install_strategy = "bsipa-zip" -category = "leaderboard" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "leaderboardcore" -name = "LeaderboardCore" -repo = "NSGolova/LeaderboardCore" -asset_patterns = ["LeaderboardCore-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "protobuf-net" -name = "protobuf-net" -repo = "protobuf-net/protobuf-net" -asset_patterns = ["protobuf-net-*.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins]] -id = "songdetailscache" -name = "SongDetailsCache" -repo = "kinsi55/BeatSaber_SongDetails" -asset_patterns = ["SongDetailsCache.BS.Lib.zip"] -install_strategy = "bsipa-zip" -category = "library" - -[[plugins.dependencies]] -id = "protobuf-net" -constraint = ">=3.0.102" -required = true - -[[plugins]] -id = "songrankedbadge" -name = "SongRankedBadge" -repo = "qe201020335/SongRankedBadge" -asset_patterns = ["SongRankedBadge-*.zip"] -install_strategy = "bsipa-zip" -category = "ui" - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "songdetailscache" -constraint = ">=1.4.0" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "beatleader" -name = "BeatLeader" -repo = "BeatLeader/beatleader-mod" -asset_patterns = ["BeatLeader-*.zip"] -install_strategy = "bsipa-zip" -category = "leaderboard" - -[[plugins.dependencies]] -id = "bs-utils" -constraint = ">=1.14.3" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "beatsaverdownloader" -name = "BeatSaverDownloader" -repo = "Top-Cat/BeatSaverDownloader" -asset_patterns = ["BeatSaverDownloader-*.zip"] -install_strategy = "bsipa-zip" -category = "downloader" - -[[plugins.dependencies]] -id = "bs-utils" -constraint = ">=1.14.3" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "scoresabersharp" -constraint = ">=0.1.0" -required = true - -[[plugins.dependencies]] -id = "system-io-compression-filesystem" -constraint = ">=4.7.3056" -required = true - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "beatsaversharp" -constraint = ">=3.4.5" -required = true - -[[plugins]] -id = "beatsaverupdater" -name = "BeatSaverUpdater" -repo = "ibillingsley/BeatSaverUpdater" -asset_patterns = ["BeatSaverUpdater-*.zip"] -install_strategy = "bsipa-zip" -category = "downloader" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "beatsaversharp" -constraint = ">=3.4.5" -required = true - -[[plugins]] -id = "playlistmanager" -name = "PlaylistManager" -repo = "rithik-b/PlaylistManager" -asset_patterns = ["PlaylistManager-*.zip"] -install_strategy = "bsipa-zip" -category = "playlist" - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "beatsaberplaylistslib" -constraint = ">=1.7.2" -required = true - -[[plugins.dependencies]] -id = "system-io-compression-filesystem" -constraint = ">=4.7.3056" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "beatsaversharp" -constraint = ">=3.4.5" -required = true - -[[plugins.dependencies]] -id = "system-io-compression" -constraint = ">=4.6.57" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins]] -id = "beatsavervoting" -name = "BeatSaverVoting" -repo = "Top-Cat/BeatSaverVoting" -asset_patterns = ["BeatSaverVoting-*.zip"] -install_strategy = "bsipa-zip" -category = "downloader" - -[[plugins.dependencies]] -id = "bs-utils" -constraint = ">=1.14.3" -required = true - -[[plugins.dependencies]] -id = "songcore" -constraint = ">=3.16.0" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "setlist" -name = "Setlist" -asset_patterns = ["Setlist.dll"] -install_strategy = "dll-to-plugins" -category = "ui" - -[[plugins.dependencies]] -id = "beatleader" -constraint = ">=0.9.0" -required = true - -[[plugins.dependencies]] -id = "playlistmanager" -constraint = ">=1.7.0" -required = true - -[[plugins.dependencies]] -id = "beatsaberplaylistslib" -constraint = ">=1.7.0" -required = true - -[[plugins]] -id = "introskip" -name = "IntroSkip" -repo = "Loloppe/Intro-Skip" -asset_patterns = ["IntroSkip-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "failbutton" -name = "FailButton" -repo = "qe201020335/FailButton" -asset_patterns = ["FailButton-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins]] -id = "easyoffset" -name = "EasyOffset" -repo = "Reezonate/EasyOffset" -asset_patterns = ["EasyOffset.dll"] -install_strategy = "dll-to-plugins" -category = "gameplay" - -[[plugins]] -id = "gottagofast" -name = "GottaGoFast" -repo = "kinsi55/CS_BeatSaber_GottaGoFast" -asset_patterns = ["GottaGoFast.dll"] -install_strategy = "dll-to-plugins" -category = "gameplay" - -[[plugins]] -id = "hitsoundtweaks" -name = "HitsoundTweaks" -repo = "GalaxyMaster2/HitsoundTweaks" -asset_patterns = ["HitsoundTweaks-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins]] -id = "keepmyoverridespls" -name = "KeepMyOverridesPls" -repo = "qqrz997/KeepMyOverridesPls" -asset_patterns = ["KeepMyOverridesPls-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins]] -id = "soundreplacer" -name = "SoundReplacer" -repo = "Meivyn/SoundReplacer" -asset_patterns = ["SoundReplacer-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "keyremapper" -name = "KeyRemapper" -repo = "lyyQwQ/KeyRemapper" -asset_patterns = ["KeyRemapper-*.zip"] -install_strategy = "bsipa-zip" -category = "gameplay" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "squattobegin" -name = "SquatToBegin" -repo = "kinsi55/BeatSaber_SquatToBegin" -asset_patterns = ["SquatToBegin.dll"] -install_strategy = "dll-to-plugins" -category = "gameplay" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "adblocker" -name = "AdBlocker" -repo = "JonnyVR1/AdBlocker" -asset_patterns = ["AdBlocker-*.zip"] -install_strategy = "bsipa-zip" -category = "cosmetic" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "highlightbombs" -name = "HighlightBombs" -repo = "Meivyn/HighlightBombs" -asset_patterns = ["HighlightBombs-*.zip", "HighlightBombs.dll"] -install_strategy = "bsipa-zip" -category = "cosmetic" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins]] -id = "pitchblack" -name = "PitchBlack" -repo = "Loloppe/BeatSaber_PitchBlack" -asset_patterns = ["PitchBlack-*.zip"] -install_strategy = "bsipa-zip" -category = "lighting" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "reecamera" -name = "ReeCamera" -repo = "Reezonate/ReeCamera" -asset_patterns = ["ReeCamera.*.zip"] -install_strategy = "root-zip" -category = "camera" - -[[plugins.dependencies]] -id = "camerautils" -constraint = ">=1.0.8" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "jdfixer" -name = "JDFixer" -repo = "zeph-yr/JDFixer" -asset_patterns = ["JDFixer.dll"] -install_strategy = "dll-to-plugins" -category = "gameplay" - -[[plugins.dependencies]] -id = "beatsabermarkuplanguage" -constraint = ">=1.14.1" -required = true - -[[plugins.dependencies]] -id = "sirautil" -constraint = ">=3.3.1" -required = true - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "beatsaberplus" -name = "BeatSaberPlus" -repo = "discord/BeatSaberPlus" -asset_patterns = ["BeatSaberPlus_*.zip"] -install_strategy = "bsipa-zip" -category = "streaming" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true - -[[plugins]] -id = "naluluna" -name = "Naluluna" -repo = "patreon/NalulunaModAssistant" -asset_patterns = ["Naluluna-*-installed-bundle.zip", "NalulunaUtils-*.zip"] -install_strategy = "root-zip" -category = "cosmetic" - -[[plugins.dependencies]] -id = "bsipa" -constraint = ">=4.3.7" -required = true diff --git a/registry/plugins/accsaber-reloaded.toml b/registry/plugins/accsaber-reloaded.toml new file mode 100644 index 0000000..16557d4 --- /dev/null +++ b/registry/plugins/accsaber-reloaded.toml @@ -0,0 +1,6 @@ +id = "accsaber-reloaded" +name = "AccSaber Reloaded" +repo = "not-dexter/accsaber-reloaded-plugin" +asset_patterns = ["1.40.8.zip"] +install_strategy = "bsipa-zip" +category = "leaderboard" diff --git a/registry/plugins/adblocker.toml b/registry/plugins/adblocker.toml new file mode 100644 index 0000000..be6e481 --- /dev/null +++ b/registry/plugins/adblocker.toml @@ -0,0 +1,9 @@ +id = "adblocker" +name = "AdBlocker" +repo = "JonnyVR1/AdBlocker" +asset_patterns = ["AdBlocker-*.zip"] +install_strategy = "bsipa-zip" +category = "cosmetic" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/assetbundleloadingtools.toml b/registry/plugins/assetbundleloadingtools.toml new file mode 100644 index 0000000..1208387 --- /dev/null +++ b/registry/plugins/assetbundleloadingtools.toml @@ -0,0 +1,13 @@ +id = "assetbundleloadingtools" +name = "AssetBundleLoadingTools" +repo = "nicoco007/AssetBundleLoadingTools" +asset_patterns = ["AssetBundleLoadingTools-*.zip"] +install_strategy = "root-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "system-io-compression", constraint = ">=4.6.57" }, + { id = "system-io-compression-filesystem", constraint = ">=4.7.3056" }, +] diff --git a/registry/plugins/beatleader.toml b/registry/plugins/beatleader.toml new file mode 100644 index 0000000..fffdc03 --- /dev/null +++ b/registry/plugins/beatleader.toml @@ -0,0 +1,14 @@ +id = "beatleader" +name = "BeatLeader" +repo = "BeatLeader/beatleader-mod" +asset_patterns = ["BeatLeader-*.zip"] +install_strategy = "bsipa-zip" +category = "leaderboard" +dependencies = [ + { id = "bs-utils", constraint = ">=1.14.3" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "songcore", constraint = ">=3.16.0" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "system-io-compression", constraint = ">=4.6.0" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/beatsabermarkuplanguage.toml b/registry/plugins/beatsabermarkuplanguage.toml new file mode 100644 index 0000000..c17a67f --- /dev/null +++ b/registry/plugins/beatsabermarkuplanguage.toml @@ -0,0 +1,9 @@ +id = "beatsabermarkuplanguage" +name = "BeatSaberMarkupLanguage" +repo = "monkeymanboy/BeatSaberMarkupLanguage" +asset_patterns = ["*RELEASE.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/beatsaberplaylistslib.toml b/registry/plugins/beatsaberplaylistslib.toml new file mode 100644 index 0000000..cc036b9 --- /dev/null +++ b/registry/plugins/beatsaberplaylistslib.toml @@ -0,0 +1,12 @@ +id = "beatsaberplaylistslib" +name = "BeatSaberPlaylistsLib" +repo = "Meivyn/BeatSaberPlaylistsLib" +asset_patterns = ["BeatSaberPlaylistsLib-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "songcore", constraint = ">=3.16.0" }, + { id = "imagesharp", constraint = ">=2.0.0" }, + { id = "system-io-compression", constraint = ">=4.6.57" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/beatsaberplus.toml b/registry/plugins/beatsaberplus.toml new file mode 100644 index 0000000..e60a0a2 --- /dev/null +++ b/registry/plugins/beatsaberplus.toml @@ -0,0 +1,9 @@ +id = "beatsaberplus" +name = "BeatSaberPlus" +repo = "discord/BeatSaberPlus" +asset_patterns = ["BeatSaberPlus_*.zip"] +install_strategy = "bsipa-zip" +category = "streaming" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/beatsaverdownloader.toml b/registry/plugins/beatsaverdownloader.toml new file mode 100644 index 0000000..5ce8108 --- /dev/null +++ b/registry/plugins/beatsaverdownloader.toml @@ -0,0 +1,15 @@ +id = "beatsaverdownloader" +name = "BeatSaverDownloader" +repo = "Top-Cat/BeatSaverDownloader" +asset_patterns = ["BeatSaverDownloader-*.zip"] +install_strategy = "bsipa-zip" +category = "downloader" +dependencies = [ + { id = "bs-utils", constraint = ">=1.14.3" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "scoresabersharp", constraint = ">=0.1.0" }, + { id = "system-io-compression-filesystem", constraint = ">=4.7.3056" }, + { id = "songcore", constraint = ">=3.16.0" }, + { id = "beatsaversharp", constraint = ">=3.4.5" }, +] diff --git a/registry/plugins/beatsaversharp.toml b/registry/plugins/beatsaversharp.toml new file mode 100644 index 0000000..6d2b2c4 --- /dev/null +++ b/registry/plugins/beatsaversharp.toml @@ -0,0 +1,6 @@ +id = "beatsaversharp" +name = "BeatSaverSharp" +repo = "Auros/BeatSaverSharper" +asset_patterns = ["BeatSaverSharp-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/beatsaverupdater.toml b/registry/plugins/beatsaverupdater.toml new file mode 100644 index 0000000..7e1906f --- /dev/null +++ b/registry/plugins/beatsaverupdater.toml @@ -0,0 +1,13 @@ +id = "beatsaverupdater" +name = "BeatSaverUpdater" +repo = "ibillingsley/BeatSaverUpdater" +asset_patterns = ["BeatSaverUpdater-*.zip"] +install_strategy = "bsipa-zip" +category = "downloader" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "songcore", constraint = ">=3.16.0" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "beatsaversharp", constraint = ">=3.4.5" }, +] diff --git a/registry/plugins/beatsavervoting.toml b/registry/plugins/beatsavervoting.toml new file mode 100644 index 0000000..3067f79 --- /dev/null +++ b/registry/plugins/beatsavervoting.toml @@ -0,0 +1,12 @@ +id = "beatsavervoting" +name = "BeatSaverVoting" +repo = "Top-Cat/BeatSaverVoting" +asset_patterns = ["BeatSaverVoting-*.zip"] +install_strategy = "bsipa-zip" +category = "downloader" +dependencies = [ + { id = "bs-utils", constraint = ">=1.14.3" }, + { id = "songcore", constraint = ">=3.16.0" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/bettersonglist.toml b/registry/plugins/bettersonglist.toml new file mode 100644 index 0000000..61557eb --- /dev/null +++ b/registry/plugins/bettersonglist.toml @@ -0,0 +1,6 @@ +id = "bettersonglist" +name = "BetterSongList" +repo = "kinsi55/BeatSaber_BetterSongList" +asset_patterns = ["BetterSongList.dll"] +install_strategy = "dll-to-plugins" +category = "ui" diff --git a/registry/plugins/bs-utils.toml b/registry/plugins/bs-utils.toml new file mode 100644 index 0000000..9e87127 --- /dev/null +++ b/registry/plugins/bs-utils.toml @@ -0,0 +1,10 @@ +id = "bs-utils" +name = "BS Utils" +repo = "Kylemc1413/Beat-Saber-Utils" +asset_patterns = ["BSUtils-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "iniparser", constraint = ">=2.5.9" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/bsipa.toml b/registry/plugins/bsipa.toml new file mode 100644 index 0000000..ce947b5 --- /dev/null +++ b/registry/plugins/bsipa.toml @@ -0,0 +1,6 @@ +id = "bsipa" +name = "BSIPA" +repo = "nike4613/BeatSaber-IPA-Reloaded" +asset_patterns = ["BSIPA-net472-x64.zip"] +install_strategy = "root-zip" +category = "core" diff --git a/registry/plugins/camerautils.toml b/registry/plugins/camerautils.toml new file mode 100644 index 0000000..6302be4 --- /dev/null +++ b/registry/plugins/camerautils.toml @@ -0,0 +1,9 @@ +id = "camerautils" +name = "CameraUtils" +repo = "Reezonate/CameraUtils" +asset_patterns = ["CameraUtils-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/chroma.toml b/registry/plugins/chroma.toml new file mode 100644 index 0000000..4570ece --- /dev/null +++ b/registry/plugins/chroma.toml @@ -0,0 +1,11 @@ +id = "chroma" +name = "Chroma" +repo = "Aeroluna/Heck" +asset_patterns = ["Chroma-*.zip"] +install_strategy = "bsipa-zip" +category = "mapping" +dependencies = [ + { id = "heck", constraint = ">=1.8.3" }, + { id = "customjsondata", constraint = ">=2.6.8" }, + { id = "lookupid", constraint = ">=1.0.1" }, +] diff --git a/registry/plugins/customjsondata.toml b/registry/plugins/customjsondata.toml new file mode 100644 index 0000000..999c930 --- /dev/null +++ b/registry/plugins/customjsondata.toml @@ -0,0 +1,9 @@ +id = "customjsondata" +name = "CustomJSONData" +repo = "Aeroluna/CustomJSONData" +asset_patterns = ["CustomJSONData-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/ditails.toml b/registry/plugins/ditails.toml new file mode 100644 index 0000000..406b651 --- /dev/null +++ b/registry/plugins/ditails.toml @@ -0,0 +1,13 @@ +id = "ditails" +name = "DiTails" +repo = "Auros/DiTails" +asset_patterns = ["DiTails-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "songcore", constraint = ">=3.16.0" }, + { id = "beatsaversharp", constraint = ">=3.4.5" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/easyoffset.toml b/registry/plugins/easyoffset.toml new file mode 100644 index 0000000..8dd9f4c --- /dev/null +++ b/registry/plugins/easyoffset.toml @@ -0,0 +1,6 @@ +id = "easyoffset" +name = "EasyOffset" +repo = "Reezonate/EasyOffset" +asset_patterns = ["EasyOffset.dll"] +install_strategy = "dll-to-plugins" +category = "gameplay" diff --git a/registry/plugins/failbutton.toml b/registry/plugins/failbutton.toml new file mode 100644 index 0000000..e8a6e57 --- /dev/null +++ b/registry/plugins/failbutton.toml @@ -0,0 +1,6 @@ +id = "failbutton" +name = "FailButton" +repo = "qe201020335/FailButton" +asset_patterns = ["FailButton-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" diff --git a/registry/plugins/gottagofast.toml b/registry/plugins/gottagofast.toml new file mode 100644 index 0000000..de9a832 --- /dev/null +++ b/registry/plugins/gottagofast.toml @@ -0,0 +1,6 @@ +id = "gottagofast" +name = "GottaGoFast" +repo = "kinsi55/CS_BeatSaber_GottaGoFast" +asset_patterns = ["GottaGoFast.dll"] +install_strategy = "dll-to-plugins" +category = "gameplay" diff --git a/registry/plugins/heck.toml b/registry/plugins/heck.toml new file mode 100644 index 0000000..51bd243 --- /dev/null +++ b/registry/plugins/heck.toml @@ -0,0 +1,10 @@ +id = "heck" +name = "Heck" +repo = "Aeroluna/Heck" +asset_patterns = ["Heck-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "customjsondata", constraint = ">=2.6.8" }, +] diff --git a/registry/plugins/hidethelogo.toml b/registry/plugins/hidethelogo.toml new file mode 100644 index 0000000..36e4d1c --- /dev/null +++ b/registry/plugins/hidethelogo.toml @@ -0,0 +1,6 @@ +id = "hidethelogo" +name = "HideTheLogo" +repo = "TheBlackParrot/HideTheLogo" +asset_patterns = ["HideTheLogo-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" diff --git a/registry/plugins/highlightbombs.toml b/registry/plugins/highlightbombs.toml new file mode 100644 index 0000000..42c83ea --- /dev/null +++ b/registry/plugins/highlightbombs.toml @@ -0,0 +1,10 @@ +id = "highlightbombs" +name = "HighlightBombs" +repo = "Meivyn/HighlightBombs" +asset_patterns = ["HighlightBombs-*.zip", "HighlightBombs.dll"] +install_strategy = "bsipa-zip" +category = "cosmetic" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "sirautil", constraint = ">=3.3.1" }, +] diff --git a/registry/plugins/hitscorevisualizer.toml b/registry/plugins/hitscorevisualizer.toml new file mode 100644 index 0000000..f22dd5d --- /dev/null +++ b/registry/plugins/hitscorevisualizer.toml @@ -0,0 +1,10 @@ +id = "hitscorevisualizer" +name = "HitScoreVisualizer" +repo = "ErisApps/HitScoreVisualizer" +asset_patterns = ["HitScoreVisualizer-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/hitsoundtweaks.toml b/registry/plugins/hitsoundtweaks.toml new file mode 100644 index 0000000..3c95386 --- /dev/null +++ b/registry/plugins/hitsoundtweaks.toml @@ -0,0 +1,6 @@ +id = "hitsoundtweaks" +name = "HitsoundTweaks" +repo = "GalaxyMaster2/HitsoundTweaks" +asset_patterns = ["HitsoundTweaks-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" diff --git a/registry/plugins/imagesharp.toml b/registry/plugins/imagesharp.toml new file mode 100644 index 0000000..fd32e7e --- /dev/null +++ b/registry/plugins/imagesharp.toml @@ -0,0 +1,6 @@ +id = "imagesharp" +name = "ImageSharp" +repo = "SixLabors/ImageSharp" +asset_patterns = ["ImageSharp-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/iniparser.toml b/registry/plugins/iniparser.toml new file mode 100644 index 0000000..0364dec --- /dev/null +++ b/registry/plugins/iniparser.toml @@ -0,0 +1,6 @@ +id = "iniparser" +name = "Ini Parser" +repo = "rickyah/ini-parser" +asset_patterns = ["IniParser-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/introskip.toml b/registry/plugins/introskip.toml new file mode 100644 index 0000000..55bc215 --- /dev/null +++ b/registry/plugins/introskip.toml @@ -0,0 +1,11 @@ +id = "introskip" +name = "IntroSkip" +repo = "Loloppe/Intro-Skip" +asset_patterns = ["IntroSkip-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/jdfixer.toml b/registry/plugins/jdfixer.toml new file mode 100644 index 0000000..aa85bd1 --- /dev/null +++ b/registry/plugins/jdfixer.toml @@ -0,0 +1,11 @@ +id = "jdfixer" +name = "JDFixer" +repo = "zeph-yr/JDFixer" +asset_patterns = ["JDFixer.dll"] +install_strategy = "dll-to-plugins" +category = "gameplay" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/keepmyoverridespls.toml b/registry/plugins/keepmyoverridespls.toml new file mode 100644 index 0000000..86f12d9 --- /dev/null +++ b/registry/plugins/keepmyoverridespls.toml @@ -0,0 +1,6 @@ +id = "keepmyoverridespls" +name = "KeepMyOverridesPls" +repo = "qqrz997/KeepMyOverridesPls" +asset_patterns = ["KeepMyOverridesPls-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" diff --git a/registry/plugins/keyremapper.toml b/registry/plugins/keyremapper.toml new file mode 100644 index 0000000..1424f9b --- /dev/null +++ b/registry/plugins/keyremapper.toml @@ -0,0 +1,11 @@ +id = "keyremapper" +name = "KeyRemapper" +repo = "lyyQwQ/KeyRemapper" +asset_patterns = ["KeyRemapper-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/leaderboardcore.toml b/registry/plugins/leaderboardcore.toml new file mode 100644 index 0000000..dcfed2f --- /dev/null +++ b/registry/plugins/leaderboardcore.toml @@ -0,0 +1,11 @@ +id = "leaderboardcore" +name = "LeaderboardCore" +repo = "NSGolova/LeaderboardCore" +asset_patterns = ["LeaderboardCore-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/lookupid.toml b/registry/plugins/lookupid.toml new file mode 100644 index 0000000..072d869 --- /dev/null +++ b/registry/plugins/lookupid.toml @@ -0,0 +1,6 @@ +id = "lookupid" +name = "LookupID" +repo = "Aeroluna/Heck" +asset_patterns = ["LookupID-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/naluluna.toml b/registry/plugins/naluluna.toml new file mode 100644 index 0000000..4c45696 --- /dev/null +++ b/registry/plugins/naluluna.toml @@ -0,0 +1,9 @@ +id = "naluluna" +name = "Naluluna" +repo = "patreon/NalulunaModAssistant" +asset_patterns = ["Naluluna-*-installed-bundle.zip", "NalulunaUtils-*.zip"] +install_strategy = "root-zip" +category = "cosmetic" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/noodleextensions.toml b/registry/plugins/noodleextensions.toml new file mode 100644 index 0000000..cab8bb8 --- /dev/null +++ b/registry/plugins/noodleextensions.toml @@ -0,0 +1,10 @@ +id = "noodleextensions" +name = "Noodle Extensions" +repo = "Aeroluna/Heck" +asset_patterns = ["NoodleExtensions-*.zip"] +install_strategy = "bsipa-zip" +category = "mapping" +dependencies = [ + { id = "heck", constraint = ">=1.8.3" }, + { id = "customjsondata", constraint = ">=2.6.8" }, +] diff --git a/registry/plugins/pitchblack.toml b/registry/plugins/pitchblack.toml new file mode 100644 index 0000000..e74a1d6 --- /dev/null +++ b/registry/plugins/pitchblack.toml @@ -0,0 +1,10 @@ +id = "pitchblack" +name = "PitchBlack" +repo = "Loloppe/BeatSaber_PitchBlack" +asset_patterns = ["PitchBlack-*.zip"] +install_strategy = "bsipa-zip" +category = "lighting" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/playlistmanager.toml b/registry/plugins/playlistmanager.toml new file mode 100644 index 0000000..ea7208b --- /dev/null +++ b/registry/plugins/playlistmanager.toml @@ -0,0 +1,16 @@ +id = "playlistmanager" +name = "PlaylistManager" +repo = "rithik-b/PlaylistManager" +asset_patterns = ["PlaylistManager-*.zip"] +install_strategy = "bsipa-zip" +category = "playlist" +dependencies = [ + { id = "songcore", constraint = ">=3.16.0" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "beatsaberplaylistslib", constraint = ">=1.7.2" }, + { id = "system-io-compression-filesystem", constraint = ">=4.7.3056" }, + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "beatsaversharp", constraint = ">=3.4.5" }, + { id = "system-io-compression", constraint = ">=4.6.57" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, +] diff --git a/registry/plugins/protobuf-net.toml b/registry/plugins/protobuf-net.toml new file mode 100644 index 0000000..9aa6f8c --- /dev/null +++ b/registry/plugins/protobuf-net.toml @@ -0,0 +1,6 @@ +id = "protobuf-net" +name = "protobuf-net" +repo = "protobuf-net/protobuf-net" +asset_patterns = ["protobuf-net-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/reecamera.toml b/registry/plugins/reecamera.toml new file mode 100644 index 0000000..371f33c --- /dev/null +++ b/registry/plugins/reecamera.toml @@ -0,0 +1,10 @@ +id = "reecamera" +name = "ReeCamera" +repo = "Reezonate/ReeCamera" +asset_patterns = ["ReeCamera.*.zip"] +install_strategy = "root-zip" +category = "camera" +dependencies = [ + { id = "camerautils", constraint = ">=1.0.8" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/scoresaber.toml b/registry/plugins/scoresaber.toml new file mode 100644 index 0000000..49ef53d --- /dev/null +++ b/registry/plugins/scoresaber.toml @@ -0,0 +1,12 @@ +id = "scoresaber" +name = "ScoreSaber" +repo = "ScoreSaber/pc-mod" +asset_patterns = ["ScoreSaber-*.zip"] +install_strategy = "bsipa-zip" +category = "leaderboard" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "songcore", constraint = ">=3.16.0" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/scoresabersharp.toml b/registry/plugins/scoresabersharp.toml new file mode 100644 index 0000000..31562ec --- /dev/null +++ b/registry/plugins/scoresabersharp.toml @@ -0,0 +1,5 @@ +id = "scoresabersharp" +name = "ScoreSaberSharp" +asset_patterns = ["ScoreSaberSharp-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/setlist.toml b/registry/plugins/setlist.toml new file mode 100644 index 0000000..10aa3cb --- /dev/null +++ b/registry/plugins/setlist.toml @@ -0,0 +1,10 @@ +id = "setlist" +name = "Setlist" +asset_patterns = ["Setlist.dll"] +install_strategy = "dll-to-plugins" +category = "ui" +dependencies = [ + { id = "beatleader", constraint = ">=0.9.0" }, + { id = "playlistmanager", constraint = ">=1.7.0" }, + { id = "beatsaberplaylistslib", constraint = ">=1.7.0" }, +] diff --git a/registry/plugins/sirautil.toml b/registry/plugins/sirautil.toml new file mode 100644 index 0000000..161d355 --- /dev/null +++ b/registry/plugins/sirautil.toml @@ -0,0 +1,9 @@ +id = "sirautil" +name = "SiraUtil" +repo = "Auros/SiraUtil" +asset_patterns = ["SiraUtil-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/songchartvisualizer.toml b/registry/plugins/songchartvisualizer.toml new file mode 100644 index 0000000..d935c02 --- /dev/null +++ b/registry/plugins/songchartvisualizer.toml @@ -0,0 +1,11 @@ +id = "songchartvisualizer" +name = "SongChartVisualizer" +repo = "NuggoDEV/SongChartVisualizer" +asset_patterns = ["SongChartVisualizer-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/songcore.toml b/registry/plugins/songcore.toml new file mode 100644 index 0000000..684e777 --- /dev/null +++ b/registry/plugins/songcore.toml @@ -0,0 +1,11 @@ +id = "songcore" +name = "SongCore" +repo = "Kylemc1413/SongCore" +asset_patterns = ["SongCore-*.zip"] +install_strategy = "bsipa-zip" +category = "core" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "sirautil", constraint = ">=3.3.1" }, +] diff --git a/registry/plugins/songdetailscache.toml b/registry/plugins/songdetailscache.toml new file mode 100644 index 0000000..893a2df --- /dev/null +++ b/registry/plugins/songdetailscache.toml @@ -0,0 +1,9 @@ +id = "songdetailscache" +name = "SongDetailsCache" +repo = "kinsi55/BeatSaber_SongDetails" +asset_patterns = ["SongDetailsCache.BS.Lib.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "protobuf-net", constraint = ">=3.0.102" }, +] diff --git a/registry/plugins/songrankedbadge.toml b/registry/plugins/songrankedbadge.toml new file mode 100644 index 0000000..23148ea --- /dev/null +++ b/registry/plugins/songrankedbadge.toml @@ -0,0 +1,12 @@ +id = "songrankedbadge" +name = "SongRankedBadge" +repo = "qe201020335/SongRankedBadge" +asset_patterns = ["SongRankedBadge-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "songcore", constraint = ">=3.16.0" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "songdetailscache", constraint = ">=1.4.0" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/soundreplacer.toml b/registry/plugins/soundreplacer.toml new file mode 100644 index 0000000..0e81321 --- /dev/null +++ b/registry/plugins/soundreplacer.toml @@ -0,0 +1,11 @@ +id = "soundreplacer" +name = "SoundReplacer" +repo = "Meivyn/SoundReplacer" +asset_patterns = ["SoundReplacer-*.zip"] +install_strategy = "bsipa-zip" +category = "gameplay" +dependencies = [ + { id = "sirautil", constraint = ">=3.3.1" }, + { id = "beatsabermarkuplanguage", constraint = ">=1.14.1" }, + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/squattobegin.toml b/registry/plugins/squattobegin.toml new file mode 100644 index 0000000..b269b77 --- /dev/null +++ b/registry/plugins/squattobegin.toml @@ -0,0 +1,9 @@ +id = "squattobegin" +name = "SquatToBegin" +repo = "kinsi55/BeatSaber_SquatToBegin" +asset_patterns = ["SquatToBegin.dll"] +install_strategy = "dll-to-plugins" +category = "gameplay" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] diff --git a/registry/plugins/system-io-compression-filesystem.toml b/registry/plugins/system-io-compression-filesystem.toml new file mode 100644 index 0000000..a8b8504 --- /dev/null +++ b/registry/plugins/system-io-compression-filesystem.toml @@ -0,0 +1,8 @@ +id = "system-io-compression-filesystem" +name = "System.IO.Compression.FileSystem" +asset_patterns = ["System.IO.Compression.FileSystem-*.zip"] +install_strategy = "bsipa-zip" +category = "library" +dependencies = [ + { id = "system-io-compression", constraint = ">=4.6.57" }, +] diff --git a/registry/plugins/system-io-compression.toml b/registry/plugins/system-io-compression.toml new file mode 100644 index 0000000..8a65bf6 --- /dev/null +++ b/registry/plugins/system-io-compression.toml @@ -0,0 +1,5 @@ +id = "system-io-compression" +name = "System.IO.Compression" +asset_patterns = ["System.IO.Compression-*.zip"] +install_strategy = "bsipa-zip" +category = "library" diff --git a/registry/plugins/vivify.toml b/registry/plugins/vivify.toml new file mode 100644 index 0000000..bd759a3 --- /dev/null +++ b/registry/plugins/vivify.toml @@ -0,0 +1,12 @@ +id = "vivify" +name = "Vivify" +repo = "Aeroluna/Vivify" +asset_patterns = ["Vivify-*.zip"] +install_strategy = "bsipa-zip" +category = "mapping" +dependencies = [ + { id = "heck", constraint = ">=1.8.3" }, + { id = "customjsondata", constraint = ">=2.6.8" }, + { id = "camerautils", constraint = ">=1.0.8" }, + { id = "assetbundleloadingtools", constraint = ">=1.1.13" }, +] diff --git a/src/plugin_helper/cli.py b/src/plugin_helper/cli.py index f0091b1..14938e1 100644 --- a/src/plugin_helper/cli.py +++ b/src/plugin_helper/cli.py @@ -106,7 +106,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) installed.add_argument("--instance", required=True) - installed.add_argument("--registry", default="registry/plugins.toml") + installed.add_argument("--registry", default="registry/plugins") installed.add_argument("--lockfile") installed.add_argument("--json", action="store_true", help="Print full JSON output") @@ -116,7 +116,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) check.add_argument("--instance", required=True) - check.add_argument("--registry", default="registry/plugins.toml") + check.add_argument("--registry", default="registry/plugins") check.add_argument("--lockfile") check.add_argument("--json", action="store_true", help="Print full JSON check output") @@ -126,7 +126,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) bootstrap.add_argument("--instance", required=True) - bootstrap.add_argument("--registry", default="registry/plugins.toml") + bootstrap.add_argument("--registry", default="registry/plugins") bootstrap.add_argument("--lockfile") bootstrap.add_argument("--proton", help="Path to Proton executable (Linux/Proton installs)") bootstrap.add_argument("--native", action="store_true", help="Run IPA.exe -n natively instead of through Proton") @@ -146,7 +146,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) updates.add_argument("--instance", required=True) - updates.add_argument("--registry", default="registry/plugins.toml") + updates.add_argument("--registry", default="registry/plugins") updates.add_argument("--lockfile") updates.add_argument("--plugin", action="append", help="Check only this locked plugin id; repeatable") updates.add_argument("--include-prerelease", action="store_true", help="Include prerelease GitHub releases") @@ -158,7 +158,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) plan.add_argument("--instance", required=True) - plan.add_argument("--registry", default="registry/plugins.toml") + plan.add_argument("--registry", default="registry/plugins") plan.add_argument("--lockfile") plan.add_argument("--plugin", "--update", action="append", help="Plan only this locked plugin id; repeatable") @@ -193,7 +193,7 @@ def build_parser() -> argparse.ArgumentParser: parents=[_common_parent()], ) enable.add_argument("--instance", required=True) - enable.add_argument("--registry", default="registry/plugins.toml") + enable.add_argument("--registry", default="registry/plugins") enable.add_argument("--lockfile") enable.add_argument("plugin") diff --git a/src/plugin_helper/models.py b/src/plugin_helper/models.py index cabf8d2..919f881 100644 --- a/src/plugin_helper/models.py +++ b/src/plugin_helper/models.py @@ -58,33 +58,51 @@ def _load_toml(path: Path) -> dict[str, Any]: return tomllib.load(handle) +def _registry_plugin_from_item(item: dict[str, Any], source: Path) -> RegistryPlugin: + dependencies = tuple( + Dependency( + id=dep["id"], + constraint=dep.get("constraint"), + required=dep.get("required", True), + ) + for dep in item.get("dependencies", []) + ) + strategy = item.get("install_strategy", "manual") + if strategy not in VALID_STRATEGIES: + raise ValueError(f"{source}: invalid install_strategy for {item['id']}: {strategy}") + return RegistryPlugin( + id=item["id"], + name=item.get("name", item["id"]), + repo=item.get("repo"), + asset_patterns=tuple(item.get("asset_patterns", [])), + install_strategy=strategy, + category=item.get("category"), + dependencies=dependencies, + ) + + +def _add_registry_plugin(plugins: dict[str, RegistryPlugin], plugin: RegistryPlugin, source: Path) -> None: + if plugin.id in plugins: + raise ValueError(f"{source}: duplicate plugin id: {plugin.id}") + plugins[plugin.id] = plugin + + def load_registry(path: Path) -> Registry: if not path.exists(): + legacy_path = path.with_suffix(".toml") + if path.name == "plugins" and legacy_path.exists(): + return load_registry(legacy_path) return Registry() - data = _load_toml(path) plugins: dict[str, RegistryPlugin] = {} + if path.is_dir(): + for item_path in sorted(path.glob("*.toml")): + data = _load_toml(item_path) + _add_registry_plugin(plugins, _registry_plugin_from_item(data, item_path), item_path) + return Registry(plugins) + + data = _load_toml(path) for item in data.get("plugins", []): - dependencies = tuple( - Dependency( - id=dep["id"], - constraint=dep.get("constraint"), - required=dep.get("required", True), - ) - for dep in item.get("dependencies", []) - ) - strategy = item.get("install_strategy", "manual") - if strategy not in VALID_STRATEGIES: - raise ValueError(f"{path}: invalid install_strategy for {item['id']}: {strategy}") - plugin = RegistryPlugin( - id=item["id"], - name=item.get("name", item["id"]), - repo=item.get("repo"), - asset_patterns=tuple(item.get("asset_patterns", [])), - install_strategy=strategy, - category=item.get("category"), - dependencies=dependencies, - ) - plugins[plugin.id] = plugin + _add_registry_plugin(plugins, _registry_plugin_from_item(item, path), path) return Registry(plugins) diff --git a/src/plugin_helper/operations.py b/src/plugin_helper/operations.py index 94c4283..fa05ef7 100644 --- a/src/plugin_helper/operations.py +++ b/src/plugin_helper/operations.py @@ -35,7 +35,7 @@ def enable_disabled_plugin( instance_path: Path, state_root: Path, plugin_id: str, - registry: str = "registry/plugins.toml", + registry: str = "registry/plugins", lockfile: str | None = None, repo: Path | None = None, progress: Callable[[str], None] | None = None, @@ -85,7 +85,7 @@ def enable_disabled_plugins( instance_path: Path, state_root: Path, plugin_ids: list[str], - registry: str = "registry/plugins.toml", + registry: str = "registry/plugins", lockfile: str | None = None, repo: Path | None = None, progress: Callable[[str], None] | None = None, diff --git a/src/plugin_helper/planner.py b/src/plugin_helper/planner.py index 292c714..8512bdc 100644 --- a/src/plugin_helper/planner.py +++ b/src/plugin_helper/planner.py @@ -65,6 +65,26 @@ def _asset_matches_patterns(name: str, patterns: tuple[str, ...]) -> bool: return not patterns or any(fnmatch.fnmatch(name, pattern) for pattern in patterns) +def _expand_required_dependencies(selected_ids: set[str], registry: Registry, lockfile: Lockfile) -> set[str]: + locked_ids = {plugin.id for plugin in lockfile.plugins} + expanded = set(selected_ids) + pending = list(selected_ids) + while pending: + plugin_id = pending.pop() + registry_plugin = registry.get(plugin_id) + if not registry_plugin: + continue + for dependency in registry_plugin.dependencies: + if not dependency.required: + continue + if dependency.id not in locked_ids: + raise ValueError(f"{plugin_id}: required dependency is not locked for this instance: {dependency.id}") + if dependency.id not in expanded: + expanded.add(dependency.id) + pending.append(dependency.id) + return expanded + + def create_plan( *, instance: str, @@ -77,7 +97,11 @@ def create_plan( selected: set[str] | None = None, require_bootstrap: bool = True, ) -> tuple[dict[str, Any], Path]: - selected_ids = selected or {plugin.id for plugin in lockfile.plugins} + selected_ids = ( + _expand_required_dependencies(selected, registry, lockfile) + if selected is not None + else {plugin.id for plugin in lockfile.plugins} + ) changes: list[dict[str, Any]] = [] warnings: list[str] = [] diff --git a/src/plugin_helper/tui.py b/src/plugin_helper/tui.py index 7caea3d..06543c4 100644 --- a/src/plugin_helper/tui.py +++ b/src/plugin_helper/tui.py @@ -269,7 +269,7 @@ class PluginHelperTui(App[int]): lockfile = load_lockfile(self.repo_root / "locks" / f"{target.instance_name}.lock.toml") report = installed_plugins_report( installed_state=load_installed_state(target.state_root, target.instance_name), - registry=load_registry(self.repo_root / "registry" / "plugins.toml"), + registry=load_registry(self.repo_root / "registry" / "plugins"), lockfile=lockfile, ) self.plugin_rows = report["plugins"] diff --git a/tests/test_plugin_helper.py b/tests/test_plugin_helper.py index f289ea7..1da8980 100644 --- a/tests/test_plugin_helper.py +++ b/tests/test_plugin_helper.py @@ -22,7 +22,7 @@ from plugin_helper.config import is_windows, load_local_config, resolve_runtime_ from plugin_helper.fsutil import sha256_file from plugin_helper.installer import apply_plan, disable_plugin, uninstall_plugin from plugin_helper.instances import get_instance, list_instances -from plugin_helper.models import Lockfile, LockedPlugin, Registry, RegistryPlugin +from plugin_helper.models import Dependency, Lockfile, LockedPlugin, Registry, RegistryPlugin, load_registry from plugin_helper.operations import enable_disabled_plugin from plugin_helper.planner import create_plan from plugin_helper.scanner import scan_bootstrap_files, scan_instance @@ -40,6 +40,35 @@ from plugin_helper.userdata import ( class PluginHelperTests(unittest.TestCase): + def test_load_registry_reads_plugin_directory(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + registry_dir = root / "registry" / "plugins" + registry_dir.mkdir(parents=True) + (registry_dir / "example.toml").write_text( + """ +id = "example" +name = "Example" +repo = "owner/example" +asset_patterns = ["Example-*.zip"] +install_strategy = "bsipa-zip" +category = "ui" +dependencies = [ + { id = "bsipa", constraint = ">=4.3.7" }, +] +""".lstrip(), + encoding="utf-8", + ) + + registry = load_registry(registry_dir) + + plugin = registry.get("example") + self.assertIsNotNone(plugin) + assert plugin is not None + self.assertEqual(plugin.name, "Example") + self.assertEqual(plugin.asset_patterns, ("Example-*.zip",)) + self.assertEqual(plugin.dependencies, (Dependency(id="bsipa", constraint=">=4.3.7"),)) + def test_normalize_beatmods_current_nested_response(self) -> None: payload = { "mods": [ @@ -872,6 +901,113 @@ sha256 = "{sha256_file(asset)}" self.assertEqual(plan["changes"][0]["source"], str(asset)) + def test_plan_expands_required_dependencies_for_selected_plugin(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + work = Path(tmp) + instance = work / "instances" / "1.40.8" + state = work / "state" + instance.mkdir(parents=True) + (instance / "Beat Saber_Data").mkdir() + plugin_asset = plugin_downloads_dir(state, "1.40.8", "example") / "Example.dll" + dependency_asset = plugin_downloads_dir(state, "1.40.8", "dependency") / "Dependency.dll" + plugin_asset.write_bytes(b"managed dll") + dependency_asset.write_bytes(b"dependency dll") + + plan, _ = create_plan( + instance="1.40.8", + instance_path=instance, + beat_saber_version="1.40.8", + registry=Registry( + { + "example": RegistryPlugin( + id="example", + name="Example", + repo=None, + install_strategy="dll-to-plugins", + dependencies=(Dependency(id="dependency"),), + ), + "dependency": RegistryPlugin( + id="dependency", + name="Dependency", + repo=None, + install_strategy="dll-to-plugins", + ), + } + ), + lockfile=Lockfile( + beat_saber_version="1.40.8", + instance="1.40.8", + plugins=( + LockedPlugin( + id="example", + repo=None, + tag=None, + asset="Example.dll", + sha256=sha256_file(plugin_asset), + ), + LockedPlugin( + id="dependency", + repo=None, + tag=None, + asset="Dependency.dll", + sha256=sha256_file(dependency_asset), + ), + ), + ), + state_root=state, + repo_root=work, + selected={"example"}, + ) + + self.assertEqual( + {change["plugin"] for change in plan["changes"]}, + {"example", "dependency"}, + ) + + def test_plan_rejects_selected_plugin_with_unlocked_required_dependency(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + work = Path(tmp) + instance = work / "instances" / "1.40.8" + state = work / "state" + instance.mkdir(parents=True) + (instance / "Beat Saber_Data").mkdir() + asset = plugin_downloads_dir(state, "1.40.8", "example") / "Example.dll" + asset.write_bytes(b"managed dll") + + with self.assertRaisesRegex(ValueError, "required dependency is not locked"): + create_plan( + instance="1.40.8", + instance_path=instance, + beat_saber_version="1.40.8", + registry=Registry( + { + "example": RegistryPlugin( + id="example", + name="Example", + repo=None, + install_strategy="dll-to-plugins", + dependencies=(Dependency(id="missing"),), + ), + } + ), + lockfile=Lockfile( + beat_saber_version="1.40.8", + instance="1.40.8", + plugins=( + LockedPlugin( + id="example", + repo=None, + tag=None, + asset="Example.dll", + sha256=sha256_file(asset), + ), + ), + ), + state_root=state, + repo_root=work, + selected={"example"}, + ) + def test_zip_member_cannot_escape_instance(self) -> None: with tempfile.TemporaryDirectory() as tmp: work = Path(tmp)