Minor: reformat and fix warnings in internal package
This commit is contained in:
@@ -54,8 +54,7 @@ sealed class BytecodeGenerationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class KotlinBytecodeToolWindow(private val myProject: Project, private val toolWindow: ToolWindow) : JPanel(BorderLayout()), Disposable {
|
class KotlinBytecodeToolWindow(private val myProject: Project, private val toolWindow: ToolWindow) : JPanel(BorderLayout()), Disposable {
|
||||||
private val LOG = Logger.getInstance(KotlinBytecodeToolWindow::class.java)
|
@Suppress("JoinDeclarationAndAssignment")
|
||||||
|
|
||||||
private val myEditor: Editor
|
private val myEditor: Editor
|
||||||
private val enableInline: JCheckBox
|
private val enableInline: JCheckBox
|
||||||
private val enableOptimization: JCheckBox
|
private val enableOptimization: JCheckBox
|
||||||
@@ -166,7 +165,6 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
myEditor = EditorFactory.getInstance().createEditor(
|
myEditor = EditorFactory.getInstance().createEditor(
|
||||||
EditorFactory.getInstance().createDocument(""), myProject, JavaFileType.INSTANCE, true
|
EditorFactory.getInstance().createDocument(""), myProject, JavaFileType.INSTANCE, true
|
||||||
)
|
)
|
||||||
@@ -223,9 +221,10 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val LOG = Logger.getInstance(KotlinBytecodeToolWindow::class.java)
|
||||||
|
|
||||||
private val UPDATE_DELAY = 1000
|
private const val UPDATE_DELAY = 1000
|
||||||
private val DEFAULT_TEXT = "/*\n" +
|
private const val DEFAULT_TEXT = "/*\n" +
|
||||||
"Generated bytecode for Kotlin source file.\n" +
|
"Generated bytecode for Kotlin source file.\n" +
|
||||||
"No Kotlin source file is opened.\n" +
|
"No Kotlin source file is opened.\n" +
|
||||||
"*/"
|
"*/"
|
||||||
@@ -283,7 +282,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
)
|
)
|
||||||
|
|
||||||
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
|
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
|
||||||
override fun shouldGeneratePackagePart(file: KtFile): Boolean {
|
override fun shouldGeneratePackagePart(@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") file: KtFile): Boolean {
|
||||||
return file === ktFile
|
return file === ktFile
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +318,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun mapLines(text: String, startLine: Int, endLine: Int): Pair<Int, Int> {
|
private fun mapLines(text: String, startLine: Int, endLine: Int): Pair<Int, Int> {
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
var startLine = startLine
|
var startLine = startLine
|
||||||
var byteCodeLine = 0
|
var byteCodeLine = 0
|
||||||
var byteCodeStartLine = -1
|
var byteCodeStartLine = -1
|
||||||
@@ -331,7 +331,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
lines.add(ktLineNum)
|
lines.add(ktLineNum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(lines)
|
lines.sort()
|
||||||
|
|
||||||
for (line in lines) {
|
for (line in lines) {
|
||||||
if (line >= startLine) {
|
if (line >= startLine) {
|
||||||
|
|||||||
+14
-17
@@ -35,7 +35,6 @@ import java.util.jar.Manifest
|
|||||||
|
|
||||||
class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
||||||
override fun decompile(file: KtFile): String? {
|
override fun decompile(file: KtFile): String? {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val bytecodeMap = when {
|
val bytecodeMap = when {
|
||||||
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
|
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
|
||||||
@@ -44,11 +43,10 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
val resultSaver = KotlinResultSaver()
|
val resultSaver = KotlinResultSaver()
|
||||||
val options = hashMapOf<String, Any>(
|
val options = hashMapOf<String, Any>(
|
||||||
IFernflowerPreferences.REMOVE_BRIDGE to "0"
|
IFernflowerPreferences.REMOVE_BRIDGE to "0"
|
||||||
)
|
)
|
||||||
|
|
||||||
val bytecodeProvider = IBytecodeProvider {
|
val bytecodeProvider = IBytecodeProvider { externalPath, _ ->
|
||||||
externalPath, _ ->
|
|
||||||
val path = File(FileUtil.toSystemIndependentName(externalPath))
|
val path = File(FileUtil.toSystemIndependentName(externalPath))
|
||||||
bytecodeMap[path]?.invoke()
|
bytecodeMap[path]?.invoke()
|
||||||
}
|
}
|
||||||
@@ -59,8 +57,7 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
decompiler.decompileContext()
|
decompiler.decompileContext()
|
||||||
return resultSaver.resultText
|
return resultSaver.resultText
|
||||||
}
|
} catch (ex: IdeaLogger.InternalException) {
|
||||||
catch (ex: IdeaLogger.InternalException) {
|
|
||||||
throw DecompileFailedException(ex.message ?: "Unknown error", ex)
|
throw DecompileFailedException(ex.message ?: "Unknown error", ex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,10 +65,10 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
private fun bytecodeMapForExistingClassfile(file: VirtualFile): Map<File, () -> ByteArray> {
|
private fun bytecodeMapForExistingClassfile(file: VirtualFile): Map<File, () -> ByteArray> {
|
||||||
val mask = "${file.nameWithoutExtension}$"
|
val mask = "${file.nameWithoutExtension}$"
|
||||||
val files =
|
val files =
|
||||||
mapOf(file.path to file) +
|
mapOf(file.path to file) +
|
||||||
file.parent.children.filter {
|
file.parent.children.filter {
|
||||||
it.nameWithoutExtension.startsWith(mask) && it.fileType === StdFileTypes.CLASS
|
it.nameWithoutExtension.startsWith(mask) && it.fileType === StdFileTypes.CLASS
|
||||||
}.map { it.path to it }
|
}.map { it.path to it }
|
||||||
|
|
||||||
return files.entries.associate {
|
return files.entries.associate {
|
||||||
Pair(File(it.key), { it.value.contentsToByteArray(false) })
|
Pair(File(it.key), { it.value.contentsToByteArray(false) })
|
||||||
@@ -105,13 +102,13 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveFolder(path: String?) { }
|
override fun saveFolder(path: String?) {}
|
||||||
|
|
||||||
override fun closeArchive(path: String?, archiveName: String?) { }
|
override fun closeArchive(path: String?, archiveName: String?) {}
|
||||||
|
|
||||||
override fun copyEntry(source: String?, path: String?, archiveName: String?, entry: String?) { }
|
override fun copyEntry(source: String?, path: String?, archiveName: String?, entry: String?) {}
|
||||||
|
|
||||||
override fun createArchive(path: String?, archiveName: String?, manifest: Manifest?) { }
|
override fun createArchive(path: String?, archiveName: String?, manifest: Manifest?) {}
|
||||||
|
|
||||||
override fun saveClassFile(path: String?, qualifiedName: String?, entryName: String?, content: String?, mapping: IntArray?) {
|
override fun saveClassFile(path: String?, qualifiedName: String?, entryName: String?, content: String?, mapping: IntArray?) {
|
||||||
if (entryName != null && content != null) {
|
if (entryName != null && content != null) {
|
||||||
@@ -119,11 +116,11 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copyFile(source: String?, path: String?, entryName: String?) { }
|
override fun copyFile(source: String?, path: String?, entryName: String?) {}
|
||||||
|
|
||||||
override fun saveClassEntry(path: String?, archiveName: String?, qualifiedName: String?, entryName: String?, content: String?) { }
|
override fun saveClassEntry(path: String?, archiveName: String?, qualifiedName: String?, entryName: String?, content: String?) {}
|
||||||
|
|
||||||
override fun saveDirEntry(path: String?, archiveName: String?, entryName: String?) { }
|
override fun saveDirEntry(path: String?, archiveName: String?, entryName: String?) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+14
-17
@@ -35,7 +35,6 @@ import java.util.jar.Manifest
|
|||||||
|
|
||||||
class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
||||||
override fun decompile(file: KtFile): String? {
|
override fun decompile(file: KtFile): String? {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val bytecodeMap = when {
|
val bytecodeMap = when {
|
||||||
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
|
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
|
||||||
@@ -44,11 +43,10 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
val resultSaver = KotlinResultSaver()
|
val resultSaver = KotlinResultSaver()
|
||||||
val options = hashMapOf<String, Any>(
|
val options = hashMapOf<String, Any>(
|
||||||
IFernflowerPreferences.REMOVE_BRIDGE to "0"
|
IFernflowerPreferences.REMOVE_BRIDGE to "0"
|
||||||
)
|
)
|
||||||
|
|
||||||
val bytecodeProvider = IBytecodeProvider {
|
val bytecodeProvider = IBytecodeProvider { externalPath, _ ->
|
||||||
externalPath, _ ->
|
|
||||||
val path = File(FileUtil.toSystemIndependentName(externalPath))
|
val path = File(FileUtil.toSystemIndependentName(externalPath))
|
||||||
bytecodeMap[path]?.invoke()
|
bytecodeMap[path]?.invoke()
|
||||||
}
|
}
|
||||||
@@ -59,8 +57,7 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
decompiler.decompileContext()
|
decompiler.decompileContext()
|
||||||
return resultSaver.resultText
|
return resultSaver.resultText
|
||||||
}
|
} catch (ex: IdeaLogger.InternalException) {
|
||||||
catch (ex: IdeaLogger.InternalException) {
|
|
||||||
throw DecompileFailedException(ex.message ?: "Unknown error", ex)
|
throw DecompileFailedException(ex.message ?: "Unknown error", ex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,10 +65,10 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
private fun bytecodeMapForExistingClassfile(file: VirtualFile): Map<File, () -> ByteArray> {
|
private fun bytecodeMapForExistingClassfile(file: VirtualFile): Map<File, () -> ByteArray> {
|
||||||
val mask = "${file.nameWithoutExtension}$"
|
val mask = "${file.nameWithoutExtension}$"
|
||||||
val files =
|
val files =
|
||||||
mapOf(file.path to file) +
|
mapOf(file.path to file) +
|
||||||
file.parent.children.filter {
|
file.parent.children.filter {
|
||||||
it.nameWithoutExtension.startsWith(mask) && it.fileType === StdFileTypes.CLASS
|
it.nameWithoutExtension.startsWith(mask) && it.fileType === StdFileTypes.CLASS
|
||||||
}.map { it.path to it }
|
}.map { it.path to it }
|
||||||
|
|
||||||
return files.entries.associate {
|
return files.entries.associate {
|
||||||
Pair(File(it.key), { it.value.contentsToByteArray(false) })
|
Pair(File(it.key), { it.value.contentsToByteArray(false) })
|
||||||
@@ -105,13 +102,13 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveFolder(path: String?) { }
|
override fun saveFolder(path: String?) {}
|
||||||
|
|
||||||
override fun closeArchive(path: String?, archiveName: String?) { }
|
override fun closeArchive(path: String?, archiveName: String?) {}
|
||||||
|
|
||||||
override fun copyEntry(source: String?, path: String?, archiveName: String?, entry: String?) { }
|
override fun copyEntry(source: String?, path: String?, archiveName: String?, entry: String?) {}
|
||||||
|
|
||||||
override fun createArchive(path: String?, archiveName: String?, manifest: Manifest?) { }
|
override fun createArchive(path: String?, archiveName: String?, manifest: Manifest?) {}
|
||||||
|
|
||||||
override fun saveClassFile(path: String?, qualifiedName: String?, entryName: String?, content: String?, mapping: IntArray?) {
|
override fun saveClassFile(path: String?, qualifiedName: String?, entryName: String?, content: String?, mapping: IntArray?) {
|
||||||
if (entryName != null && content != null) {
|
if (entryName != null && content != null) {
|
||||||
@@ -119,11 +116,11 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copyFile(source: String?, path: String?, entryName: String?) { }
|
override fun copyFile(source: String?, path: String?, entryName: String?) {}
|
||||||
|
|
||||||
override fun saveClassEntry(path: String?, archiveName: String?, qualifiedName: String?, entryName: String?, content: String?) { }
|
override fun saveClassEntry(path: String?, archiveName: String?, qualifiedName: String?, entryName: String?, content: String?) {}
|
||||||
|
|
||||||
override fun saveDirEntry(path: String?, archiveName: String?, entryName: String?) { }
|
override fun saveDirEntry(path: String?, archiveName: String?, entryName: String?) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+43
-36
@@ -39,15 +39,15 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging Kotlin incremental compilation") {
|
class CreateIncrementalCompilationBackup : AnAction("Create backup for debugging Kotlin incremental compilation") {
|
||||||
companion object {
|
companion object {
|
||||||
val BACKUP_DIR_NAME = ".backup"
|
const val BACKUP_DIR_NAME = ".backup"
|
||||||
val PATCHES_TO_CREATE = 5
|
const val PATCHES_TO_CREATE = 5
|
||||||
|
|
||||||
val PATCHES_FRACTION = .25
|
const val PATCHES_FRACTION = .25
|
||||||
val LOGS_FRACTION = .05
|
const val LOGS_FRACTION = .05
|
||||||
val PROJECT_SYSTEM_FRACTION = .05
|
const val PROJECT_SYSTEM_FRACTION = .05
|
||||||
val ZIP_FRACTION = 1.0 - PATCHES_FRACTION - LOGS_FRACTION - PROJECT_SYSTEM_FRACTION
|
const val ZIP_FRACTION = 1.0 - PATCHES_FRACTION - LOGS_FRACTION - PROJECT_SYSTEM_FRACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
@@ -56,15 +56,15 @@ class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging
|
|||||||
val backupDir = File(FileUtil.createTempDirectory("makeBackup", null), BACKUP_DIR_NAME)
|
val backupDir = File(FileUtil.createTempDirectory("makeBackup", null), BACKUP_DIR_NAME)
|
||||||
|
|
||||||
ProgressManager.getInstance().run(
|
ProgressManager.getInstance().run(
|
||||||
object : Task.Backgroundable(project, "Creating backup for debugging Kotlin incremental compilation", true) {
|
object : Task.Backgroundable(project, "Creating backup for debugging Kotlin incremental compilation", true) {
|
||||||
override fun run(indicator: ProgressIndicator) {
|
override fun run(indicator: ProgressIndicator) {
|
||||||
createPatches(backupDir, project, indicator)
|
createPatches(backupDir, project, indicator)
|
||||||
copyLogs(backupDir, indicator)
|
copyLogs(backupDir, indicator)
|
||||||
copyProjectSystemDir(backupDir, project, indicator)
|
copyProjectSystemDir(backupDir, project, indicator)
|
||||||
|
|
||||||
zipProjectDir(backupDir, project, projectBaseDir, indicator)
|
zipProjectDir(backupDir, project, projectBaseDir, indicator)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,13 @@ class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging
|
|||||||
val gateway = localHistoryImpl.gateway!!
|
val gateway = localHistoryImpl.gateway!!
|
||||||
val localHistoryFacade = localHistoryImpl.facade
|
val localHistoryFacade = localHistoryImpl.facade
|
||||||
|
|
||||||
val revisionsCollector = RevisionsCollector(localHistoryFacade, gateway.createTransientRootEntry(), project.baseDir!!.path, project.locationHash, null)
|
val revisionsCollector = RevisionsCollector(
|
||||||
|
localHistoryFacade,
|
||||||
|
gateway.createTransientRootEntry(),
|
||||||
|
project.baseDir!!.path,
|
||||||
|
project.locationHash,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
var patchesCreated = 0
|
var patchesCreated = 0
|
||||||
|
|
||||||
@@ -91,8 +97,7 @@ class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging
|
|||||||
indicator.fraction = PATCHES_FRACTION * patchesCreated / PATCHES_TO_CREATE
|
indicator.fraction = PATCHES_FRACTION * patchesCreated / PATCHES_TO_CREATE
|
||||||
|
|
||||||
val differences = revisions[0].getDifferencesWith(rev)!!
|
val differences = revisions[0].getDifferencesWith(rev)!!
|
||||||
val changes = differences.map {
|
val changes = differences.map { d ->
|
||||||
d ->
|
|
||||||
Change(d.getLeftContentRevision(gateway), d.getRightContentRevision(gateway))
|
Change(d.getLeftContentRevision(gateway), d.getRightContentRevision(gateway))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,24 +139,24 @@ class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging
|
|||||||
|
|
||||||
for (dir in listOf(projectDir, backupDir.parentFile!!)) {
|
for (dir in listOf(projectDir, backupDir.parentFile!!)) {
|
||||||
FileUtil.processFilesRecursively(
|
FileUtil.processFilesRecursively(
|
||||||
dir,
|
dir,
|
||||||
/*processor*/ {
|
/*processor*/ {
|
||||||
if (it!!.isFile
|
if (it!!.isFile
|
||||||
&& !it.name.endsWith(".hprof")
|
&& !it.name.endsWith(".hprof")
|
||||||
&& !(it.name.startsWith("make_backup_") && it.name.endsWith(".zip"))
|
&& !(it.name.startsWith("make_backup_") && it.name.endsWith(".zip"))
|
||||||
) {
|
) {
|
||||||
|
|
||||||
indicator.text = "Scanning project dir: $it"
|
indicator.text = "Scanning project dir: $it"
|
||||||
|
|
||||||
files.add(Pair(it, FileUtil.getRelativePath(dir, it)!!))
|
files.add(Pair(it, FileUtil.getRelativePath(dir, it)!!))
|
||||||
totalBytes += it.length()
|
totalBytes += it.length()
|
||||||
}
|
|
||||||
true
|
|
||||||
},
|
|
||||||
/*directoryFilter*/ {
|
|
||||||
val name = it!!.name
|
|
||||||
name != ".git" && name != "out"
|
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
},
|
||||||
|
/*directoryFilter*/ {
|
||||||
|
val name = it!!.name
|
||||||
|
name != ".git" && name != "out"
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,14 +181,16 @@ class CreateIncrementalCompilationBackup: AnAction("Create backup for debugging
|
|||||||
|
|
||||||
FileUtil.delete(backupDir)
|
FileUtil.delete(backupDir)
|
||||||
|
|
||||||
WaitForProgressToShow.runOrInvokeLaterAboveProgress({
|
WaitForProgressToShow.runOrInvokeLaterAboveProgress(
|
||||||
ShowFilePathAction.showDialog(
|
{
|
||||||
|
ShowFilePathAction.showDialog(
|
||||||
project,
|
project,
|
||||||
"Successfully created backup " + backupFile.absolutePath,
|
"Successfully created backup " + backupFile.absolutePath,
|
||||||
"Created backup",
|
"Created backup",
|
||||||
backupFile,
|
backupFile,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}, null, project)
|
}, null, project
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -26,7 +26,7 @@ val random = Random()
|
|||||||
|
|
||||||
val HISTORY_LABEL_KEY = Key.create<String>("history label")
|
val HISTORY_LABEL_KEY = Key.create<String>("history label")
|
||||||
|
|
||||||
class MakeBackupCompileTask: CompileTask {
|
class MakeBackupCompileTask : CompileTask {
|
||||||
override fun execute(context: CompileContext?): Boolean {
|
override fun execute(context: CompileContext?): Boolean {
|
||||||
val project = context!!.project!!
|
val project = context!!.project!!
|
||||||
|
|
||||||
@@ -38,5 +38,4 @@ class MakeBackupCompileTask: CompileTask {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.internal.makeBackup
|
package org.jetbrains.kotlin.idea.internal.makeBackup
|
||||||
|
|
||||||
val HISTORY_LABEL_PREFIX = "build started "
|
const val HISTORY_LABEL_PREFIX = "build started "
|
||||||
|
|||||||
Reference in New Issue
Block a user