Refactor plugin registry into separate files per plugin

This commit is contained in:
pleb
2026-07-05 14:24:58 -07:00
parent 1b4087c5b5
commit 1858f76766
62 changed files with 730 additions and 1008 deletions
+6 -10
View File
@@ -59,7 +59,9 @@ plugin-helper/
DESIGN.md DESIGN.md
README.md README.md
registry/ registry/
plugins.toml plugins/
songcore.toml
bsipa.toml
locks/ locks/
1.40.8.lock.toml 1.40.8.lock.toml
src/plugin_helper/ src/plugin_helper/
@@ -124,21 +126,15 @@ Artifact source preference:
Example: Example:
```toml ```toml
[[plugins]]
id = "songcore" id = "songcore"
name = "SongCore" name = "SongCore"
repo = "Kylemc1413/SongCore" repo = "Kylemc1413/SongCore"
asset_patterns = ["*SongCore*.zip"] asset_patterns = ["*SongCore*.zip"]
install_strategy = "bsipa-zip" install_strategy = "bsipa-zip"
category = "library" category = "library"
dependencies = [
[plugins.compatibility] { id = "bs-utils", constraint = ">=1.0" },
source = "metadata-or-release-notes" ]
[[plugins.dependencies]]
id = "bs-utils"
constraint = ">=1.0"
required = true
``` ```
Important fields: Important fields:
+18
View File
@@ -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.
-965
View File
@@ -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
+6
View File
@@ -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"
+9
View File
@@ -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" },
]
@@ -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" },
]
+14
View File
@@ -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" },
]
@@ -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" },
]
@@ -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" },
]
+9
View File
@@ -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" },
]
+15
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "beatsaversharp"
name = "BeatSaverSharp"
repo = "Auros/BeatSaverSharper"
asset_patterns = ["BeatSaverSharp-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+13
View File
@@ -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" },
]
+12
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "bettersonglist"
name = "BetterSongList"
repo = "kinsi55/BeatSaber_BetterSongList"
asset_patterns = ["BetterSongList.dll"]
install_strategy = "dll-to-plugins"
category = "ui"
+10
View File
@@ -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" },
]
+6
View File
@@ -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"
+9
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+9
View File
@@ -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" },
]
+13
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "easyoffset"
name = "EasyOffset"
repo = "Reezonate/EasyOffset"
asset_patterns = ["EasyOffset.dll"]
install_strategy = "dll-to-plugins"
category = "gameplay"
+6
View File
@@ -0,0 +1,6 @@
id = "failbutton"
name = "FailButton"
repo = "qe201020335/FailButton"
asset_patterns = ["FailButton-*.zip"]
install_strategy = "bsipa-zip"
category = "gameplay"
+6
View File
@@ -0,0 +1,6 @@
id = "gottagofast"
name = "GottaGoFast"
repo = "kinsi55/CS_BeatSaber_GottaGoFast"
asset_patterns = ["GottaGoFast.dll"]
install_strategy = "dll-to-plugins"
category = "gameplay"
+10
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "hidethelogo"
name = "HideTheLogo"
repo = "TheBlackParrot/HideTheLogo"
asset_patterns = ["HideTheLogo-*.zip"]
install_strategy = "bsipa-zip"
category = "ui"
+10
View File
@@ -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" },
]
+10
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "hitsoundtweaks"
name = "HitsoundTweaks"
repo = "GalaxyMaster2/HitsoundTweaks"
asset_patterns = ["HitsoundTweaks-*.zip"]
install_strategy = "bsipa-zip"
category = "gameplay"
+6
View File
@@ -0,0 +1,6 @@
id = "imagesharp"
name = "ImageSharp"
repo = "SixLabors/ImageSharp"
asset_patterns = ["ImageSharp-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+6
View File
@@ -0,0 +1,6 @@
id = "iniparser"
name = "Ini Parser"
repo = "rickyah/ini-parser"
asset_patterns = ["IniParser-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+11
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "keepmyoverridespls"
name = "KeepMyOverridesPls"
repo = "qqrz997/KeepMyOverridesPls"
asset_patterns = ["KeepMyOverridesPls-*.zip"]
install_strategy = "bsipa-zip"
category = "gameplay"
+11
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+6
View File
@@ -0,0 +1,6 @@
id = "lookupid"
name = "LookupID"
repo = "Aeroluna/Heck"
asset_patterns = ["LookupID-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+9
View File
@@ -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" },
]
+10
View File
@@ -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" },
]
+10
View File
@@ -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" },
]
+16
View File
@@ -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" },
]
+6
View File
@@ -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"
+10
View File
@@ -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" },
]
+12
View File
@@ -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" },
]
+5
View File
@@ -0,0 +1,5 @@
id = "scoresabersharp"
name = "ScoreSaberSharp"
asset_patterns = ["ScoreSaberSharp-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+10
View File
@@ -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" },
]
+9
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+9
View File
@@ -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" },
]
+12
View File
@@ -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" },
]
+11
View File
@@ -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" },
]
+9
View File
@@ -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" },
]
@@ -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" },
]
@@ -0,0 +1,5 @@
id = "system-io-compression"
name = "System.IO.Compression"
asset_patterns = ["System.IO.Compression-*.zip"]
install_strategy = "bsipa-zip"
category = "library"
+12
View File
@@ -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" },
]
+6 -6
View File
@@ -106,7 +106,7 @@ def build_parser() -> argparse.ArgumentParser:
parents=[_common_parent()], parents=[_common_parent()],
) )
installed.add_argument("--instance", required=True) 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("--lockfile")
installed.add_argument("--json", action="store_true", help="Print full JSON output") installed.add_argument("--json", action="store_true", help="Print full JSON output")
@@ -116,7 +116,7 @@ def build_parser() -> argparse.ArgumentParser:
parents=[_common_parent()], parents=[_common_parent()],
) )
check.add_argument("--instance", required=True) 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("--lockfile")
check.add_argument("--json", action="store_true", help="Print full JSON check output") 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()], parents=[_common_parent()],
) )
bootstrap.add_argument("--instance", required=True) 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("--lockfile")
bootstrap.add_argument("--proton", help="Path to Proton executable (Linux/Proton installs)") 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") 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()], parents=[_common_parent()],
) )
updates.add_argument("--instance", required=True) 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("--lockfile")
updates.add_argument("--plugin", action="append", help="Check only this locked plugin id; repeatable") 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") 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()], parents=[_common_parent()],
) )
plan.add_argument("--instance", required=True) 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("--lockfile")
plan.add_argument("--plugin", "--update", action="append", help="Plan only this locked plugin id; repeatable") 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()], parents=[_common_parent()],
) )
enable.add_argument("--instance", required=True) 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("--lockfile")
enable.add_argument("plugin") enable.add_argument("plugin")
+40 -22
View File
@@ -58,33 +58,51 @@ def _load_toml(path: Path) -> dict[str, Any]:
return tomllib.load(handle) 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: def load_registry(path: Path) -> Registry:
if not path.exists(): 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() return Registry()
data = _load_toml(path)
plugins: dict[str, RegistryPlugin] = {} 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", []): for item in data.get("plugins", []):
dependencies = tuple( _add_registry_plugin(plugins, _registry_plugin_from_item(item, path), path)
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
return Registry(plugins) return Registry(plugins)
+2 -2
View File
@@ -35,7 +35,7 @@ def enable_disabled_plugin(
instance_path: Path, instance_path: Path,
state_root: Path, state_root: Path,
plugin_id: str, plugin_id: str,
registry: str = "registry/plugins.toml", registry: str = "registry/plugins",
lockfile: str | None = None, lockfile: str | None = None,
repo: Path | None = None, repo: Path | None = None,
progress: Callable[[str], None] | None = None, progress: Callable[[str], None] | None = None,
@@ -85,7 +85,7 @@ def enable_disabled_plugins(
instance_path: Path, instance_path: Path,
state_root: Path, state_root: Path,
plugin_ids: list[str], plugin_ids: list[str],
registry: str = "registry/plugins.toml", registry: str = "registry/plugins",
lockfile: str | None = None, lockfile: str | None = None,
repo: Path | None = None, repo: Path | None = None,
progress: Callable[[str], None] | None = None, progress: Callable[[str], None] | None = None,
+25 -1
View File
@@ -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) 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( def create_plan(
*, *,
instance: str, instance: str,
@@ -77,7 +97,11 @@ def create_plan(
selected: set[str] | None = None, selected: set[str] | None = None,
require_bootstrap: bool = True, require_bootstrap: bool = True,
) -> tuple[dict[str, Any], Path]: ) -> 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]] = [] changes: list[dict[str, Any]] = []
warnings: list[str] = [] warnings: list[str] = []
+1 -1
View File
@@ -269,7 +269,7 @@ class PluginHelperTui(App[int]):
lockfile = load_lockfile(self.repo_root / "locks" / f"{target.instance_name}.lock.toml") lockfile = load_lockfile(self.repo_root / "locks" / f"{target.instance_name}.lock.toml")
report = installed_plugins_report( report = installed_plugins_report(
installed_state=load_installed_state(target.state_root, target.instance_name), 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, lockfile=lockfile,
) )
self.plugin_rows = report["plugins"] self.plugin_rows = report["plugins"]
+137 -1
View File
@@ -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.fsutil import sha256_file
from plugin_helper.installer import apply_plan, disable_plugin, uninstall_plugin from plugin_helper.installer import apply_plan, disable_plugin, uninstall_plugin
from plugin_helper.instances import get_instance, list_instances 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.operations import enable_disabled_plugin
from plugin_helper.planner import create_plan from plugin_helper.planner import create_plan
from plugin_helper.scanner import scan_bootstrap_files, scan_instance from plugin_helper.scanner import scan_bootstrap_files, scan_instance
@@ -40,6 +40,35 @@ from plugin_helper.userdata import (
class PluginHelperTests(unittest.TestCase): 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: def test_normalize_beatmods_current_nested_response(self) -> None:
payload = { payload = {
"mods": [ "mods": [
@@ -872,6 +901,113 @@ sha256 = "{sha256_file(asset)}"
self.assertEqual(plan["changes"][0]["source"], str(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: def test_zip_member_cannot_escape_instance(self) -> None:
with tempfile.TemporaryDirectory() as tmp: with tempfile.TemporaryDirectory() as tmp:
work = Path(tmp) work = Path(tmp)