Skip to content

Commit 632f179

Browse files
authored
Merge pull request #436 from codacy/duplication-tools-api
feature: Use duplication tools from API
2 parents 85f36e3 + ff684cc commit 632f179

28 files changed

Lines changed: 398 additions & 260 deletions

File tree

.circleci/config.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ references:
8989
webhook: https://hooks.slack.com/services/$SLACK_TOKEN
9090
failure_message: ":red_circle: A $CIRCLE_JOB job has failed! See more on: $RP_LAUNCH_URL, login with the default user."
9191

92+
cache_prefix: &cache_prefix sbt-cache-31012022
93+
9294
jobs:
9395
maven_dependencies:
9496
docker:
@@ -144,35 +146,39 @@ workflows:
144146
write_sbt_version: true
145147
- codacy/sbt:
146148
name: compile
147-
install_sbt_version: 1.3.12
149+
install_sbt_version: 1.6.1
148150
cmd: sbt coverage +test:compile
151+
cache_prefix: *cache_prefix
149152
persist_to_workspace: true
150153
requires:
151154
- codacy/checkout_and_version
152155
- codacy/sbt:
153156
name: lint
154-
install_sbt_version: 1.3.12
157+
install_sbt_version: 1.6.1
155158
cmd: |
156159
sbt "scalafmtCheckAll;scalafmtSbtCheck;scapegoat;scalafixEnable;scalafix --test"
160+
cache_prefix: *cache_prefix
157161
requires:
158162
- compile
159163
- codacy/sbt:
160164
name: test
161-
install_sbt_version: 1.3.12
165+
install_sbt_version: 1.6.1
162166
cmd: |
163167
git config --global user.email "team@codacy.com"
164168
git config --global user.name "Codacy Team"
165169
sbt coverage +test coverageReport
166170
bash <(curl -Ls https://coverage.codacy.com/get.sh) report --skip
171+
cache_prefix: *cache_prefix
167172
requires:
168173
- compile
169174
- codacy/sbt:
170175
name: publish_docker_locally
171-
install_sbt_version: 1.3.12
176+
install_sbt_version: 1.6.1
172177
cmd: |
173178
sbt "set codacyAnalysisCli / version := \"dev-snapshot\";
174179
codacyAnalysisCli/docker:publishLocal"
175180
docker save --output docker-image.tar $CIRCLE_PROJECT_REPONAME:dev-snapshot
181+
cache_prefix: *cache_prefix
176182
persist_to_workspace: true
177183
requires:
178184
- compile
@@ -191,13 +197,14 @@ workflows:
191197
# - maven_dependencies
192198
- codacy/sbt:
193199
name: publish_lib
194-
install_sbt_version: 1.3.12
200+
install_sbt_version: 1.6.1
195201
context: CodacyAWS
196202
cmd: |
197203
sbt "retrieveGPGKeys;
198204
codacyAnalysisCore/publishSigned;
199205
+codacyAnalysisModels/publishSigned;
200206
sonatypeBundleRelease"
207+
cache_prefix: *cache_prefix
201208
requires:
202209
- publish_docker_locally
203210
filters:
@@ -216,14 +223,15 @@ workflows:
216223
- master
217224
- codacy/sbt:
218225
name: build_cli_jar
219-
install_sbt_version: 1.3.12
226+
install_sbt_version: 1.6.1
220227
persist_to_workspace: true
221228
cmd: |
222229
sbt "set codacyAnalysisCli / version := \"$(cat .version)\";
223-
set test in assembly := {};
230+
set assembly / test := {};
224231
codacyAnalysisCli/assembly"
225232
mkdir -p ~/workdir/artifacts/
226233
mv ./cli/target/scala-2.12/codacy-analysis-cli-assembly-$(cat .version).jar ~/workdir/artifacts/
234+
cache_prefix: *cache_prefix
227235
requires:
228236
- publish_docker_locally
229237
filters:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ project/plugins/project/
8585
.DS_Store
8686

8787
.bloop
88+
.bsp
8889
.metals
8990
project/metals.sbt
9091
project/project/

build.sbt

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@ import sbt._
44
import codacy.libs._
55
import sbt._
66

7-
Universal / javaOptions ++= Seq("-Xms1g", "-Xmx2g", "-Xss512m", "-XX:+UseG1GC", "-XX:+UseStringDeduplication")
8-
97
val assemblyCommon = Seq(
10-
test in assembly := {},
8+
assembly / test := {},
119
// Without this assembly merge strategy, gives the following error:
1210
// (codacyAnalysisCli / assembly) deduplicate: different file contents found in the following:
1311
// [error] org/bouncycastle/bcpg-jdk15on/1.64/bcpg-jdk15on-1.64.jar:META-INF/versions/9/module-info.class
1412
// Workaround:
1513
// https://stackoverflow.com/questions/54834125/sbt-assembly-deduplicate-module-info-class
16-
assemblyMergeStrategy in assembly := {
14+
assembly / assemblyMergeStrategy := {
1715
case "META-INF/versions/9/module-info.class" => MergeStrategy.discard
1816
case x =>
19-
val oldStrategy = (assemblyMergeStrategy in assembly).value
17+
val oldStrategy = (assembly / assemblyMergeStrategy).value
2018
oldStrategy(x)
2119
})
2220

@@ -60,8 +58,6 @@ lazy val codacyAnalysisCore = project
6058
sonatypeInformation,
6159
description := "Library to analyze projects")
6260
.settings(assemblyCommon: _*)
63-
// Disable legacy Scalafmt plugin imported by codacy-sbt-plugin
64-
.disablePlugins(com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin)
6561
.dependsOn(codacyAnalysisModels)
6662

6763
lazy val codacyAnalysisCli = project
@@ -79,18 +75,14 @@ lazy val codacyAnalysisCli = project
7975
.settings(assemblyCommon: _*)
8076
.enablePlugins(JavaAppPackaging)
8177
.enablePlugins(DockerPlugin)
82-
// Disable legacy Scalafmt plugin imported by codacy-sbt-plugin
83-
.disablePlugins(com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin)
8478
.dependsOn(codacyAnalysisCore % "compile->compile;test->test", toolRepositoryRemote)
8579
.aggregate(codacyAnalysisCore, toolRepositoryRemote)
8680

8781
lazy val toolRepositoryRemote = project
8882
.in(file("toolRepository-remote"))
8983
.settings(Common.genericSettings, libraryDependencies ++= Dependencies.specs2)
9084
.settings(assemblyCommon: _*)
91-
// Disable legacy Scalafmt plugin imported by codacy-sbt-plugin
92-
.disablePlugins(com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin)
93-
.dependsOn(codacyAnalysisCore, codacyAnalysisModels, codacyApiClient)
85+
.dependsOn(codacyAnalysisCore % "compile->compile;test->test", codacyAnalysisModels, codacyApiClient)
9486

9587
lazy val codacyAnalysisModels = project
9688
.in(file("model"))
@@ -104,8 +96,6 @@ lazy val codacyAnalysisModels = project
10496
description := "Library with analysis models")
10597
.settings(assemblyCommon: _*)
10698
.settings(sonatypeInformation)
107-
// Disable legacy Scalafmt plugin imported by codacy-sbt-plugin
108-
.disablePlugins(com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin)
10999
.enablePlugins(JavaAppPackaging)
110100

