diff --git a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketLock.groovy b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketLock.groovy index 3c58640..b45c5aa 100644 --- a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketLock.groovy +++ b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketLock.groovy @@ -40,47 +40,49 @@ class PaketLock { PaketLock(String lockContent) { content = [:] - def currentSourceType - def currentPackageName - def currentIndent = 0 - def currentLeadingWhitespaces = 0 - def currentLineData + String currentSourceType + String currentPackageName + int currentIndent = 0 + String currentLineData lockContent.eachLine { line -> - if (!line.trim()) { - return - } - - def newLeadingWhitespaces = (line =~ /\s/).size() - if (newLeadingWhitespaces > currentLeadingWhitespaces) { - currentIndent++ - } else if (newLeadingWhitespaces < currentLeadingWhitespaces) { - currentIndent-- - } - currentLeadingWhitespaces = newLeadingWhitespaces currentLineData = line.trim() - - if (currentIndent == LineType.TYPE.value && isValidSourceType(currentLineData)) { - currentSourceType = currentLineData - content[currentSourceType] = [:] - return - } - if (currentIndent == LineType.REMOTE.value) { - return - } - if (currentIndent == LineType.NAME.value) { - currentPackageName = currentLineData.split(" ")[0] - content["${currentSourceType}"][currentPackageName] = [] + if (currentLineData.trim().empty) { return } - if (currentIndent == LineType.DEPENDENCY.value) { - (content["${currentSourceType}"]["${currentPackageName}"] as List) << currentLineData.split(" ")[0] + + def match = (line =~ /^[\s]+/) + currentIndent = !match ? 0 : match[0].size() / 2 + + switch (currentIndent) { + case LineType.TYPE.value: + if(isValidSourceType(currentLineData)) { + currentSourceType = currentLineData + content[currentSourceType] = [:] + } + break + case LineType.NAME.value: + currentPackageName = currentLineData.split(/\s/)[0] + if(currentSourceType && currentPackageName) { + content[currentSourceType][currentPackageName] = [] + } + break + + case LineType.DEPENDENCY.value: + if(currentSourceType && currentPackageName) { + (content[currentSourceType][currentPackageName] as List) << currentLineData.split(/\s/)[0] + } + break + + case LineType.REMOTE.value: + default: + break } } } - boolean isValidSourceType(String value) { + static boolean isValidSourceType(String value) { for (SourceType type in SourceType.values()) { if (type.value == value) return true @@ -89,22 +91,14 @@ class PaketLock { } List getDependencies(SourceType source, String id) { - content[source.getValue()] && content[source.getValue()][id] ? content[source.getValue()][id] as List : null + content[source.getValue()] && content[source.getValue()][id] ? content[source.getValue()][id] as List : [] } List getAllDependencies(List references) { - def result = [] - for (def referenceDependency in references) { - result.add(referenceDependency) - def referenceDependencies = getDependencies(SourceType.NUGET, referenceDependency) - if (referenceDependencies) { - result.addAll(referenceDependencies) - def dependencies = getAllDependencies(referenceDependencies) - if (dependencies) { - result.addAll(dependencies) - } - } + def ref = references.collect { reference -> + [reference, getAllDependencies(getDependencies(SourceType.NUGET, reference))] } - result.unique() + + ref.flatten().unique() } } diff --git a/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketLockSpec.groovy b/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketLockSpec.groovy index d42dc94..d305b32 100644 --- a/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketLockSpec.groovy +++ b/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketLockSpec.groovy @@ -8,25 +8,70 @@ class PaketLockSpec extends Specification { static String LOCK_CONTENT = """ NUGET - remote: https://wooga.artifactoryonline.com/wooga/api/nuget/atlas-nuget - NSubstitute (1.9.1.0) - Substance (0.0.10-beta) - Substance.Collections (0.0.10-beta) - Substance (>= 0.0.10-beta) - Substance.Collections.Generic (0.0.10-beta) - Substance (>= 0.0.10-beta) - Substance.Collections (>= 0.0.10-beta) - Substance.Collections.Immutable (0.0.10-beta) - Substance (>= 0.0.10-beta) - Substance.Collections (>= 0.0.10-beta) - Substance.Collections.Generic (>= 0.0.10-beta) - Wooga.AtlasBuildTools (1.0.0) - Wooga.Lambda (0.7.0) - Substance.Collections.Immutable (>= 0.0.0-beta) - Wooga.XCodeEditor (3.1.3) - Wooga.JsonDotNetNode (>= 0.1.0-prerelease < 0.2.0-prerelease) - remote: https://wooga.artifactoryonline.com/wooga/api/nuget/atlas-nuget-snapshot - Wooga.JsonDotNetNode (0.1.1-master00001) + remote: https://a.repo.com + A (0.0.10-beta) + W.A (3.0.0-rc00001) + W.S (>= 3.0.0-rc) + W.E (1.0.0) + W.N (0.1.0) + W.S (3.0.1) + W.J (>= 0.1.0-prerelease < 0.2.0-prerelease) + W.L (>= 0.7 < 1.0) + remote: https://www.nuget.org/api/v2 + A.C (0.0.10-beta) + A (>= 0.0.10-beta) + A.C.G (0.0.10-beta) + A (>= 0.0.10-beta) + A.C (>= 0.0.10-beta) + A.C.I (0.0.10-beta) + A (>= 0.0.10-beta) + A.C (>= 0.0.10-beta) + A.C.G (>= 0.0.10-beta) + W.L (0.7) + A.C.I (>= 0.0.0-beta) + remote: https://a.repo.com/snapshot + W.J (0.1.1-master00001) + """.stripIndent() + + static String MULTI_TYPE_LOCK_CONTENT = """ + ${LOCK_CONTENT} + + GITHUB + remote: fsharp/FAKE + modules/Octokit/Octokit.fsx (a25c2f256a99242c1106b5a3478aae6bb68c7a93) + Octokit (>= 0) + GIT + remote: https://github.com/forki/nupkgtest.git + (05366e390e7552a569f3f328a0f3094249f3b93b) + HTTP + remote: http://www.fssnip.net/raw/1M/test1.fs + test1.fs + """.stripIndent() + + static String LOCK_CONTENT_BROKEN_TYPE = """ + NUGIT + remote: https://a.repo.com + A (0.0.10-beta) + W.A (3.0.0-rc00001) + W.S (>= 3.0.0-rc) + W.E (1.0.0) + W.N (0.1.0) + W.S (3.0.1) + W.J (>= 0.1.0-prerelease < 0.2.0-prerelease) + W.L (>= 0.7 < 1.0) + """.stripIndent() + + static String LOCK_CONTENT_BROKEN_INDENTION = """ + NUGET + remote: https://a.repo.com + A (0.0.10-beta) + W.A (3.0.0-rc00001) + W.S (>= 3.0.0-rc) + W.E (1.0.0) + W.N (0.1.0) + W.S (3.0.1) + W.J (>= 0.1.0-prerelease < 0.2.0-prerelease) + W.L (>= 0.7 < 1.0) """.stripIndent() @Shared @@ -49,14 +94,63 @@ class PaketLockSpec extends Specification { def lock = new PaketLock(content) then: - def nugets = lock.getDependencies(PaketLock.SourceType.NUGET, "Wooga.XCodeEditor") + def nugets = lock.getDependencies(PaketLock.SourceType.NUGET, "W.A") nugets.size() == 1 - nugets.contains("Wooga.JsonDotNetNode") + nugets.contains("W.S") where: objectType | content - "String" | LOCK_CONTENT - "File" | lockFile << LOCK_CONTENT + "String" | LOCK_CONTENT + "File" | lockFile << LOCK_CONTENT + "multi type String" | MULTI_TYPE_LOCK_CONTENT + "multi type File" | lockFile << MULTI_TYPE_LOCK_CONTENT + } + + @Unroll + def "parses all nuget dependencies from paket.lock with #objectType"() { + when: + def lock = new PaketLock(content) + + then: + def nugets = lock.getAllDependencies(references) + + expectedDependencies.every { + nugets.contains(it) + } + + nugets.size() == expectedDependencies.size() + + where: + objectType | content + "String" | LOCK_CONTENT + "File" | lockFile << LOCK_CONTENT + "multi type String" | MULTI_TYPE_LOCK_CONTENT + "multi type File" | lockFile << MULTI_TYPE_LOCK_CONTENT + + references = ["W.S", "W.A", "W.N", "W.E"] + expectedDependencies = references + ["A", "A.C", "A.C.I", "A.C.G", "W.L", "W.J"] + } + + @Unroll + def "fails to expand when dependency file has #failure"() { + when: + def lock = new PaketLock(content) + + then: + def nugets = lock.getAllDependencies(references) + + expectedDependencies.every { + nugets.contains(it) + } + + nugets.size() == expectedDependencies.size() + + where: + failure | content + "broken type" | LOCK_CONTENT_BROKEN_TYPE + "wrong indention" | LOCK_CONTENT_BROKEN_INDENTION + references = ["A"] + expectedDependencies = references } }