From 5f7d9c721cf99ac6434b05bb69536240372f0d9d Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 17 Sep 2026 18:05:58 -0600 Subject: [PATCH 1/2] Handle blank-line comment metadata in Control config masking --- .../control/BackendConfigurationService.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/control/BackendConfigurationService.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/control/BackendConfigurationService.java index 68b7a267c..d1671239f 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/control/BackendConfigurationService.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/control/BackendConfigurationService.java @@ -765,7 +765,7 @@ private static void removeRedactedCommentMetadata(YamlConfiguration source) { } private static List withoutRedactedComments(List comments) { - return comments.stream().filter(comment -> !comment.contains(REDACTED)).toList(); + return comments.stream().filter(comment -> comment == null || !comment.contains(REDACTED)).toList(); } private static String matchingKey(ConfigurationSection section, String expected, boolean ignoreCase) { @@ -876,6 +876,13 @@ private static List sanitizeComments(List comments, List List sanitized = new ArrayList<>(comments.size()); boolean redactContinuation = false; for (String original : comments) { + if (original == null) { + // Bukkit comment metadata uses null entries to preserve blank lines. + // Keep that structural marker instead of treating it as text. + sanitized.add(null); + redactContinuation = false; + continue; + } String comment = original; if (redactContinuation) { if (original.isBlank()) { @@ -961,7 +968,8 @@ private static Map> redactedCommentsByOwner(YamlConfigurati private static void addRedactedCommentOwner(Map> markers, String owner, List comments) { - List ownerMarkers = comments.stream().filter(comment -> comment.contains(REDACTED)).toList(); + List ownerMarkers = comments.stream() + .filter(comment -> comment != null && comment.contains(REDACTED)).toList(); if (!ownerMarkers.isEmpty()) markers.put(owner, ownerMarkers); } @@ -969,7 +977,7 @@ private static List restoreCommentSecrets(List proposed, List redactedCurrent) { for (int index = 0; index < redactedCurrent.size(); index++) { String redacted = redactedCurrent.get(index); - if (redacted.contains(REDACTED) + if (redacted != null && redacted.contains(REDACTED) && (index >= proposed.size() || !redacted.equals(proposed.get(index)))) { throw new IllegalArgumentException("redacted comment placeholders must not be edited or moved"); } @@ -977,7 +985,7 @@ private static List restoreCommentSecrets(List proposed, List restored = new ArrayList<>(proposed.size()); for (int index = 0; index < proposed.size(); index++) { String comment = proposed.get(index); - if (!comment.contains(REDACTED)) { + if (comment == null || !comment.contains(REDACTED)) { restored.add(comment); continue; } From 25b9b870c0c3d54980f6eedbe1b1e22663a11b52 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 17 Sep 2026 18:07:12 -0600 Subject: [PATCH 2/2] Reproduce Control apply with blank comment metadata --- .../BackendConfigurationServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/control/BackendConfigurationServiceTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/control/BackendConfigurationServiceTest.java index e144b26a5..99390a1d8 100644 --- a/VotingPlugin/src/test/java/com/bencodez/votingplugin/control/BackendConfigurationServiceTest.java +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/control/BackendConfigurationServiceTest.java @@ -746,6 +746,24 @@ class BackendConfigurationServiceTest { Map.of("method", "PLUGINMESSAGING"))); } + @Test void proxyMethodApplyPreservesBlankCommentMetadataWithoutRollingBack() throws Exception { + Path settings = directory.resolve("BungeeSettings.yml"); + Files.writeString(settings, "# Proxy settings\n#\n# Method selection\n" + + "UseBungeecord: true\nServer: server\nBungeeMethod: PLUGINMESSAGING\n" + + "PluginMessageChannel: vp:vp\nRedis:\n Host: localhost\n Port: 6379\n"); + BackendConfigurationService service = new BackendConfigurationService(directory, () -> { }); + BackendConfigurationService.QuickPreview preview = service.previewQuickSetup("proxy-method", + Map.of("method", "REDIS")); + + BackendConfigurationService.ApplyResult applied = service.applyQuickSetup("proxy-method", + Map.of("method", "REDIS"), preview.revision(), ignored -> { }); + + assertFalse(applied.rolledBack()); + assertTrue(Files.readString(settings).contains("BungeeMethod: REDIS")); + assertTrue(applied.document().content().contains("# Proxy settings")); + assertTrue(applied.document().content().contains("# Method selection")); + } + @Test void proxyMethodApplyUsesOnlyTheTargetedRuntimeAction() throws Exception { Path settings = directory.resolve("BungeeSettings.yml"); Files.writeString(settings, "UseBungeecord: true\nServer: lobby\nBungeeMethod: PLUGINMESSAGING\n"