111101
lazy val apiSwaggerFile: File =

cli/src/main/scala/com/codacy/analysis/cli/analysis/ToolSelector.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,29 @@ import com.codacy.plugins.api.languages.Language
1010
class ToolSelector(toolRepository: ToolRepository) {
1111

1212
private val toolCollector = new ToolCollector(toolRepository)
13+
private val duplicationToolCollector = new DuplicationToolCollector(toolRepository)
1314

1415
def allTools(toolInput: Option[String],
1516
configuration: CLIConfiguration.Tool,
1617
languages: Set[Language]): Either[CLIError, Set[ITool]] = {
1718

19+
def toolsEither = tools(toolInput, configuration, languages)
1820
def metricsTools = MetricsToolCollector.fromLanguages(languages)
19-
def duplicationTools = DuplicationToolCollector.fromLanguages(languages)
21+
def duplicationToolsEither =
22+
duplicationToolCollector.fromLanguages(languages).left.map(e => CLIError.CouldNotGetTools(e.message))
2023

2124
toolInput match {
2225
case None =>
23-
val toolsEither = tools(toolInput, configuration, languages)
24-
25-
toolsEither.map(_ ++ metricsTools ++ duplicationTools)
26+
for {
27+
tools <- toolsEither
28+
duplicationTools <- duplicationToolsEither
29+
} yield tools ++ metricsTools ++ duplicationTools
2630

2731
case Some("metrics") =>
2832
Right(metricsTools.map(_.to[ITool]))
2933

3034
case Some("duplication") =>
31-
Right(duplicationTools.map(_.to[ITool]))
35+
duplicationToolsEither.map(_.map(_.to[ITool]))
3236

3337
case Some(_) =>
3438
val toolsEither = tools(toolInput, configuration, languages)

cli/src/main/scala/com/codacy/analysis/cli/command/AnalyseCommand.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ import com.codacy.analysis.core.configuration.CodacyConfigurationFileLoader
2525
import com.codacy.analysis.core.files.FileCollector
2626
import com.codacy.analysis.core.git.{Commit, Git, Repository}
2727
import com.codacy.analysis.core.model._
28+
import com.codacy.analysis.core.storage.FileDataStorage
2829
import com.codacy.analysis.core.upload.ResultsUploader
2930
import com.codacy.analysis.core.utils.Logger
3031
import com.codacy.analysis.core.utils.SeqOps._
3132
import com.codacy.toolRepository.remote.ToolRepositoryRemote
32-
import com.codacy.toolRepository.remote.storage.{PatternSpecDataStorage, ToolSpecDataStorage}
33+
import com.codacy.toolRepository.remote.storage.ToolPatternsSpecsEncoders._
3334
import org.log4s.getLogger
3435

3536
import scala.concurrent.ExecutionContext.Implicits.global
@@ -81,7 +82,9 @@ object AnalyseCommand {
8182

8283
val toolsClient =
8384
ToolsClient(codacyApiUrl)(httpClient = httpClient, ec = actorSystem.dispatcher, mat = materializer)
84-
new ToolRepositoryRemote(toolsClient, ToolSpecDataStorage.apply, PatternSpecDataStorage.apply)(
85+
val toolsDataStorage = FileDataStorage[ToolSpec]("tools")
86+
val duplicationToolsDataStorage = FileDataStorage[DuplicationToolSpec]("duplicationTools")
87+
new ToolRepositoryRemote(toolsClient, toolsDataStorage, duplicationToolsDataStorage, FileDataStorage(_))(
8588
ec = actorSystem.dispatcher,
8689
mat = materializer)
8790
}

cli/src/test/scala/com/codacy/analysis/cli/AnalyseExecutorSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class AnalyseExecutorSpec extends Specification with NoLanguageFeatures with Moc
166166
val analyser: Analyser[Try] = Analyser(analyserName)
167167
val fileCollector: FileCollector[Try] = FileCollector.defaultCollector()
168168

169-
val toolRepository = new ToolRepositoryMock
169+
val toolRepository = ToolRepositoryMock
170170
val toolSelector = new ToolSelector(toolRepository)
171171
new AnalyseExecutor(formatter, analyser, fileCollector, configuration, toolSelector).run() must beRight
172172
}

cli/src/test/scala/com/codacy/analysis/cli/CLISpec.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ import com.codacy.analysis.core.git.Commit
88
import com.codacy.analysis.core.model.{DuplicationClone, FileError, Result, ToolResult}
99
import com.codacy.analysis.core.utils.TestUtils._
1010
import com.codacy.plugins.utils.CommandRunner
11-
import io.circe
1211
import io.circe.generic.auto._
13-
import io.circe.{Json, parser}
12+
import io.circe.parser
1413
import org.specs2.control.NoLanguageFeatures
1514
import org.specs2.matcher.FileMatchers
1615
import org.specs2.mutable.Specification

cli/src/test/scala/com/codacy/analysis/cli/ToolSelectorSpec.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ import com.codacy.analysis.cli.analysis.ToolSelector
55
import com.codacy.analysis.cli.configuration.CLIConfiguration
66
import com.codacy.analysis.core.files.FilesTarget
77
import com.codacy.analysis.core.model.{AnalyserError, PatternSpec, ToolSpec}
8-
import com.codacy.analysis.core.tools.{Tool, ToolRepository}
8+
import com.codacy.analysis.core.tools.{Tool, ToolRepositoryStub}
99
import com.codacy.analysis.core.utils.LanguagesHelper
1010
import com.codacy.plugins.api.languages.Languages.{Javascript, Python}
1111
import com.codacy.plugins.api.languages.{Language, Languages}
1212
import org.specs2.control.NoLanguageFeatures
1313
import org.specs2.mutable.Specification
14+
import com.codacy.analysis.core.model.DuplicationToolSpec
1415

1516
class ToolSelectorSpec extends Specification with NoLanguageFeatures {
1617

1718
val emptyFilesTarget = FilesTarget(File(""), Set.empty, Set.empty)
1819
val noLocalConfiguration = Left("no config")
1920

20-
val toolRepository = new ToolRepository {
21+
val toolRepository = new ToolRepositoryStub {
2122

2223
private def getToolSpec(uuid: String, name: String, languages: Set[Language]) =
2324
ToolSpec(
@@ -37,7 +38,7 @@ class ToolSelectorSpec extends Specification with NoLanguageFeatures {
3738
isClientSide = false,
3839
hasUIConfiguration = true)
3940

40-
override def list(): Either[AnalyserError, Seq[ToolSpec]] =
41+
override def listTools(): Either[AnalyserError, Seq[ToolSpec]] =
4142
Right(
4243
Seq(
4344
getToolSpec("34225275-f79e-4b85-8126-c7512c987c0d", "PyLint", Set(Python)),
@@ -46,9 +47,10 @@ class ToolSelectorSpec extends Specification with NoLanguageFeatures {
4647
getToolSpec("38794ba2-94d8-4178-ab99-1f5c1d12760c", "BundlerAudit", Set(Languages.Ruby)),
4748
getToolSpec("cf05f3aa-fd23-4586-8cce-5368917ec3e5", "ESLint", Set(Languages.Javascript))))
4849

49-
override def get(uuid: String): Either[AnalyserError, ToolSpec] = ???
50-
5150
override def listPatterns(tool: ToolSpec): Either[AnalyserError, Seq[PatternSpec]] = Right(Seq.empty)
51+
52+
override def listDuplicationTools(): Either[AnalyserError, Seq[DuplicationToolSpec]] =
53+
Right(Seq(DuplicationToolSpec("", Set(Languages.Ruby))))
5254
}
5355
val toolSelector: ToolSelector = new ToolSelector(toolRepository)
5456

core/src/main/scala/com/codacy/analysis/core/storage/FileDataStorage.scala renamed to core/src/main/scala/com/codacy/analysis/core/storage/DataStorage.scala

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,46 @@ import org.log4s.{Logger, getLogger}
88

99
import scala.util.{Failure, Success, Try}
1010

11-
abstract class FileDataStorage[T](val storageFilename: String) {
11+
trait DataStorage[T] {
12+
def get(): Option[Seq[T]]
13+
def save(values: Seq[T]): Boolean
14+
def invalidate(): Try[Unit]
15+
}
1216

13-
implicit val encoder: Encoder[T]
14-
implicit val decoder: Decoder[T]
17+
object FileDataStorage {
1518

16-
private val logger: Logger = getLogger
19+
def apply[T](storageFilename: String)(implicit encoder: Encoder[T], decoder: Decoder[T]): DataStorage[T] = {
20+
val cacheFolder: File = {
21+
val defaultFolder = File.currentWorkingDirectory / ".codacy" / "codacy-analysis-cli"
22+
val osNameOpt = sys.props.get("os.name").map(_.toLowerCase)
23+
val result = osNameOpt match {
24+
case Some(sysName) if sysName.contains("mac") || sysName == "darwin" =>
25+
home / "Library" / "Caches" / "Codacy" / "codacy-analysis-cli"
1726

18-
private val cacheFolder: File = {
19-
val defaultFolder = File.currentWorkingDirectory / ".codacy" / "codacy-analysis-cli"
20-
val osNameOpt = sys.props.get("os.name").map(_.toLowerCase)
21-
val result = osNameOpt match {
22-
case Some(sysName) if sysName.contains("mac") || sysName == "darwin" =>
23-
home / "Library" / "Caches" / "Codacy" / "codacy-analysis-cli"
27+
case Some(sysName) if sysName.contains("nix") || sysName.contains("nux") =>
28+
home / ".cache" / "codacy" / "codacy-analysis-cli"
2429

25-
case Some(sysName) if sysName.contains("nix") || sysName.contains("nux") =>
26-
home / ".cache" / "codacy" / "codacy-analysis-cli"
30+
case Some(sysName) if sysName.contains("windows") =>
31+
sys.env.get("APPDATA").fold(defaultFolder) { windowsCacheDir =>
32+
File(windowsCacheDir) / "Codacy" / "codacy-analysis-cli"
33+
}
2734

28-
case Some(sysName) if sysName.contains("windows") =>
29-
sys.env.get("APPDATA").fold(defaultFolder) { windowsCacheDir =>
30-
File(windowsCacheDir) / "Codacy" / "codacy-analysis-cli"
31-
}
35+
case _ => defaultFolder
36+
}
3237

33-
case _ => defaultFolder
38+
result.createIfNotExists(asDirectory = true, createParents = true)
39+
result
3440
}
35-
36-
result.createIfNotExists(asDirectory = true, createParents = true)
37-
result
41+
apply[T](cacheFolder / storageFilename)
3842
}
3943

40-
val storageFile: File = cacheFolder / storageFilename
44+
def apply[T](storageFile: File)(implicit encoder: Encoder[T], decoder: Decoder[T]): DataStorage[T] =
45+
new FileDataStorage(storageFile)
46+
}
47+
48+
private class FileDataStorage[T] private[storage] (storageFile: File)(implicit encoder: Encoder[T], decoder: Decoder[T])
49+
extends DataStorage[T] {
50+
private val logger: Logger = getLogger
4151

4252
private def writeToFile(content: String): Try[File] =
4353
Try {

0 commit comments

Comments
 (0)