-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reject version for FixedCommand if same or older than any affected ve…
…rsion (#728) Check can be skipped by adding ` force` suffix to the command.
- Loading branch information
1 parent
7df93d8
commit e6c0902
Showing
11 changed files
with
220 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 19 additions & 11 deletions
30
src/main/kotlin/io/github/mojira/arisa/modules/commands/FixedCommand.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,34 @@ | ||
package io.github.mojira.arisa.modules.commands | ||
|
||
import io.github.mojira.arisa.domain.Issue | ||
import java.time.Instant | ||
|
||
class FixedCommand { | ||
@Suppress("ThrowsCount") | ||
operator fun invoke(issue: Issue, version: String): Int { | ||
if (issue.fixVersions.any { it.name == version }) { | ||
throw CommandExceptions.ALREADY_FIXED_IN.create(version) | ||
} | ||
if (issue.project.versions.none { it.name == version }) { | ||
throw CommandExceptions.NO_SUCH_VERSION.create(version) | ||
operator fun invoke(issue: Issue, fixVersionName: String, force: Boolean): Int { | ||
if (issue.fixVersions.any { it.name == fixVersionName }) { | ||
throw CommandExceptions.ALREADY_FIXED_IN.create(fixVersionName) | ||
} | ||
|
||
val fixVersion = issue.project.versions.firstOrNull { it.name == fixVersionName } | ||
?: throw CommandExceptions.NO_SUCH_VERSION.create(fixVersionName) | ||
|
||
if (issue.resolution !in listOf(null, "", "Unresolved")) { | ||
throw CommandExceptions.ALREADY_RESOLVED.create(issue.resolution) | ||
} | ||
if (issue.affectedVersions.first().releaseDate!!.isAfter( | ||
issue.project.versions.first { it.name == version }.releaseDate | ||
)) { | ||
throw CommandExceptions.FIX_VERSION_BEFORE_FIRST_AFFECTED_VERSION.create(version) | ||
|
||
if (!force) { | ||
// Fail if any affected version is same or newer than fix version | ||
// Since archived fix versions cannot be removed again this prevents accidentally adding an incorrect | ||
// fix version | ||
issue.affectedVersions.firstOrNull { it.releaseDate!!.isSameOrAfter(fixVersion.releaseDate!!) }?.let { | ||
throw CommandExceptions.FIX_VERSION_SAME_OR_BEFORE_AFFECTED_VERSION.create(fixVersionName, it.name) | ||
} | ||
} | ||
|
||
issue.markAsFixedWithSpecificVersion(version) | ||
issue.markAsFixedWithSpecificVersion(fixVersionName) | ||
return 1 | ||
} | ||
} | ||
|
||
private fun Instant.isSameOrAfter(other: Instant) = !this.isBefore(other) |
41 changes: 41 additions & 0 deletions
41
...ithub/mojira/arisa/modules/commands/arguments/GreedyStringWithTrailingFlagArgumentType.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package io.github.mojira.arisa.modules.commands.arguments | ||
|
||
import com.mojang.brigadier.StringReader | ||
import com.mojang.brigadier.arguments.ArgumentType | ||
import io.github.mojira.arisa.modules.commands.CommandExceptions | ||
|
||
/** | ||
* Similar to [com.mojang.brigadier.arguments.StringArgumentType.greedyString], except that the string | ||
* may end with an optional flag separated by a space. | ||
*/ | ||
fun greedyStringWithFlag(flag: String): ArgumentType<StringWithFlag> = GreedyStringWithTrailingFlagArgumentType(flag) | ||
|
||
private class GreedyStringWithTrailingFlagArgumentType(private val flag: String) : ArgumentType<StringWithFlag> { | ||
private val flagSuffix = " $flag" | ||
|
||
override fun parse(reader: StringReader): StringWithFlag { | ||
var text = reader.remaining | ||
|
||
// Throw exception when input consists only of flag, to prevent accidental incorrect usage | ||
if (text == flag) { | ||
throw CommandExceptions.GREEDY_STRING_ONLY_FLAG.createWithContext(reader, flag) | ||
} | ||
|
||
// Consume complete input | ||
reader.cursor = reader.totalLength | ||
|
||
var isFlagSet = false | ||
if (text.endsWith(flagSuffix)) { | ||
text = text.removeSuffix(flagSuffix) | ||
isFlagSet = true | ||
} | ||
|
||
return StringWithFlag(text, isFlagSet) | ||
} | ||
} | ||
|
||
data class StringWithFlag( | ||
val string: String, | ||
/** `true` if the flag was explicitly provided in the command */ | ||
val isFlagSet: Boolean | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
...b/mojira/arisa/modules/commands/arguments/GreedyStringWithTrailingFlagArgumentTypeTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package io.github.mojira.arisa.modules.commands.arguments | ||
|
||
import com.mojang.brigadier.StringReader | ||
import com.mojang.brigadier.exceptions.CommandSyntaxException | ||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class GreedyStringWithTrailingFlagArgumentTypeTest : StringSpec({ | ||
val flag = "my-flag" | ||
val argumentType = greedyStringWithFlag(flag) | ||
|
||
"should work without flag" { | ||
val reader = StringReader("some text") | ||
val result = argumentType.parse(reader) | ||
result shouldBe StringWithFlag( | ||
"some text", | ||
false | ||
) | ||
reader.remainingLength shouldBe 0 | ||
} | ||
|
||
"should work with flag" { | ||
val reader = StringReader("some text $flag") | ||
val result = argumentType.parse(reader) | ||
result shouldBe StringWithFlag( | ||
"some text", | ||
true | ||
) | ||
reader.remainingLength shouldBe 0 | ||
} | ||
|
||
"should not detect as flag without space" { | ||
val reader = StringReader("some text$flag") | ||
val result = argumentType.parse(reader) | ||
result shouldBe StringWithFlag( | ||
"some text$flag", | ||
false | ||
) | ||
reader.remainingLength shouldBe 0 | ||
} | ||
|
||
"should work with empty text and flag" { | ||
val reader = StringReader(" $flag") | ||
val result = argumentType.parse(reader) | ||
result shouldBe StringWithFlag( | ||
"", | ||
true | ||
) | ||
reader.remainingLength shouldBe 0 | ||
} | ||
|
||
"should fail when only flag is used" { | ||
val reader = StringReader(flag) | ||
val exception = shouldThrow<CommandSyntaxException> { | ||
argumentType.parse(reader) | ||
} | ||
exception.message shouldBe "Argument consists only of flag 'my-flag' but does not contain a string at position 0: <--[HERE]" | ||
|
||
// Cursor should not have been changed | ||
reader.cursor shouldBe 0 | ||
} | ||
}) |
Oops, something went wrong.