Skip to content

Commit

Permalink
Improve CLI output name handling by adding file extensions (#2914)
Browse files Browse the repository at this point in the history
* FileExtensionHandler added + Tests  #2800

* solution for path problem #2800

* case: path without filename considered #2800

* CodeMaatImporter + CSVImporter fixed #2800

* RawTextParser + TokeiImporter fixed #2800

* minor refactoring to prevent files from being created while testing #2800

* pipeline fehler #2800

* write jsons in terminal for golden_test.sh #2800

* updated changes with review remarks #2800

* fix test #2800

* remove test boolean #2800

* remove comment, sysout variable
#2800

* refacotor OutputFileHandler.kt, adjust parsers
#2800

* refactor RawText Parser and adjust tests
#2800

* remove sysout from golden_test.sh
#2800

* Add tests to GitLogParser and SVNLogParser
#2800

* Refactor SVNLogParser.kt for linter correctness
#2800

* Fix file ending for CrococosmoImporter
#2800

* Fix path-separator not correctly added in OutputFileHandler
Refactor/simplify CrococosmoImporter, so it handles suffixes properly
Enhance tests for Crococosmo and MetricGardener
#2800

* Update CHANGELOG.md
#2800

* Fix EdgeFilter and MergeFilter not using the new OutputFileHandler
#2800

* Refactor a test for linter happiness
#2800

* Add a test for the EdgeFilter
#2800

* Refactor test for MergeFilter to JUnit
Add more tests for MergeFilter
#2800

* Fix StructureModifier not using new OutputFileHandler
Refactor all Importers/Parsers for more consistent line breaks
#2800

Co-authored-by: MW-Friedrich <108457762+MW-Friedrich@users.noreply.github.com>
Co-authored-by: ChristianSpa <cspahn@gmx.net>
  • Loading branch information
3 people committed Aug 17, 2022
1 parent 6d13754 commit e8d52b5
Show file tree
Hide file tree
Showing 39 changed files with 616 additions and 344 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/)

## [unreleased] (Added 🚀 | Changed | Removed 🗑 | Fixed 🐞 | Chore 👨‍💻 👩‍💻)

### Added 🚀

- Correct file types now get appended to the name of the output file when using the interactive ccsh [2914](https://github.com/MaibornWolff/codecharta/pull/2914)

## [1.103.6] - 2022-08-17

### Fixed 🐞
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package de.maibornwolff.codecharta.filter.edgefilter

import de.maibornwolff.codecharta.serialization.OutputFileHandler
import de.maibornwolff.codecharta.serialization.ProjectDeserializer
import de.maibornwolff.codecharta.serialization.ProjectSerializer
import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser
import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface
import picocli.CommandLine
import java.io.File
import java.io.PrintStream
import java.util.concurrent.Callable

@CommandLine.Command(
name = "edgefilter",
description = ["aggregtes edgeAttributes as nodeAttributes into a new cc.json file"],
description = ["aggregates edgeAttributes as nodeAttributes into a new cc.json file"],
footer = ["Copyright(c) 2022, MaibornWolff GmbH"]
)
class EdgeFilter : Callable<Void?>, InteractiveParser {
class EdgeFilter(
private val output: PrintStream = System.out
) : Callable<Void?>, InteractiveParser {

@CommandLine.Option(names = ["-h", "--help"], usageHelp = true, description = ["displays this help and exits"])
var help: Boolean = false
Expand All @@ -25,18 +29,24 @@ class EdgeFilter : Callable<Void?>, InteractiveParser {
private var pathSeparator = '/'

@CommandLine.Option(names = ["-o", "--output-file"], description = ["output File (or empty for stdout)"])
private var outputFile: File? = null
private var outputFile: String? = null

override fun call(): Void? {
val srcProject = ProjectDeserializer.deserializeProject(File(source).inputStream())

val newProject = EdgeProjectBuilder(srcProject, pathSeparator).merge()

val writer = outputFile?.bufferedWriter() ?: System.out.bufferedWriter()
ProjectSerializer.serializeProject(newProject, writer)
ProjectSerializer.serializeProject(newProject, OutputFileHandler.writer(outputFile ?: "", output))

return null
}

companion object {
@JvmStatic
fun main(args: Array<String>) {
CommandLine.call(EdgeFilter(), System.out, *args)
}
}

override fun getDialog(): ParserDialogInterface = ParserDialog
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.maibornwolff.codecharta.filter.edgefilter

import de.maibornwolff.codecharta.filter.edgefilter.EdgeFilter.Companion.main
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.io.File

class EdgeFilterTest {
@Test
fun `should create json uncompressed file`() {
main(
arrayOf(
"src/test/resources/coupling.json", "-o=src/test/resources/output"
)
)
val file = File("src/test/resources/output.cc.json")
file.deleteOnExit()

assertTrue(file.exists())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import com.github.kinquirer.components.promptInput
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import picocli.CommandLine
import java.io.File

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ParserDialogTest {
Expand All @@ -30,7 +28,8 @@ class ParserDialogTest {

val parserArguments = ParserDialog.collectParserArgs()

Assertions.assertThat(parserArguments).isEqualTo(listOf("sampleFile.cc.json", "--output-file=sampleOutputFile", "--path-separator=/"))
assertThat(parserArguments)
.isEqualTo(listOf("sampleFile.cc.json", "--output-file=sampleOutputFile", "--path-separator=/"))
}

@Test
Expand All @@ -43,7 +42,7 @@ class ParserDialogTest {
val parserArguments = ParserDialog.collectParserArgs()
val cmdLine = CommandLine(EdgeFilter())
val parseResult = cmdLine.parseArgs(*parserArguments.toTypedArray())
assertThat(parseResult.matchedOption("output-file").getValue<File>().name).isEqualTo("sampleOutputFile")
assertThat(parseResult.matchedOption("output-file").getValue<String>()).isEqualTo("sampleOutputFile")
assertThat(parseResult.matchedOption("path-separator").getValue<Char>()).isEqualTo('/')
assertThat(parseResult.matchedPositional(0).getValue<String>()).isEqualTo("sampleFile.cc.json")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package de.maibornwolff.codecharta.filter.mergefilter

import de.maibornwolff.codecharta.model.Project
import de.maibornwolff.codecharta.serialization.OutputFileHandler
import de.maibornwolff.codecharta.serialization.ProjectDeserializer
import de.maibornwolff.codecharta.serialization.ProjectSerializer
import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser
import de.maibornwolff.codecharta.tools.interactiveparser.ParserDialogInterface
import mu.KotlinLogging
import picocli.CommandLine
import java.io.File
import java.io.Writer
import java.io.PrintStream
import java.util.concurrent.Callable

@CommandLine.Command(
name = "merge",
description = ["merges multiple cc.json files"],
footer = ["Copyright(c) 2020, MaibornWolff GmbH"]
)
class MergeFilter : Callable<Void?>, InteractiveParser {
class MergeFilter(
private val output: PrintStream = System.out
) : Callable<Void?>, InteractiveParser {

@CommandLine.Option(names = ["-h", "--help"], usageHelp = true, description = ["displays this help and exits"])
var help: Boolean = false
Expand All @@ -34,7 +37,7 @@ class MergeFilter : Callable<Void?>, InteractiveParser {
private var leafStrategySet = false

@CommandLine.Option(names = ["-o", "--output-file"], description = ["output File (or empty for stdout)"])
private var outputFile: File? = null
private var outputFile: String? = null

@CommandLine.Option(names = ["-nc", "--not-compressed"], description = ["save uncompressed output File"])
private var compress = true
Expand Down Expand Up @@ -72,17 +75,19 @@ class MergeFilter : Callable<Void?>, InteractiveParser {

val mergedProject = ProjectMerger(srcProjects, nodeMergerStrategy).merge()

val filePath = outputFile?.absolutePath ?: "notSpecified"

if (compress && filePath != "notSpecified") ProjectSerializer.serializeAsCompressedFile(mergedProject, filePath) else ProjectSerializer.serializeProject(mergedProject, writer())
val filePath = outputFile ?: "notSpecified"
if (compress && filePath != "notSpecified") {
ProjectSerializer.serializeAsCompressedFile(
mergedProject,
filePath
)
} else {
ProjectSerializer.serializeProject(mergedProject, OutputFileHandler.writer(outputFile ?: "", output))
}

return null
}

private fun writer(): Writer {
return outputFile?.bufferedWriter() ?: System.out.bufferedWriter()
}

private fun getFilesInFolder(folder: File): List<File> {
val files = folder.walk().filter { !it.name.startsWith(".") && !it.isDirectory }
return files.toList()
Expand All @@ -95,6 +100,11 @@ class MergeFilter : Callable<Void?>, InteractiveParser {
RecursiveNodeMergerStrategy(false)
).merge()
}

@JvmStatic
fun main(args: Array<String>) {
CommandLine.call(MergeFilter(), System.out, *args)
}
}

override fun getDialog(): ParserDialogInterface = ParserDialog
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,85 @@
package de.maibornwolff.codecharta.filter.mergefilter

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.containsString
import org.hamcrest.Matchers.not
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import de.maibornwolff.codecharta.filter.mergefilter.MergeFilter.Companion.main
import org.hamcrest.MatcherAssert
import org.hamcrest.Matchers
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import picocli.CommandLine
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream

class MergeFilterTest : Spek({
class MergeFilterTest {
private val mergeFilter = MergeFilter()
val outContent = ByteArrayOutputStream()
val originalOut = System.out
val errContent = ByteArrayOutputStream()
val originalErr = System.err
describe("merge filter test") {

context("merging a folder") {
val projectLocation = "src/test/resources/mergeFolderTest"
val valueInFile1 = "SourceMonCsvConverterTest.java"
val valueInFile2 = "SourceMonCsvConverter.java"
val invalidFile = "invalid.json"

System.setOut(PrintStream(outContent))
System.setErr(PrintStream(errContent))
CommandLine(MergeFilter()).execute(projectLocation).toString()
System.setOut(originalOut)
System.setErr(originalErr)

it("should ignore files starting with a dot") {
assertThat(outContent.toString(), not(containsString("ShouldNotAppear.java")))
}

it("should merge all valid projects in folder") {
assertThat(outContent.toString(), containsString(valueInFile1))
assertThat(outContent.toString(), containsString(valueInFile2))
}

it("should warn about skipped files") {
assertThat(errContent.toString(), containsString(invalidFile))
}
}

context("merging files") {
System.setOut(PrintStream(outContent))
CommandLine(MergeFilter()).execute(
"src/test/resources/mergeFolderTest/file1.cc.json", "src/test/resources/mergeFolderTest/file2.cc.json"
).toString()
System.setOut(originalOut)
val valueInFile1 = "SourceMonCsvConverterTest.java"
val valueInFile2 = "SourceMonCsvConverter.java"

it("should merge all indicated files") {
assertThat(outContent.toString(), containsString(valueInFile1))
assertThat(outContent.toString(), containsString(valueInFile2))
}
}

@Test
fun `should merge all files in a folder correctly`() {
val projectLocation = "src/test/resources/mergeFolderTest"
val valueInFile1 = "SourceMonCsvConverterTest.java"
val valueInFile2 = "SourceMonCsvConverter.java"
val invalidFile = "invalid.json"

System.setOut(PrintStream(outContent))
System.setErr(PrintStream(errContent))
CommandLine(MergeFilter()).execute(projectLocation).toString()
System.setOut(originalOut)
System.setErr(originalErr)

// should ignore files starting with a dot
MatcherAssert.assertThat(outContent.toString(), Matchers.not(Matchers.containsString("ShouldNotAppear.java")))

// should merge all valid projects in folder
MatcherAssert.assertThat(outContent.toString(), Matchers.containsString(valueInFile1))
MatcherAssert.assertThat(outContent.toString(), Matchers.containsString(valueInFile2))

// should warn about skipped files
MatcherAssert.assertThat(errContent.toString(), Matchers.containsString(invalidFile))
}

@Test
fun `should merge all indicated files`() {
System.setOut(PrintStream(outContent))
CommandLine(MergeFilter()).execute(
"src/test/resources/mergeFolderTest/file1.cc.json", "src/test/resources/mergeFolderTest/file2.cc.json"
).toString()
System.setOut(originalOut)
val valueInFile1 = "SourceMonCsvConverterTest.java"
val valueInFile2 = "SourceMonCsvConverter.java"

MatcherAssert.assertThat(outContent.toString(), Matchers.containsString(valueInFile1))
MatcherAssert.assertThat(outContent.toString(), Matchers.containsString(valueInFile2))
}

@Test
fun `should create json uncompressed file`() {
main(
arrayOf(
"src/test/resources/test.json", "src/test/resources/test2.json", "-nc",
"-o=src/test/resources/output"
)
)
val file = File("src/test/resources/output.cc.json")
file.deleteOnExit()

Assertions.assertTrue(file.exists())
}

@Test
fun `should create json gzip file`() {
main(
arrayOf(
"src/test/resources/test.json", "src/test/resources/test2.json",
"-o=src/test/resources/output"
)
)
val file = File("src/test/resources/output.cc.json.gz")
file.deleteOnExit()

Assertions.assertTrue(file.exists())
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ class ParserDialogTest {

val commandLine = CommandLine(MergeFilter())
val parseResult = commandLine.parseArgs(*parserArguments.toTypedArray())
assertThat(parseResult.matchedPositional(0).getValue<Array<File>>().map { it.name }).isEqualTo(listOf(inputFolderName))
assertThat(parseResult.matchedOption("output-file").getValue<File>().name).isEqualTo(outputFileName)
assertThat(parseResult.matchedPositional(0).getValue<Array<File>>().map { it.name }).isEqualTo(
listOf(
inputFolderName
)
)
assertThat(parseResult.matchedOption("output-file").getValue<String>()).isEqualTo(outputFileName)
assertThat(parseResult.matchedOption("not-compressed").getValue<Boolean>()).isEqualTo(compress)
assertThat(parseResult.matchedOption("add-missing").getValue<Boolean>()).isEqualTo(addMissing)
assertThat(parseResult.matchedOption("recursive").getValue<Boolean>()).isEqualTo(recursive)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.maibornwolff.codecharta.filter.structuremodifier

import de.maibornwolff.codecharta.model.Project
import de.maibornwolff.codecharta.serialization.OutputFileHandler
import de.maibornwolff.codecharta.serialization.ProjectDeserializer
import de.maibornwolff.codecharta.serialization.ProjectSerializer
import de.maibornwolff.codecharta.tools.interactiveparser.InteractiveParser
Expand Down Expand Up @@ -32,11 +33,15 @@ class StructureModifier(
@CommandLine.Option(names = ["-s", "--set-root"], description = ["path within project to be extracted"])
private var setRoot: String? = null

@CommandLine.Option(arity = "1", names = ["-p", "--print-levels"], description = ["show first x layers of project hierarchy"])
@CommandLine.Option(
arity = "1",
names = ["-p", "--print-levels"],
description = ["show first x layers of project hierarchy"]
)
private var printLevels: Int = 0

@CommandLine.Option(names = ["-o", "--output-file"], description = ["output File (or empty for stdout)"])
private var outputFile: File? = null
private var outputFile: String? = null

@CommandLine.Option(names = ["-f", "--move-from"], description = ["move nodes in project folder..."])
private var moveFrom: String? = null
Expand All @@ -59,13 +64,13 @@ class StructureModifier(
ProjectStructurePrinter(project, output).printProjectStructure(printLevels)
return null
}

setRoot != null -> project = SubProjectExtractor(project).extract(setRoot!!)
remove.isNotEmpty() -> project = NodeRemover(project).remove(remove)
moveFrom != null -> project = FolderMover(project).move(moveFrom, moveTo) ?: return null
}

val writer = outputFile?.bufferedWriter() ?: output.bufferedWriter()
ProjectSerializer.serializeProject(project, writer)
ProjectSerializer.serializeProject(project, OutputFileHandler.writer(outputFile ?: "", output))

return null
}
Expand Down

0 comments on commit e8d52b5

Please sign in to comment.