From 8bbd60f5abb10bfb7b58e43ef6b8d4f689e85d60 Mon Sep 17 00:00:00 2001 From: Christian Sagel Date: Wed, 13 Mar 2024 08:44:38 +0100 Subject: [PATCH] =?UTF-8?q?Add=20support=20for=20automatically=20mapping?= =?UTF-8?q?=20used=20framework=20for=20generated=20up=E2=80=A6=20(#104)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for automatically mapping used framework for generated upm package directories * Use the newer integration spec on this plugin already * Fix the bug with paketInstall on windows in UPM mode * Normalized paket package folder name * Remove the unused assembly definition strategy * Improve naming on task, new properties --------- Co-authored-by: Joaquim Alvino de Mesquita Neto --- .gitignore | 1 + ...y => BootstrapPaketIntegrationSpec.groovy} | 2 +- .../PaketIntegrationArgumentsSpec.groovy | 2 +- .../PaketIntegrationDependencyFileSpec.groovy | 2 +- ...pec.groovy => PaketIntegrationSpec.groovy} | 41 ++- .../base/PaketBaseIntegrationSpec.groovy | 4 +- ...ketNugetDependenciesIntegrationSpec.groovy | 8 +- .../get/PaketRestoreIntegrationSpec.groovy | 4 +- .../PaketPublishIntegrationSpec.groovy | 32 ++- ...UnityAssemblyDefinitionStrategySpec.groovy | 74 ----- .../paket/unity/PaketUnityChangeSpec.groovy | 62 +---- .../unity/PaketUnityFrameworksSpec.groovy | 50 +++- .../unity/PaketUnityIntegrationSpec.groovy | 64 ++--- ...tures.groovy => PaketFixturesTrait.groovy} | 19 +- .../gradle/paket/FrameworkRestriction.groovy | 21 ++ .../paket/base/PaketPluginExtension.groovy | 8 +- ...es.groovy => PaketDependenciesSpec.groovy} | 10 +- .../utils/internal/PaketDependencies.groovy | 108 +++++++- .../base/utils/internal/PaketLock.groovy | 5 +- .../internal/PaketUPMWrapperReference.groovy | 19 +- .../gradle/paket/get/PaketGetPlugin.groovy | 2 - .../paket/unity/PaketUnityPlugin.groovy | 67 +++-- .../unity/PaketUnityPluginConventions.groovy | 12 +- .../unity/PaketUnityPluginExtension.groovy | 16 +- .../paket/unity/PaketUpmPackageSpec.groovy | 22 +- .../DefaultPaketUnityPluginExtension.groovy | 11 - .../internal/NugetToUpmPackageIdCache.groovy | 90 +++--- .../unity/internal/UPMPackageDirectory.groovy | 39 +++ .../unity/internal/UPMPaketPackage.groovy | 41 --- .../unity/tasks/AbstractPaketUnityTask.groovy | 88 ++++++ .../unity/tasks/PaketUnityInstall.groovy | 262 +++++++++--------- .../unity/tasks/PaketUnwrapUPMPackages.groovy | 81 ++---- .../internal/PaketDependenciesSpec.groovy | 17 ++ 33 files changed, 704 insertions(+), 580 deletions(-) rename src/integrationTest/groovy/wooga/gradle/paket/{PaketIntegrationBaseSpec.groovy => BootstrapPaketIntegrationSpec.groovy} (98%) rename src/integrationTest/groovy/wooga/gradle/paket/{IntegrationSpec.groovy => PaketIntegrationSpec.groovy} (64%) delete mode 100644 src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityAssemblyDefinitionStrategySpec.groovy rename src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/{PaketFixtures.groovy => PaketFixturesTrait.groovy} (87%) create mode 100644 src/main/groovy/wooga/gradle/paket/FrameworkRestriction.groovy rename src/main/groovy/wooga/gradle/paket/base/utils/{PaketDependencies.groovy => PaketDependenciesSpec.groovy} (79%) create mode 100644 src/main/groovy/wooga/gradle/paket/unity/internal/UPMPackageDirectory.groovy delete mode 100644 src/main/groovy/wooga/gradle/paket/unity/internal/UPMPaketPackage.groovy create mode 100644 src/main/groovy/wooga/gradle/paket/unity/tasks/AbstractPaketUnityTask.groovy diff --git a/.gitignore b/.gitignore index e213dfe..6c87cfb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ gradle-app.setting # gradle/wrapper/gradle-wrapper.properties userHome/ +bin diff --git a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationBaseSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/BootstrapPaketIntegrationSpec.groovy similarity index 98% rename from src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationBaseSpec.groovy rename to src/integrationTest/groovy/wooga/gradle/paket/BootstrapPaketIntegrationSpec.groovy index 8444b1a..6287237 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationBaseSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/BootstrapPaketIntegrationSpec.groovy @@ -22,7 +22,7 @@ import spock.lang.Shared import spock.lang.Unroll import wooga.gradle.paket.base.PaketBasePlugin -abstract class PaketIntegrationBaseSpec extends IntegrationSpec { +abstract class BootstrapPaketIntegrationSpec extends PaketIntegrationSpec { @Shared def bootstrapTestCases diff --git a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationArgumentsSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationArgumentsSpec.groovy index 87af6d9..8fd3330 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationArgumentsSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationArgumentsSpec.groovy @@ -20,7 +20,7 @@ package wooga.gradle.paket import spock.lang.IgnoreIf import spock.lang.Unroll -abstract class PaketIntegrationArgumentsSpec extends IntegrationSpec { +abstract class PaketIntegrationArgumentsSpec extends PaketIntegrationSpec { abstract Class getTestPlugin() abstract List getTestTasks() diff --git a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationDependencyFileSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationDependencyFileSpec.groovy index 1e79fa1..9606005 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationDependencyFileSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationDependencyFileSpec.groovy @@ -22,7 +22,7 @@ import wooga.gradle.paket.get.PaketGetPlugin import wooga.gradle.paket.unity.internal.DefaultPaketUnityPluginExtension import wooga.gradle.paket.unity.PaketUnityPlugin -abstract class PaketIntegrationDependencyFileSpec extends PaketIntegrationBaseSpec { +abstract class PaketIntegrationDependencyFileSpec extends BootstrapPaketIntegrationSpec { @Unroll def "skips paket call with [NO-SOURCE] when no [paket.dependencies] file is present when running #taskToRun"(String taskToRun) { diff --git a/src/integrationTest/groovy/wooga/gradle/paket/IntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationSpec.groovy similarity index 64% rename from src/integrationTest/groovy/wooga/gradle/paket/IntegrationSpec.groovy rename to src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationSpec.groovy index 0114742..aa7af92 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/IntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/PaketIntegrationSpec.groovy @@ -17,14 +17,18 @@ package wooga.gradle.paket -import nebula.test.functional.ExecutionResult +import com.wooga.gradle.test.IntegrationSpec import org.apache.commons.io.FileUtils -import org.apache.commons.lang3.StringEscapeUtils import org.junit.Rule import org.junit.contrib.java.lang.system.ProvideSystemProperty import spock.lang.Shared +import wooga.gradle.paket.base.utils.internal.PaketDependencies +import wooga.gradle.paket.unity.internal.DefaultPaketUnityPluginExtension -class IntegrationSpec extends nebula.test.IntegrationSpec{ +/** + * The base class for all tests in this test package + */ +class PaketIntegrationSpec extends IntegrationSpec { @Rule ProvideSystemProperty properties = new ProvideSystemProperty("ignoreDeprecations", "true") @@ -32,14 +36,6 @@ class IntegrationSpec extends nebula.test.IntegrationSpec{ @Shared File cachedPaketDir - def escapedPath(String path) { - String osName = System.getProperty("os.name").toLowerCase() - if (osName.contains("windows")) { - return StringEscapeUtils.escapeJava(path) - } - path - } - def convertToWindowsPath(String path) { new File(path).toString() } @@ -91,7 +87,26 @@ class IntegrationSpec extends nebula.test.IntegrationSpec{ } } - Boolean outputContains(ExecutionResult result, String message) { - result.standardOutput.contains(message) || result.standardError.contains(message) + File generateDependenciesFile(PaketDependencies dependencies){ + def file = createFile("paket.dependencies") + file << dependencies.toString() + file + } + + File generateUnityProject(String name, boolean rooted) { + File unityProjDir = rooted ? projectDir : new File(projectDir, name) + new File(unityProjDir, "Assets").mkdirs() + new File(unityProjDir, "Packages").mkdirs() + def manifestJson = new File(unityProjDir, "Packages/manifest.json") + manifestJson.createNewFile() + unityProjDir + } + + File generateReferencesFile(PaketDependencies dependencies, File baseDir = null) { + baseDir ?= projectDir + File file = new File(baseDir, DefaultPaketUnityPluginExtension.DEFAULT_PAKET_UNITY_REFERENCES_FILE_NAME) + file.createNewFile() + file << dependencies.getNugetDependencies().join(System.lineSeparator()) + file } } diff --git a/src/integrationTest/groovy/wooga/gradle/paket/base/PaketBaseIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/base/PaketBaseIntegrationSpec.groovy index f409838..9a2b296 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/base/PaketBaseIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/base/PaketBaseIntegrationSpec.groovy @@ -20,10 +20,10 @@ package wooga.gradle.paket.base import org.gradle.language.base.plugins.LifecycleBasePlugin import spock.lang.Shared import spock.lang.Unroll -import wooga.gradle.paket.PaketIntegrationBaseSpec +import wooga.gradle.paket.BootstrapPaketIntegrationSpec import wooga.gradle.paket.get.PaketGetPlugin -class PaketBaseIntegrationSpec extends PaketIntegrationBaseSpec { +class PaketBaseIntegrationSpec extends BootstrapPaketIntegrationSpec { def setupSpec() { System.setProperty("USE_DEPENDENCY_TEST", "NO") diff --git a/src/integrationTest/groovy/wooga/gradle/paket/base/dependencies/PaketNugetDependenciesIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/base/dependencies/PaketNugetDependenciesIntegrationSpec.groovy index 3654837..f77bc08 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/base/dependencies/PaketNugetDependenciesIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/base/dependencies/PaketNugetDependenciesIntegrationSpec.groovy @@ -18,11 +18,11 @@ package wooga.gradle.paket.base.dependencies import spock.lang.Unroll -import wooga.gradle.paket.IntegrationSpec +import wooga.gradle.paket.PaketIntegrationSpec import wooga.gradle.paket.base.PaketBasePlugin import wooga.gradle.paket.get.PaketGetPlugin -class PaketNugetDependenciesIntegrationSpec extends IntegrationSpec { +class PaketNugetDependenciesIntegrationSpec extends PaketIntegrationSpec { def setup() { buildFile << """ group = 'test' @@ -234,8 +234,8 @@ class PaketNugetDependenciesIntegrationSpec extends IntegrationSpec { then: paketDependencies.exists() - paketDependencies.text.contains("source ${convertToWindowsPath('../path/to/source/one')}") - paketDependencies.text.contains("source ${convertToWindowsPath('../path/to/source/two')}") + paketDependencies.text.contains("source ${osPath('../path/to/source/one')}") + paketDependencies.text.contains("source ${osPath('../path/to/source/two')}") where: diff --git a/src/integrationTest/groovy/wooga/gradle/paket/get/PaketRestoreIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/get/PaketRestoreIntegrationSpec.groovy index 35a3389..ab29111 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/get/PaketRestoreIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/get/PaketRestoreIntegrationSpec.groovy @@ -20,9 +20,9 @@ package wooga.gradle.paket.get import spock.lang.Ignore import spock.lang.Shared import spock.lang.Unroll -import wooga.gradle.paket.PaketIntegrationBaseSpec +import wooga.gradle.paket.BootstrapPaketIntegrationSpec -class PaketRestoreIntegrationSpec extends PaketIntegrationBaseSpec { +class PaketRestoreIntegrationSpec extends BootstrapPaketIntegrationSpec { def setup() { buildFile << """ diff --git a/src/integrationTest/groovy/wooga/gradle/paket/publish/PaketPublishIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/publish/PaketPublishIntegrationSpec.groovy index c66ff70..6a3513e 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/publish/PaketPublishIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/publish/PaketPublishIntegrationSpec.groovy @@ -17,7 +17,7 @@ package wooga.gradle.paket.publish -import groovy.json.StringEscapeUtils + import org.jfrog.artifactory.client.Artifactory import org.jfrog.artifactory.client.ArtifactoryClientBuilder import org.jfrog.artifactory.client.model.RepoPath @@ -33,7 +33,7 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { @Shared def version = "1.0.0" - def uniquPackagePostfix() { + static def uniquePackagePostfix() { String key = "TRAVIS_JOB_NUMBER" def env = System.getenv() if (env.containsKey(key)) { @@ -43,7 +43,7 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { } @Shared - def packageID = "Wooga.Test" + uniquPackagePostfix() + def packageID = "Wooga.Test" + uniquePackagePostfix() @Shared def repoName = "integration" @@ -71,7 +71,19 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { } def setupSpec() { - String artifactoryCredentials = System.getenv("artifactoryCredentials") + String username + String password + + String artifactoryCredentials + def usr = System.getenv("ATLAS_READ_USR") + def pwd = System.getenv("ATLAS_READ_PSW") + if (usr && pwd) { + artifactoryCredentials = "${usr}:${pwd}" + } + else{ + artifactoryCredentials = System.getenv("artifactoryCredentials") + } + assert artifactoryCredentials def credentials = artifactoryCredentials.split(':') artifactory = ArtifactoryClientBuilder.create() @@ -223,7 +235,7 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { and: "paket.dependencies and paket.lock file" createFile("paket.lock") createFile("paket.dependencies") - def escapedPath = escapedPath(localPath.absolutePath) + def escapedPath = osPath (localPath.absolutePath) and: "a build.gradle file with a local publish entry" buildFile.text = "" @@ -238,7 +250,7 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { repositories { nuget { name "$repoName" - path "$escapedPath" + path ${wrapValueBasedOnType(escapedPath, String)} } } } @@ -265,12 +277,4 @@ class PaketPublishIntegrationSpec extends PaketIntegrationDependencyFileSpec { where: taskToRun << ["publish-${packageIdToName(packageID)}", "publish${repoName.capitalize()}-${packageIdToName(packageID)}", "publish${repoName.capitalize()}", "publish"] } - - def escapedPath(String path) { - String osName = System.getProperty("os.name").toLowerCase() - if (osName.contains("windows")) { - return StringEscapeUtils.escapeJava(path) - } - path - } } diff --git a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityAssemblyDefinitionStrategySpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityAssemblyDefinitionStrategySpec.groovy deleted file mode 100644 index 874b0e4..0000000 --- a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityAssemblyDefinitionStrategySpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 Wooga GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package wooga.gradle.paket.unity - -import nebula.test.IntegrationSpec -import spock.lang.Unroll -import wooga.gradle.extensions.PaketDependency -import wooga.gradle.extensions.PaketDependencySetup -import wooga.gradle.extensions.PaketUnity -import wooga.gradle.extensions.PaketUnitySetup -import wooga.gradle.paket.get.PaketGetPlugin - -class PaketUnityAssemblyDefinitionStrategySpec extends IntegrationSpec { - - @PaketDependency - PaketDependencySetup _paketSetup - - @PaketUnity - PaketUnitySetup unityProject - - def setup() { - buildFile << """ - ${applyPlugin(PaketGetPlugin)} - ${applyPlugin(PaketUnityPlugin)} - """.stripIndent() - } - - @Unroll - def "task :paketInstall #message in #location paket install directory when assembly definition strategy is set to #strategy"() { - given: - buildFile << """ - paketUnity.assemblyDefinitionFileStrategy = "$strategy" - """.stripIndent() - - and: "a file matching the file pattern" - def baseDir = (location == "root") ? unityProject.installDirectory : new File(unityProject.installDirectory, "some/nested/directory") - baseDir.mkdirs() - - def fileToKeep = createFile("test${filePattern}", baseDir) << "random content" - - when: - runTasksSuccessfully(PaketUnityPlugin.INSTALL_TASK_NAME) - - then: - fileToKeep.exists() == expectFileToExist - - where: - filePattern | location | strategy | expectFileToExist - ".asmdef" | "root" | "manual" | true - ".asmdef" | "nested" | "manual" | true - ".asmdef.meta" | "root" | "manual" | true - ".asmdef.meta" | "nested" | "manual" | true - ".asmdef" | "root" | "disabled" | false - ".asmdef" | "nested" | "disabled" | false - ".asmdef.meta" | "root" | "disabled" | false - ".asmdef.meta" | "nested" | "disabled" | false - message = (expectFileToExist) ? "keeps files with $filePattern" : "cleans assembly definition files" - } -} diff --git a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityChangeSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityChangeSpec.groovy index 1603999..e36e13d 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityChangeSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityChangeSpec.groovy @@ -1,33 +1,12 @@ -/* - * Copyright 2018 Wooga GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - package wooga.gradle.paket.unity -import nebula.test.IntegrationSpec + import spock.lang.Unroll -import wooga.gradle.extensions.PaketDependency -import wooga.gradle.extensions.PaketDependencyInterceptor -import wooga.gradle.extensions.PaketDependencySetup -import wooga.gradle.extensions.PaketUnity -import wooga.gradle.extensions.PaketUnitySetup +import wooga.gradle.extensions.* +import wooga.gradle.paket.PaketIntegrationSpec import wooga.gradle.paket.get.PaketGetPlugin -import wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages -class PaketUnityChangeSpec extends IntegrationSpec { +class PaketUnityChangeSpec extends PaketIntegrationSpec { final static String STD_OUT_ALL_OUT_OF_DATE = "The input changes require a full rebuild for incremental task" final static String U = PaketDependencyInterceptor.localUPMWrapperPackagePrefix; @@ -44,7 +23,6 @@ class PaketUnityChangeSpec extends IntegrationSpec { @PaketUnity(projectReferences = ["D3", "D4"]) PaketUnitySetup unityProject3 - def setup() { buildFile << """ group = 'test' @@ -54,7 +32,7 @@ class PaketUnityChangeSpec extends IntegrationSpec { } @Unroll - def "task :paketUnityInstall when #message was up to date #wasUpToDate"() { + def "task paketUnityInstall when #message was up to date #wasUpToDate"() { given: "a root project with a unity project" and: "paket dependency file" @@ -79,7 +57,7 @@ class PaketUnityChangeSpec extends IntegrationSpec { unityProject1.projectReferencesFile.exists() appliedReferencesAfterUpdate.every { ref -> - new File(unityProject1.installDirectory, ref as String).exists() + new File(unityProject1.installDirectory, ref).exists() } where: @@ -117,7 +95,7 @@ class PaketUnityChangeSpec extends IntegrationSpec { } @Unroll - def "task :paketUnityUnwrapUPMPackages when #message was up to date #wasUpToDate"() { + def "task paketUnityUnwrapUPMPackages when #message was up to date #wasUpToDate"() { given: "a root project with a unity project" and: "paket dependency file" @@ -413,32 +391,6 @@ class PaketUnityChangeSpec extends IntegrationSpec { out2.exists() } - @Unroll - def "task :paketInstall keeps files with #filePattern in #location paket install directory when strategy is #strategy"() { - given: "a file matching the file pattern" - def baseDir = (location == "root") ? unityProject1.installDirectory : new File(unityProject1.installDirectory, "some/nested/directory") - baseDir.mkdirs() - def fileToKeep = createFile("test${filePattern}", baseDir) << "random content" - - and: "the assembly file definition strategy set to manual" - buildFile << """ - paketUnity.assemblyDefinitionFileStrategy = "$strategy" - """.stripIndent() - - when: - runTasksSuccessfully(PaketUnityPlugin.INSTALL_TASK_NAME) - - then: - fileToKeep.exists() - - where: - filePattern | location | strategy - ".asmdef" | "root" | "manual" - ".asmdef" | "nested" | "manual" - ".asmdef.meta" | "root" | "manual" - ".asmdef.meta" | "nested" | "manual" - } - def "task :paketInstall deletes empty directories"() { given: "a root project with a unity project" buildFile << """ diff --git a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityFrameworksSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityFrameworksSpec.groovy index 7001a57..3c780a3 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityFrameworksSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityFrameworksSpec.groovy @@ -17,12 +17,16 @@ package wooga.gradle.paket.unity +import groovy.json.JsonSlurper import nebula.test.IntegrationSpec import spock.lang.Unroll +import wooga.gradle.paket.FrameworkRestriction +import wooga.gradle.paket.PaketIntegrationSpec import wooga.gradle.paket.PaketPlugin +import wooga.gradle.paket.base.utils.internal.PaketDependencies import wooga.gradle.paket.unity.internal.DefaultPaketUnityPluginExtension -class PaketUnityFrameworksSpec extends IntegrationSpec { +class PaketUnityFrameworksSpec extends PaketIntegrationSpec { def setup() { buildFile << """ @@ -95,4 +99,48 @@ class PaketUnityFrameworksSpec extends IntegrationSpec { "BouncyCastle" | "1.8.4" | "BouncyCastle.Crypto.dll" } + // Yes, I had to do a shorthand because of Windows longpath exceptions. + @Unroll + def "cpd"() { + + given: "a generated unity project" + def unityProjDir = generateUnityProject("unity", rooted) + + and: "generated paket files" + def paketDeps = new PaketDependencies() + .withNugetSource() + .withDependency(nugetId, version) + .withFrameworks(FrameworkRestriction.NetStandard2) + + generateDependenciesFile(paketDeps) + generateReferencesFile(paketDeps, unityProjDir) + + and: "a configured plugin" + appendToTask("paketUnity", "paketUpmPackageEnabled = true") + appendToTask("paketUnity", "includeAssemblyDefinitions = true") + if (namespace != null) { + appendToTask("paketUnity", "defaultUpmNamespace = ${wrapValueBasedOnType(namespace, String)}") + } + + when: + def result = runTasks("paketInstall") + + then: + result.success + def packageDirectory = new File(unityProjDir, "Packages/${upmId}") + def packageManifestFile = new File(packageDirectory, "package.json") + + packageManifestFile.file + + def packageManifest = new JsonSlurper().parse(packageManifestFile) as Map + packageManifest['name'] == upmId + + where: + rooted | nugetId | version | namespace | upmId + false | "NSubstitute" | "5.1.0" | null | "com.wooga.nuget.nsubstitute" + false | "NSubstitute" | "5.1.0" | "com.wooga.nuget.netstandard2" | "com.wooga.nuget.netstandard2.nsubstitute" + true | "NSubstitute" | "5.1.0" | null | "com.wooga.nuget.nsubstitute" + true | "NSubstitute" | "5.1.0" | "com.wooga.nuget.netstandard2" | "com.wooga.nuget.netstandard2.nsubstitute" + } + } diff --git a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityIntegrationSpec.groovy b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityIntegrationSpec.groovy index a4c61bc..afda054 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityIntegrationSpec.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/unity/PaketUnityIntegrationSpec.groovy @@ -19,16 +19,18 @@ package wooga.gradle.paket.unity import com.wooga.gradle.test.PropertyUtils import groovy.json.JsonSlurper -import nebula.test.IntegrationSpec import nebula.test.functional.ExecutionResult import spock.lang.Shared import spock.lang.Unroll import wooga.gradle.extensions.PaketDependencyInterceptor +import wooga.gradle.paket.FrameworkRestriction +import wooga.gradle.paket.PaketIntegrationSpec +import wooga.gradle.paket.base.utils.internal.PaketDependencies import wooga.gradle.paket.get.PaketGetPlugin import wooga.gradle.paket.unity.fixtures.PaketFixturesTrait import wooga.gradle.paket.unity.tasks.PaketUnityInstall -class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixturesTrait { +class PaketUnityIntegrationSpec extends PaketIntegrationSpec implements PaketFixturesTrait { def setup() { buildFile << """ @@ -293,8 +295,8 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures paketUnity { paketUpmPackageEnabled = $paketUpmPackageEnabled ${overrides ? - "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : - "" + "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : + "" } } """ @@ -347,8 +349,8 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures paketUnity { paketUpmPackageEnabled = true ${overrides ? - "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : - "" + "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : + "" } } """ @@ -369,10 +371,10 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures pkgJson.entrySet().containsAll(overrides?.entrySet() ?: [].toSet()) where: - packageType | source | isUpmPackage | overrides - "upm-enabled" | "package-json" | true | null - "non-upm" | "generated" | false | null - "non-upm" | "overridden" | false | ["name": "com.custom.name"] + packageType | source | isUpmPackage | overrides + "upm-enabled" | "package-json" | true | null + "non-upm" | "generated" | false | null + "non-upm" | "overridden" | false | ["name": "com.custom.name"] } def "Paket-installed #packageType packages get deleted"() { @@ -402,8 +404,8 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures paketUnity { paketUpmPackageEnabled = true ${overrides ? - "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : - "" + "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : + "" } } """ @@ -425,10 +427,10 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures where: - packageType | isUpmPackage | overrides - "upm-enabled" | true | null - "non-upm" | false | null - "non-upm-overridden" | false | ["name": "com.custom.name"] + packageType | isUpmPackage | overrides + "upm-enabled" | true | null + "non-upm" | false | null + "non-upm-overridden" | false | ["name": "com.custom.name"] } def "#deleteVerb #packageType package on non-incremental delete"() { @@ -466,12 +468,13 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures } where: - deleteVerb | packageType | doesDelete | packageId | preinstalledPackage | isUpmPackage - "Does NOT delete" | "non-upm-package" | false | "com.wooga.do-not-delete-me" | "" | false - "Does NOT delete" | "preinstalled" | false | "com.wooga.do-not-delete-me" | "com.wooga.do-not-delete-me" | true - "Deletes" | "upm-package" | true | "com.wooga.delete-me" | "" | true + deleteVerb | packageType | doesDelete | packageId | preinstalledPackage | isUpmPackage + "Does NOT delete" | "non-upm-package" | false | "com.wooga.do-not-delete-me" | "" | false + "Does NOT delete" | "preinstalled" | false | "com.wooga.do-not-delete-me" | "com.wooga.do-not-delete-me" | true + "Deletes" | "upm-package" | true | "com.wooga.delete-me" | "" | true } + def "Shared paket and unity install-dir install"() { given: def unityProjDir = projectDir @@ -495,8 +498,8 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures paketUnity { paketUpmPackageEnabled = true ${overrides ? - "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : - "" + "paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" : + "" } } """ @@ -507,7 +510,6 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures then: result.success def pkgJsonFile = new File(pktUnityInstallDir, "package.json") - pkgJsonFile.file manifestJson.file @@ -517,10 +519,10 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures pkgJson.entrySet().containsAll(overrides?.entrySet() ?: [].toSet()) where: - packageType | source | isUpmPackage | overrides - "upm-enabled" | "package-json" | true | null - "non-upm" | "generated" | false | null - "non-upm" | "overridden" | false | ["name": "com.custom.name"] + packageType | source | isUpmPackage | overrides + "upm-enabled" | "package-json" | true | null + "non-upm" | "generated" | false | null + "non-upm" | "overridden" | false | ["name": "com.custom.name"] } def "Shared paket and unity packages folder #deleteVerb #packageType package on non-incremental delete"() { @@ -560,10 +562,10 @@ class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixtures dependencyFile.exists() where: - deleteVerb | packageType | doesDelete | packageId | preinstalledPackage | isUpmPackage - "Does NOT delete" | "non-upm-package" | false | "com.wooga.do-not-delete-me" | "" | false - "Does NOT delete" | "preinstalled" | false | "com.wooga.do-not-delete-me" | "com.wooga.do-not-delete-me" | true - "Deletes" | "upm-package" | true | "com.wooga.delete-me" | "" | true + deleteVerb | packageType | doesDelete | packageId | preinstalledPackage | isUpmPackage + "Does NOT delete" | "non-upm-package" | false | "com.wooga.do-not-delete-me" | "" | false + "Does NOT delete" | "preinstalled" | false | "com.wooga.do-not-delete-me" | "com.wooga.do-not-delete-me" | true + "Deletes" | "upm-package" | true | "com.wooga.delete-me" | "" | true } diff --git a/src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixtures.groovy b/src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixturesTrait.groovy similarity index 87% rename from src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixtures.groovy rename to src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixturesTrait.groovy index e64a688..64203a6 100644 --- a/src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixtures.groovy +++ b/src/integrationTest/groovy/wooga/gradle/paket/unity/fixtures/PaketFixturesTrait.groovy @@ -1,27 +1,10 @@ package wooga.gradle.paket.unity.fixtures -import nebula.test.IntegrationSpec - -import java.nio.file.FileSystems import java.nio.file.Files -import java.nio.file.Path import java.util.stream.Collectors -class PaketFixtures implements PaketFixturesTrait { - - private IntegrationSpec spec - - PaketFixtures(IntegrationSpec spec) { - this.spec = spec - } - - @Override - File getProjectDir() { - return spec.projectDir - } -} - trait PaketFixturesTrait { + abstract File getProjectDir() File fakePaketPackage(String name, diff --git a/src/main/groovy/wooga/gradle/paket/FrameworkRestriction.groovy b/src/main/groovy/wooga/gradle/paket/FrameworkRestriction.groovy new file mode 100644 index 0000000..6e5116e --- /dev/null +++ b/src/main/groovy/wooga/gradle/paket/FrameworkRestriction.groovy @@ -0,0 +1,21 @@ +package wooga.gradle.paket + +/** + * Supported framework restriction. + * Reference + */ +enum FrameworkRestriction { + + Net35("net35"), + Net45("net45"), + NetStandard2("netstandard2.0") + + String getLabel(){ + label + } + private final String label + + FrameworkRestriction(String label) { + this.label = label + } +} diff --git a/src/main/groovy/wooga/gradle/paket/base/PaketPluginExtension.groovy b/src/main/groovy/wooga/gradle/paket/base/PaketPluginExtension.groovy index 2557140..d94b230 100644 --- a/src/main/groovy/wooga/gradle/paket/base/PaketPluginExtension.groovy +++ b/src/main/groovy/wooga/gradle/paket/base/PaketPluginExtension.groovy @@ -18,7 +18,7 @@ package wooga.gradle.paket.base import wooga.gradle.paket.base.dependencies.PaketDependencyHandler -import wooga.gradle.paket.base.utils.PaketDependencies +import wooga.gradle.paket.base.utils.PaketDependenciesSpec /** * Base extension point for paket plugins. @@ -191,12 +191,12 @@ interface PaketPluginExtension { File getPaketLockFile() /** - * Returns the content of {@code paket.dependencies} parsed as {@link PaketDependencies} object. + * Returns the content of {@code paket.dependencies} parsed as {@link PaketDependenciesSpec} object. * * @return the parsed {@code paket.dependencies} file - * @see PaketDependencies + * @see PaketDependenciesSpec */ - PaketDependencies getPaketDependencies() + PaketDependenciesSpec getPaketDependencies() PaketDependencyHandler getDependencyHandler() } diff --git a/src/main/groovy/wooga/gradle/paket/base/utils/PaketDependencies.groovy b/src/main/groovy/wooga/gradle/paket/base/utils/PaketDependenciesSpec.groovy similarity index 79% rename from src/main/groovy/wooga/gradle/paket/base/utils/PaketDependencies.groovy rename to src/main/groovy/wooga/gradle/paket/base/utils/PaketDependenciesSpec.groovy index ed2fe62..cd7dfb9 100644 --- a/src/main/groovy/wooga/gradle/paket/base/utils/PaketDependencies.groovy +++ b/src/main/groovy/wooga/gradle/paket/base/utils/PaketDependenciesSpec.groovy @@ -20,26 +20,26 @@ package wooga.gradle.paket.base.utils /** * Object representation of a {@code paket.dependencies} file. */ -interface PaketDependencies { +interface PaketDependenciesSpec { /** - * Returns a {@link Set} of sources configured in {@code paket.dependencies} file. + * Returns a set of sources configured in {@code paket.dependencies} file. * * @return sources for paket to fetch dependencies from */ Set getSources() /** - * Returns a {@link Set} of {@code nuget} dependencies configured {@code paket.dependencies} file. + * Returns a set of {@code nuget} dependencies configured {@code paket.dependencies} file. * * @return all nuget dependencies in {@code paket.dependencies} file. */ Set getNugetDependencies() /** - * Returns a {@link List} of configured .NET frameworks. + * Returns as set of configured .NET frameworks. * @return list of .NET frameworks configured */ List getFrameworks() -} \ No newline at end of file +} diff --git a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketDependencies.groovy b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketDependencies.groovy index b2cbd9c..cb06413 100644 --- a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketDependencies.groovy +++ b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketDependencies.groovy @@ -17,35 +17,58 @@ package wooga.gradle.paket.base.utils.internal +import wooga.gradle.paket.FrameworkRestriction +import wooga.gradle.paket.base.utils.PaketDependenciesSpec import wooga.gradle.paket.unity.PaketUnityPluginConventions -class PaketDependencies implements wooga.gradle.paket.base.utils.PaketDependencies { +/** + * Object representation of a `paket.dependencies` file. + * https://fsprojects.github.io/Paket/dependencies-file.html + */ +class PaketDependencies implements PaketDependenciesSpec { PaketDependencies(File dependenciesFile) { this(dependenciesFile.text) } - private List nugets - private List dependencySources - private List frameworks + private Set dependencies = [] + private Set sources = [] + private List frameworks = [] + + Set getSources() { + sources + } + + Set getNugetDependencies() { + dependencies.collect({it.name}) + } + + List getFrameworks() { + if (frameworks == null || frameworks.empty){ + return PaketUnityPluginConventions.defaultFrameworks + } + frameworks + } PaketDependencies(String dependenciesContent) { - nugets = [] - dependencySources = [] dependenciesContent.eachLine { line -> def matcher if ((matcher = line =~ /^\s*([\w:]+)\s([\w\/:.(, )+]+)(.*)$/)) { + // First component def key = matcher[0][1].toString() + // Second component def value = matcher[0][2].toString().trim() switch (key) { case "nuget": - nugets << value + // Third component + def rule = matcher[0][3].toString().trim() + dependencies.add(new PaketDependencyDeclaration(value, rule, "nuget")) break case "source": - dependencySources << value + sources.add(value) break case "framework:": frameworks = value.split(",").collect { it.trim() } @@ -55,15 +78,72 @@ class PaketDependencies implements wooga.gradle.paket.base.utils.PaketDependenci } } - Set getSources() { - dependencySources + PaketDependencies(){ } - Set getNugetDependencies() { - nugets + @Override + String toString() { + def builder = new StringJoiner(System.lineSeparator()) + + sources.forEach({ + builder.add("source ${it}") + }) + + if (!frameworks.empty){ + builder.add("framework: ${frameworks.join(',')}") + } + + dependencies.forEach({ + builder.add("${it.source} ${it.name} ${it.rule}") + }) + + builder.toString().trim() } - List getFrameworks() { - frameworks ?: PaketUnityPluginConventions.defaultFrameworks + PaketDependencies withSource(String name) { + sources.add(name) + this + } + + PaketDependencies withNugetSource(int version = 2) { + withSource("https://nuget.org/api/v${version}") + } + + PaketDependencies withDependency(String name, String rule, String source = "nuget") { + dependencies.add(new PaketDependencyDeclaration(name, rule, source)) + this + } + + PaketDependencies withFrameworks(String... names) { + frameworks.addAll(names) + this + } + + PaketDependencies withFrameworks(FrameworkRestriction... values) { + frameworks.addAll(values.collect({it.label})) + this + } + + List getReferences(){ + + } + + + + +} + +/** + * A declaration for a paket dependency, in a `paket.dependencies` file. + * Such as {@code nuget Pancakes > 1.0}. + */ +class PaketDependencyDeclaration { + String source + String name + String rule + PaketDependencyDeclaration(String name, String rule, String source) { + this.name = name + this.rule = rule + this.source = source } } 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 a1b9e2d..820ab45 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 @@ -35,7 +35,10 @@ class PaketLock { enum LineType { - TYPE(0), REMOTE(1), NAME(2), DEPENDENCY(3) + TYPE(0), + REMOTE(1), + NAME(2), + DEPENDENCY(3) private final int value diff --git a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketUPMWrapperReference.groovy b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketUPMWrapperReference.groovy index b15d287..0ff60c3 100644 --- a/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketUPMWrapperReference.groovy +++ b/src/main/groovy/wooga/gradle/paket/base/utils/internal/PaketUPMWrapperReference.groovy @@ -1,10 +1,8 @@ package wooga.gradle.paket.base.utils.internal -import org.gradle.api.Project + import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging -import org.gradle.api.tasks.Input - /* * Copyright 2022 Wooga GmbH * @@ -22,6 +20,9 @@ import org.gradle.api.tasks.Input * */ +/** + * ??? + */ class PaketUPMWrapperReference { public String upmPackageNameUnversioned public String upmPackageName @@ -33,7 +34,7 @@ class PaketUPMWrapperReference { public final static String upmWrapperReferenceFile = "paket.upm.wrapper.reference" static Logger logger = Logging.getLogger(PaketUPMWrapperReference) - public static boolean IsReferenceFile(File file) { + static boolean IsReferenceFile(File file) { return file.name == upmWrapperReferenceFile } @@ -55,14 +56,8 @@ class PaketUPMWrapperReference { } } - PaketUPMWrapperReference(String nugetPackage, Project project) { - this(project.file("${getPackagesDirectory(project)}/${nugetPackage}/lib/${upmWrapperReferenceFile}")) + PaketUPMWrapperReference(File paketDirectory, String nugetPackage) { + this(new File(paketDirectory, "${nugetPackage}/lib/${upmWrapperReferenceFile}")) } - - public static String getPackagesDirectory(Project project) { - // this will return "Packages" on case-INsensitive FS and the proper "packages" in case-senitive FS - return project.file("packages").canonicalFile.name - } - } diff --git a/src/main/groovy/wooga/gradle/paket/get/PaketGetPlugin.groovy b/src/main/groovy/wooga/gradle/paket/get/PaketGetPlugin.groovy index 60431b9..bd544f4 100644 --- a/src/main/groovy/wooga/gradle/paket/get/PaketGetPlugin.groovy +++ b/src/main/groovy/wooga/gradle/paket/get/PaketGetPlugin.groovy @@ -19,9 +19,7 @@ package wooga.gradle.paket.get import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.tasks.TaskContainer -import org.gradle.api.tasks.TaskProvider import wooga.gradle.paket.base.PaketBasePlugin import wooga.gradle.paket.base.PaketPluginExtension import wooga.gradle.paket.base.utils.internal.PaketDependencies diff --git a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPlugin.groovy b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPlugin.groovy index 7cde69b..7ba2f39 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPlugin.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPlugin.groovy @@ -34,10 +34,8 @@ import wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages * Example: *
  * {@code
- *     plugins {
- *         id 'net.wooga.paket-unity' version '0.10.1'
- *     }
- * }
+ *     plugins {*         id 'net.wooga.paket-unity' version '0.10.1'
+ *}*}
  * 
*/ class PaketUnityPlugin implements Plugin { @@ -46,8 +44,11 @@ class PaketUnityPlugin implements Plugin { static final String GROUP = "PaketUnity" static final String EXTENSION_NAME = 'paketUnity' - static final String INSTALL_TASK_NAME = "paketUnityInstall" - static final String UNWRAP_UPM_TASK_NAME = "paketUnityUnwrapUPMPackages" + + static final String TASK_PREFIX = EXTENSION_NAME + static final String INSTALL_TASK_NAME = TASK_PREFIX + "Install" + static final String UNWRAP_UPM_TASK_NAME = TASK_PREFIX + "UnwrapUPMPackages" + @Override void apply(Project project) { this.project = project @@ -56,36 +57,56 @@ class PaketUnityPlugin implements Plugin { final PaketPluginExtension baseExtension = project.extensions.getByName(PaketBasePlugin.EXTENSION_NAME) as PaketPluginExtension final extension = project.extensions.create(EXTENSION_NAME, DefaultPaketUnityPluginExtension, project, baseExtension.dependencyHandler) + configureExtension(extension, project) createPaketUnityInstallTasks(project, extension) createPaketUpmUnwrapTasks(project, extension) - extension.assemblyDefinitionFileStrategy = PaketUnityPluginConventions.assemblyDefinitionFileStrategy - extension.paketUpmPackageEnabled.convention(PaketUnityPluginConventions.paketUpmPackageEnabled.getBooleanValueProvider(project)) - project.tasks.matching({ it.name.startsWith("paketUnity")}).configureEach { task -> + // Set the task predicates + project.tasks.matching({ it.name.startsWith(TASK_PREFIX) }).configureEach { task -> task.onlyIf { - extension.getPaketReferencesFiles() && !extension.getPaketReferencesFiles().isEmpty() && - extension.getPaketDependenciesFile() && extension.getPaketDependenciesFile().exists() && - extension.getPaketLockFile() && extension.getPaketLockFile().exists() + + if (!extension.paketReferencesFiles || extension.paketReferencesFiles.empty) { + logger.warn("Will skip ${it.name} as there are no paket reference files were found in the project") + return false + } + + if (!extension.paketDependenciesFile || !extension.paketDependenciesFile.exists()) { + logger.warn("Will skip ${it.name} as there are no paket dependencies files were found in the project") + return false + } + + if (!extension.paketLockFile || !extension.paketLockFile.exists()){ + logger.warn("Will skip ${it.name} as there are no paket lock files were found in the project") + return false + } + + return true } } configurePaketDependencyInstallIfPresent() } + private static void configureExtension(DefaultPaketUnityPluginExtension extension, Project project) { + extension.paketUpmPackageEnabled.convention(PaketUnityPluginConventions.paketUpmPackageEnabled.getBooleanValueProvider(project)) + extension.defaultUpmNamespace.convention(PaketUnityPluginConventions.defaultUpmNamespace.getStringValueProvider(project)) + } + private static void createPaketUnityInstallTasks(final Project project, final PaketUnityPluginExtension extension) { - def installProviders = extension.paketReferencesFiles.files.collect { referenceFile -> - def taskName = INSTALL_TASK_NAME + referenceFile.parentFile.name + + // Create an install task for EACH paket.unity3d.references file + def installProviders = extension.paketReferencesFiles.files.collect { referencesFile -> + def taskName = INSTALL_TASK_NAME + referencesFile.parentFile.name def installProvider = project.tasks.register(taskName, PaketUnityInstall) installProvider.configure { PaketUnityInstall t -> t.group = GROUP - t.description = "Installs dependencies for Unity3d project ${referenceFile.parentFile.name} " - t.conventionMapping.map("paketOutputDirectoryName", { extension.getPaketOutputDirectoryName() }) + t.description = "Installs dependencies for Unity3d project ${referencesFile.parentFile.name} " t.conventionMapping.map("includeAssemblyDefinitions", { extension.getIncludeAssemblyDefinitions() }) - t.conventionMapping.map("assemblyDefinitionFileStrategy", { extension.getAssemblyDefinitionFileStrategy() }) t.conventionMapping.map("preInstalledUpmPackages", { extension.getPreInstalledUpmPackages() }) t.frameworks = extension.getPaketDependencies().getFrameworks() t.lockFile = extension.getPaketLockFile() - t.referencesFile = referenceFile + t.defaultUpmNamespace.convention(extension.defaultUpmNamespace) + t.referencesFile = referencesFile t.paketUpmPackageEnabled.convention(extension.paketUpmPackageEnabled) t.paketUpmPackageManifests.convention(extension.paketUpmPackageManifests) } @@ -93,7 +114,7 @@ class PaketUnityPlugin implements Plugin { } def lifecycleTaskProvider = project.tasks.register(INSTALL_TASK_NAME) - lifecycleTaskProvider.configure {lifecycleTask -> + lifecycleTaskProvider.configure { lifecycleTask -> lifecycleTask.group = GROUP lifecycleTask.description = "Installs dependencies for all Unity3d projects" installProviders.each { installTaskProvider -> @@ -116,7 +137,7 @@ class PaketUnityPlugin implements Plugin { } def lifecycleTaskProvider = project.tasks.register(UNWRAP_UPM_TASK_NAME) - lifecycleTaskProvider.configure {lifecycleTask -> + lifecycleTaskProvider.configure { lifecycleTask -> lifecycleTask.group = GROUP lifecycleTask.description = "Unwraps Wrapped UPM dependencies for all Unity3d projects" unwrapProviders.each { unwrapTaskProvider -> @@ -139,10 +160,10 @@ class PaketUnityPlugin implements Plugin { project.tasks.withType(PaketUpdate).configureEach(configClosure) - [paketInstall, paketRestore].each {it.configure(configClosure) } + [paketInstall, paketRestore].each { it.configure(configClosure) } - project.tasks.withType(PaketUnityInstall).configureEach{ t -> t.finalizedBy(paketUpmUnwrap)} - paketUnityInstall.configure{t -> t.finalizedBy(paketUpmUnwrap)} + project.tasks.withType(PaketUnityInstall).configureEach { t -> t.finalizedBy(paketUpmUnwrap) } + paketUnityInstall.configure { t -> t.finalizedBy(paketUpmUnwrap) } } } diff --git a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginConventions.groovy b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginConventions.groovy index 24f1d84..021832e 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginConventions.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginConventions.groovy @@ -5,11 +5,6 @@ import wooga.gradle.paket.unity.internal.AssemblyDefinitionFileStrategy class PaketUnityPluginConventions { - /** - * Default strategy for handling the assembly definition files - */ - static final AssemblyDefinitionFileStrategy assemblyDefinitionFileStrategy = AssemblyDefinitionFileStrategy.disabled - /** * Whetehr to enable upm package support */ @@ -22,5 +17,10 @@ class PaketUnityPluginConventions { /** * Default NET frameworks that are to be installed onto the target directory */ - static final List defaultFrameworks = ["net11", "net20", "net35", "net45", "netstandard2.0"] + static final List defaultFrameworks = ["net20", "net35", "net45", "netstandard2.0"] + + /** + * Default namespace used for generated packages + */ + static PropertyLookup defaultUpmNamespace = new PropertyLookup("PAKET_UNITY_DEFAULT_UPM_NAMESPACE", "paketUnity.defaulUpmNamespace","com.wooga.nuget") } diff --git a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginExtension.groovy b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginExtension.groovy index 41074ec..2f9ab50 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginExtension.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/PaketUnityPluginExtension.groovy @@ -36,7 +36,9 @@ interface PaketUnityPluginExtension extends PaketPluginExtension, PaketUpmPackag /** * @return the paket unity output directory name. Relative to `/Assets` + * @deprecated No longer used since the resolution of the package directory is done internally */ + @Deprecated String getPaketOutputDirectoryName() /** @@ -45,18 +47,6 @@ interface PaketUnityPluginExtension extends PaketPluginExtension, PaketUpmPackag */ void setPaketOutputDirectoryName(String directory) - /** - * @return the assembly definition file strategy - */ - AssemblyDefinitionFileStrategy getAssemblyDefinitionFileStrategy() - - /** - * Sets the assembly definition strategy to be used during install. - * - * @param strategy the strategy to be used - */ - void setAssemblyDefinitionFileStrategy(AssemblyDefinitionFileStrategy strategy) - /** * Sets whether assembly definition files should be included during installation * @param value @@ -89,4 +79,4 @@ interface PaketUnityPluginExtension extends PaketPluginExtension, PaketUpmPackag * @return A list of pre-installed upm package id's, that should not be modified by the PaketUnityInstall task */ Provider> getPreInstalledUpmPackagesProvider() -} \ No newline at end of file +} diff --git a/src/main/groovy/wooga/gradle/paket/unity/PaketUpmPackageSpec.groovy b/src/main/groovy/wooga/gradle/paket/unity/PaketUpmPackageSpec.groovy index d403ebb..69350c3 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/PaketUpmPackageSpec.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/PaketUpmPackageSpec.groovy @@ -9,8 +9,6 @@ import org.gradle.api.tasks.Optional trait PaketUpmPackageSpec implements BaseSpec { - private final MapProperty> paketUpmPackageManifests = objects.mapProperty(String, Map) - /** * Map [: ] that overrides the contents of generated package.json files in UPM package mode. */ @@ -20,6 +18,8 @@ trait PaketUpmPackageSpec implements BaseSpec { return paketUpmPackageManifests } + private final MapProperty> paketUpmPackageManifests = objects.mapProperty(String, Map) + void setPaketUpmPackageManifests(Map paketUpmPackages) { this.paketUpmPackageManifests.set(paketUpmPackages) } @@ -29,7 +29,21 @@ trait PaketUpmPackageSpec implements BaseSpec { } - private final Property paketUpmPackageEnabled = objects.property(Boolean) + /** + * @return The default namespace when UPM packages are generated from paket. + * The default can be found in {@link PaketUnityPluginConventions} + */ + @Input + @Optional + Property getDefaultUpmNamespace() { + defaultUpmNamespace + } + + void setDefaultUpmNamespace(String value) { + defaultUpmNamespace.set(value) + } + + private Property defaultUpmNamespace = objects.property(String) /** * @@ -45,6 +59,8 @@ trait PaketUpmPackageSpec implements BaseSpec { paketUpmPackageEnabled.set(true) } + private final Property paketUpmPackageEnabled = objects.property(Boolean) + /** * Enables/Disables "UPM package mode" for paket. See {@code PaketUpmPackageSpec::enablePaketUpmPackages} for more details. */ diff --git a/src/main/groovy/wooga/gradle/paket/unity/internal/DefaultPaketUnityPluginExtension.groovy b/src/main/groovy/wooga/gradle/paket/unity/internal/DefaultPaketUnityPluginExtension.groovy index 7c9786f..2255f4d 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/internal/DefaultPaketUnityPluginExtension.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/internal/DefaultPaketUnityPluginExtension.groovy @@ -32,7 +32,6 @@ class DefaultPaketUnityPluginExtension extends DefaultPaketPluginExtension imple //This path is relative to the /Assets dir public static final String UNITY_PACKAGES_DIRECTORY = "../Packages" - protected AssemblyDefinitionFileStrategy assemblyDefinitionFileStrategy protected String customPaketOutputDirectory protected Boolean includeAssemblyDefinitions = false protected ListProperty preInstalledUpmPackages @@ -59,16 +58,6 @@ class DefaultPaketUnityPluginExtension extends DefaultPaketPluginExtension imple customPaketOutputDirectory = directory } - @Override - AssemblyDefinitionFileStrategy getAssemblyDefinitionFileStrategy() { - return assemblyDefinitionFileStrategy - } - - @Override - void setAssemblyDefinitionFileStrategy(AssemblyDefinitionFileStrategy strategy) { - assemblyDefinitionFileStrategy = strategy - } - @Override void setIncludeAssemblyDefinitions(Boolean value) { includeAssemblyDefinitions = value diff --git a/src/main/groovy/wooga/gradle/paket/unity/internal/NugetToUpmPackageIdCache.groovy b/src/main/groovy/wooga/gradle/paket/unity/internal/NugetToUpmPackageIdCache.groovy index ec72fb3..2348b62 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/internal/NugetToUpmPackageIdCache.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/internal/NugetToUpmPackageIdCache.groovy @@ -1,32 +1,45 @@ package wooga.gradle.paket.unity.internal + import groovy.json.JsonSlurper import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.api.provider.MapProperty -import wooga.gradle.paket.base.utils.internal.PaketUPMWrapperReference import java.nio.file.Files import java.nio.file.Path -class NugetToUpmPackageIdCache -{ - static final String PACKAGE_JSON = "package.json" - static final String NAME = "name" - static final String DISPLAY_NAME = "displayName" +/** + * Contains a cache of identifiers of Unity packages + * that are generated from nuget then converted into UPM. + */ +class NugetToUpmPackageIdCache { + + static final String packageManifestFileName = "package.json" + static final String namePropertyKey = "name" + static final String displayNamePropertyKey = "displayName" final Project project + final File paketPackagesDirectory final FileCollection inputFiles final File outputDirectory final MapProperty> paketUpmPackageManifests - Map nugetToUPMPackageIdCache = [:] as Map + Map nugetToUPMPackageIdCache = [:] as Map + final String defaultNamespace - NugetToUpmPackageIdCache(Project project, FileCollection inputs, File outputDirectory, MapProperty> packageManifests) { + NugetToUpmPackageIdCache(Project project, + File paketPackagesDirectory, + FileCollection inputs, + File outputDirectory, + MapProperty> packageManifests, + String namespace = "com.wooga.nuget") { this.project = project + this.paketPackagesDirectory = paketPackagesDirectory this.inputFiles = inputs this.outputDirectory = outputDirectory this.paketUpmPackageManifests = packageManifests + this.defaultNamespace = namespace populateCacheFromInputFiles() populateCacheFromOutputDirectory() @@ -36,8 +49,7 @@ class NugetToUpmPackageIdCache nugetToUPMPackageIdCache[nugetId] ?: generateUpmId(nugetId) } - boolean containsKey(String nugetId) - { + boolean containsKey(String nugetId) { nugetToUPMPackageIdCache.containsKey(nugetId) } @@ -46,18 +58,18 @@ class NugetToUpmPackageIdCache } private String generateUpmId(String paketId) { - def pkgJsonOverrides = paketUpmPackageManifests.getting(paketId)?.getOrElse([:]) - pkgJsonOverrides[NAME] ?: "com.wooga.nuget.${paketId.toLowerCase()}" + def manifestOverrides = paketUpmPackageManifests.getting(paketId)?.getOrElse([:]) + manifestOverrides[namePropertyKey] ?: "${defaultNamespace}.${paketId.toLowerCase()}" } private Path getAbsolutePath(String directory) { - project.file(directory).toPath().toAbsolutePath().normalize() + return project.file(directory).toPath().toAbsolutePath() } private Map findPackageJsons(Path dirPath) { Map map = [:] inputFiles.each { - if (it.name == PACKAGE_JSON) { + if (it.name == packageManifestFileName) { def relativePath = dirPath.relativize(getAbsolutePath(it.path)) def paketId = relativePath[0].toString() if (isNewOrCloserJson(relativePath, map[paketId])) map[paketId] = relativePath @@ -71,40 +83,42 @@ class NugetToUpmPackageIdCache } private void populateCacheFromInputFiles() { - def packagesDirPath = getAbsolutePath(PaketUPMWrapperReference.getPackagesDirectory(project)) - def packageJsonMap = findPackageJsons(packagesDirPath) + + def paketPackagesDirPath = paketPackagesDirectory.toPath() + def packageManifestMap = findPackageJsons(paketPackagesDirPath) inputFiles.each { - def relativePath = packagesDirPath.relativize(getAbsolutePath(it.path)) - def paketId = relativePath[0].toString() - if (!packageJsonMap.containsKey(paketId)) { + def filePath = getAbsolutePath(it.path) + def relativeFilePath = paketPackagesDirPath.relativize(filePath) + def paketId = relativeFilePath[0].toString() + if (!packageManifestMap.containsKey(paketId)) { def upmName = generateUpmId(paketId) nugetToUPMPackageIdCache[paketId] = upmName } } - packageJsonMap.each { paketId, packagePath -> - updateCacheFromPackageJson(packagesDirPath.resolve(packagePath), paketId) + packageManifestMap.each { paketId, packagePath -> + updateCacheFromPackageJson(paketPackagesDirPath.resolve(packagePath), paketId) } } private void updateCacheFromPackageJson(Path packagePath, String paketId) { if (Files.exists(packagePath)) { try { - def pkgJsonMap = new JsonSlurper().parse(packagePath) - if (pkgJsonMap.containsKey(NAME)) nugetToUPMPackageIdCache[paketId] = pkgJsonMap[NAME] + def packageManifest = new JsonSlurper().parse(packagePath) + if (packageManifest.containsKey(namePropertyKey)) nugetToUPMPackageIdCache[paketId] = packageManifest[namePropertyKey] } catch (Exception e) { - project.logger.error("Failed to parse ${PACKAGE_JSON}", e) + project.logger.error("Failed to parse ${packageManifestFileName}", e) } } } private void populateCacheFromOutputDirectory() { - def outputPackageJsons = findOutputPackageJsons() - outputPackageJsons.each { - def pkgJsonMap = new JsonSlurper().parse(it.value) - if (pkgJsonMap.containsKey(NAME) && pkgJsonMap.containsKey(DISPLAY_NAME)) { - def paketId = pkgJsonMap[DISPLAY_NAME] - if (!nugetToUPMPackageIdCache.containsKey(paketId)) nugetToUPMPackageIdCache[paketId] = pkgJsonMap[NAME] + def outputPackageManifests = findOutputPackageJsons() + outputPackageManifests.each { + def packageManifestMap = new JsonSlurper().parse(it.value) + if (packageManifestMap.containsKey(namePropertyKey) && packageManifestMap.containsKey(displayNamePropertyKey)) { + def paketId = packageManifestMap[displayNamePropertyKey] + if (!nugetToUPMPackageIdCache.containsKey(paketId)) nugetToUPMPackageIdCache[paketId] = packageManifestMap[namePropertyKey] } } } @@ -112,9 +126,23 @@ class NugetToUpmPackageIdCache private LinkedHashMap findOutputPackageJsons() { LinkedHashMap map = [:] project.fileTree(outputDirectory).visit { - if (it.name == PACKAGE_JSON) map[it.relativePath.segments[0]] = it.file + if (it.name == packageManifestFileName) map[it.relativePath.segments[0]] = it.file } return map } + // TODO: Parse the version? Though it's not needed since these end up getting consumed as "Custom" packages by Unity + Map generateManifest(String nugetId, Map overrides = [:]) { + + def upmmId = getUpmId(nugetId) + + Map base = [ + name : upmmId, + displayName: nugetId, + version : "0.0.0" + ] + base.putAll(overrides) + return base + } + } diff --git a/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPackageDirectory.groovy b/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPackageDirectory.groovy new file mode 100644 index 0000000..f60d341 --- /dev/null +++ b/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPackageDirectory.groovy @@ -0,0 +1,39 @@ +package wooga.gradle.paket.unity.internal + +import groovy.json.JsonOutput + +/** + * An UPM package. For details see: https://docs.unity3d.com/Manual/CustomPackages.html + */ +class UPMPackageDirectory { + + final File baseDir + final String name + + /** + * @return True if the directory exists in the file system + */ + boolean exists () { + baseDir.exists() + } + + /** + * @return A reference to the manifest file + */ + Optional getManifestFile() { + return Optional.ofNullable(new File(baseDir, "package.json")).map { + it.exists()? it : null + } + } + + UPMPackageDirectory(File paketPackageDir) { + this.baseDir = paketPackageDir + this.name = baseDir.name + } + + File writeManifest(Map contents) { + def createdPkgJson = new File(baseDir, "package.json") + createdPkgJson << JsonOutput.prettyPrint(JsonOutput.toJson(contents)) + return createdPkgJson + } +} diff --git a/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPaketPackage.groovy b/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPaketPackage.groovy deleted file mode 100644 index 1c2988e..0000000 --- a/src/main/groovy/wooga/gradle/paket/unity/internal/UPMPaketPackage.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package wooga.gradle.paket.unity.internal - -import groovy.json.JsonOutput - -class UPMPaketPackage { - - final File baseDir - final String name - - UPMPaketPackage(File paketPackageDir) { - this.baseDir = paketPackageDir - this.name = baseDir.name - } - - Optional getPackageManifest() { - return Optional.ofNullable(new File(baseDir, "package.json")).map { - it.exists()? it : null - } - } - - File writePackageManifest(Map contents) { - return writePackageManifest(baseDir, contents) - } - - static File writePackageManifest(File baseDir, Map contents) { - def createdPkgJson = new File(baseDir, "package.json") - createdPkgJson << JsonOutput.prettyPrint(JsonOutput.toJson(contents)) - return createdPkgJson - } - - static Map basicUPMPackageManifest(String packageName, String displayName, Map overrides = [:]) { - Map base = [ - name: packageName, - displayName: displayName, - version: "0.0.0" - ] - base.putAll(overrides) - return base - } - -} diff --git a/src/main/groovy/wooga/gradle/paket/unity/tasks/AbstractPaketUnityTask.groovy b/src/main/groovy/wooga/gradle/paket/unity/tasks/AbstractPaketUnityTask.groovy new file mode 100644 index 0000000..fad508a --- /dev/null +++ b/src/main/groovy/wooga/gradle/paket/unity/tasks/AbstractPaketUnityTask.groovy @@ -0,0 +1,88 @@ +package wooga.gradle.paket.unity.tasks + +import groovy.transform.Internal +import org.gradle.api.file.FileCollection +import org.gradle.api.internal.ConventionTask +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputDirectory +import wooga.gradle.paket.base.utils.internal.PaketLock +import wooga.gradle.paket.base.utils.internal.PaketUPMWrapperReference +import wooga.gradle.paket.base.utils.internal.PaketUnityReferences + +import java.util.function.Function + +/** + * A task that installs packages onto an Unity Project + */ +abstract class AbstractPaketUnityTask extends ConventionTask { + + /** + * @return the path to a {@code paket.unity3d.references} file + */ + @InputFile + File referencesFile + + /** + * @return the path to a {@code paket.lock} file + */ + @InputFile + File lockFile + + /** + * @return The directory where Unity packages installed by this task + * should be located + */ + @OutputDirectory + @Internal + abstract File getOutputDirectory() + + /** + * @return The path to where paket originally installs (extracts) the downloaded packages + */ + @org.gradle.api.tasks.Internal + File getPaketPackagesDirectory() { + // The MacOS Java implementation resolves 'Packages' and 'packages' in separate, as if it was on a unix system. + // However, MacOS actually treat those two folders as the same, so we use .canonicalPath to make sure that we get the + // correct capitalization on the existing folder. + def normalizedPath = new File(project.projectDir, "packages").canonicalPath + return new File(normalizedPath) + } + + /** + * @param packageName The name of the package + * @return True if the + */ + boolean isUPMWrapper(String packageName) { + return (new PaketUPMWrapperReference(paketPackagesDirectory, packageName)).exists + } + + /** + * @return The input files to use for the task based on the referenced nuget packages + */ + protected FileCollection collectInputFiles(Function> getFiles) { + Set files = [] + + if (!lockFile.exists()) { + return null + } + + def locks = new PaketLock(lockFile) + def references = new PaketUnityReferences(referencesFile) + def dependencies = locks.getAllDependencies(references.nugets) + dependencies.each { nugetId -> + files << getFiles(nugetId) + } + + project.files(files) + } + + /** + * Each UPM package has a manifest file with metadata about the package's contents + */ + static final String packageManifestFileName = "package.json" + + /** + * The extension used by Unity's assembly definition files + */ + final static String assemblyDefinitionFileExtension = "asmdef" +} diff --git a/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnityInstall.groovy b/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnityInstall.groovy index 6a49d97..ff2881b 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnityInstall.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnityInstall.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2018 Wooga GmbH + * Copyright 2018-2024 Wooga GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,26 +17,23 @@ package wooga.gradle.paket.unity.tasks - import org.apache.commons.io.FileUtils import org.gradle.api.Action import org.gradle.api.file.FileCollection import org.gradle.api.file.FileVisitDetails import org.gradle.api.file.FileVisitor -import org.gradle.api.internal.ConventionTask import org.gradle.api.tasks.* import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.InputFileDetails import wooga.gradle.paket.base.utils.internal.PaketLock -import wooga.gradle.paket.base.utils.internal.PaketUPMWrapperReference import wooga.gradle.paket.base.utils.internal.PaketUnityReferences import wooga.gradle.paket.unity.PaketUnityPlugin import wooga.gradle.paket.unity.PaketUpmPackageSpec -import wooga.gradle.paket.unity.internal.AssemblyDefinitionFileStrategy import wooga.gradle.paket.unity.internal.NugetToUpmPackageIdCache -import wooga.gradle.paket.unity.internal.UPMPaketPackage +import wooga.gradle.paket.unity.internal.UPMPackageDirectory import java.nio.file.Paths + /** * A task to copy referenced NuGet packages into Unity3D projects. *

@@ -48,24 +45,10 @@ import java.nio.file.Paths * task unityInstall(type:wooga.gradle.paket.unity.tasks.PaketUnityInstall) {* referencesFile = file('paket.unity3D.references') * lockFile = file('../paket.lock') * frameworks = ["net11", "net20", "net35"] - * paketOutputDirectoryName = "PaketUnity3D" *}*} * */ -class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { - static final String PACKAGE_JSON = "package.json" - - /** - * @return the path to a {@code paket.unity3d.references} file - */ - @InputFile - File referencesFile - - /** - * @return the path to a {@code paket.lock} file - */ - @InputFile - File lockFile +class PaketUnityInstall extends AbstractPaketUnityTask implements PaketUpmPackageSpec { /** * @return a list of .NET framework identifiers. @@ -73,12 +56,6 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { @Input List frameworks - /** - * The name of the output directory with the unity projects {@code Assets} folder. - */ - @Input - String paketOutputDirectoryName - /** * Whether assembly definition files (.asmdef) should be included during installation */ @@ -92,22 +69,19 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { @Optional List preInstalledUpmPackages - @Input - AssemblyDefinitionFileStrategy assemblyDefinitionFileStrategy - - // We need this cache, since the mapping from nuget to upm package Id exists only in the package.json of a package from the paket packages cache - // since this can get deleted, we need to look inside the not-yet-deleted unity upm package and deduce the nuget & paket Id from there. - @Internal - NugetToUpmPackageIdCache nugetToUpmId - - public final static String assemblyDefinitionFileExtension = "asmdef" - /** - * @return the installation output directory + * We need this cache, since the mapping from nuget to upm package Id exists only in the package.json of a package from the paket packages cache + * since this can get deleted, we need to look inside the not-yet-deleted unity upm package and deduce the nuget & paket Id from there. */ - @OutputDirectory + @Internal + NugetToUpmPackageIdCache nugetToUpmCache + + @Override File getOutputDirectory() { - new File(getReferencesFile().getParentFile(), "Assets/${getPaketOutputDirectoryName()}") + if (paketUpmPackageEnabled.get()){ + return new File(referencesFile.parentFile, "Packages") + } + new File(referencesFile.parentFile, "Assets/Paket.Unity3D") } /** @@ -115,23 +89,32 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { */ @InputFiles FileCollection getInputFiles() { - Set files = [] - def references = new PaketUnityReferences(getReferencesFile()) + collectInputFiles(nugetId -> { - if (!getLockFile().exists()) { - return null - } + if (isUPMWrapper(nugetId)){ + return new HashSet() + } + + def packagesDirectory = paketPackagesDirectory; + def fileTree = project.fileTree(packagesDirectory) + fileTree.include("${nugetId}/content/**") + + getFrameworks().each({ + fileTree.include("${nugetId}/lib/${it}/**") + }) + + fileTree.include("${nugetId}/lib/*.dll") + + fileTree.exclude("**/*.pdb") + fileTree.exclude("**/Meta") - def locks = new PaketLock(getLockFile()) - def dependencies = locks.getAllDependencies(references.nugets) - dependencies.each { nuget -> - if (!PaketUnwrapUPMPackages.isUPMWrapper(nuget, project)) { - def depFiles = getFilesForPackage(nuget) - files << depFiles + if (!getIncludeAssemblyDefinitions()) { + fileTree.exclude("**/*.${assemblyDefinitionFileExtension}") } - } - project.files(files) + def files = fileTree.files + return files + }) } PaketUnityInstall() { @@ -139,14 +122,14 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { group = PaketUnityPlugin.GROUP this.doLast { - if (isPaketUpmPackageEnabled().get()) { - def references = new PaketUnityReferences(getReferencesFile()) - def locks = new PaketLock(getLockFile()) + if (paketUpmPackageEnabled.get()) { + def references = new PaketUnityReferences(referencesFile) + def locks = new PaketLock(lockFile) def packages = [] - locks.getAllDependencies(references.nugets).each { nuget -> - if (!PaketUnwrapUPMPackages.isUPMWrapper(nuget, project) && nugetToUpmId.containsKey(nuget)) { - packages << [nuget, new File(outputDirectory, nugetToUpmId.getUpmId(nuget))] + locks.getAllDependencies(references.nugets).each { nugetId -> + if (!isUPMWrapper(nugetId) && nugetToUpmCache.containsKey(nugetId)) { + packages << [nugetId, new File(outputDirectory, nugetToUpmCache.getUpmId(nugetId))] } } @@ -158,79 +141,65 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { } /** - * @param nuget The name of the package - * @return The files to be copied over from this package + * Executes the copy of the packages downloaded by paket + * into the appropriate Unity project's package directory. + * @param inputs The input files */ - Set getFilesForPackage(String nuget) { - def packagesDirectory = getPackagesDirectory(); - def fileTree = project.fileTree(dir: project.projectDir) - fileTree.include("${packagesDirectory}/${nuget}/content/**") - - getFrameworks().each({ - fileTree.include("${packagesDirectory}/${nuget}/lib/${it}/**") - }) - - fileTree.include("${packagesDirectory}/${nuget}/lib/*.dll") - - fileTree.exclude("**/*.pdb") - fileTree.exclude("**/Meta") - - if (!getIncludeAssemblyDefinitions()) { - fileTree.exclude("**/*.${assemblyDefinitionFileExtension}") - } - - def files = fileTree.files - return files - } - - @Input - String getPackagesDirectory() { - PaketUPMWrapperReference.getPackagesDirectory(project) - } - @TaskAction protected performCopy(IncrementalTaskInputs inputs) { - logger.quiet("include libs with frameworks: " + getFrameworks().join(", ")) - if (isPaketUpmPackageEnabled().get()) { - logger.info("Update Nuget2Upm PackageId Cache") - nugetToUpmId = new NugetToUpmPackageIdCache(project, inputFiles, outputDirectory, paketUpmPackageManifests) - nugetToUpmId.dumpCacheToLog() + logger.quiet("> Now performing copy of packages from paket to Unity project. Will include libs with frameworks: " + getFrameworks().join(", ")) + + if (paketUpmPackageEnabled.get()) { + logger.info("> Will setup paket packages alongside the UPM packages") + nugetToUpmCache = new NugetToUpmPackageIdCache(project, + paketPackagesDirectory, + inputFiles, + outputDirectory, + paketUpmPackageManifests, + defaultUpmNamespace.get()) + + nugetToUpmCache.dumpCacheToLog() } if (!inputs.incremental) { - if (getOutputDirectory().exists()) { + if (outputDirectory.exists()) { cleanOutputDirectory() } } + // INSTALL/UPDATE inputs.outOfDate(new Action() { @Override void execute(InputFileDetails outOfDate) { if (inputFiles.contains(outOfDate.file)) { - def outputPath = transformInputToOutputPath(outOfDate.file, project.file(getPackagesDirectory())) - logger.info("${outOfDate.added ? "install" : "update"}: ${outputPath}") + // Compose the path where the package file should be copied to + def outputPath = transformInputToOutputPath(outOfDate.file) + logger.info("${outOfDate.added ? "+ INSTALL" : "+= UPDATE"}: ${outputPath}") FileUtils.copyFile(outOfDate.file, outputPath) assert outputPath.exists() } } }) + // REMOVE inputs.removed(new Action() { @Override void execute(InputFileDetails removed) { - logger.info("remove: ${removed.file}") + logger.info("- REMOVED: ${removed.file}") removed.file.delete() - def outputPath = transformInputToOutputPath(removed.file, project.file(getPackagesDirectory())) + + // Delete the files that were copied over from the paket packages + def outputPath = transformInputToOutputPath(removed.file) outputPath.delete() - // delete generated package.jsons - if (isPaketUpmPackageEnabled().get()) { - def relativePath = project.file(getPackagesDirectory()).toURI().relativize(removed.file.toURI()).getPath() - def paketId = relativePath.split("/").toList()[0] - def packageJson = Paths.get(getOutputDirectory().absolutePath, nugetToUpmId.getUpmId(paketId), PACKAGE_JSON).toFile() - def packageJsonMeta = Paths.get(getOutputDirectory().absolutePath, nugetToUpmId.getUpmId(paketId), "${PACKAGE_JSON}.meta").toFile() - if (packageJson.exists()) packageJson.delete() - if (packageJsonMeta.exists()) packageJsonMeta.delete() + // Delete generated package.jsons + if (paketUpmPackageEnabled.get()) { + def relativePath = paketPackagesDirectory.toURI().relativize(removed.file.toURI()).getPath() + def nugetId = relativePath.split("/").toList()[0] + def packageManifestFile = Paths.get(outputDirectory.absolutePath, nugetToUpmCache.getUpmId(nugetId), packageManifestFileName).toFile() + def packageManifestMetaFile = Paths.get(outputDirectory.absolutePath, nugetToUpmCache.getUpmId(nugetId), "${packageManifestFileName}.meta").toFile() + if (packageManifestFile.exists()) packageManifestFile.delete() + if (packageManifestMetaFile.exists()) packageManifestMetaFile.delete() } File parent = outputPath.parentFile @@ -247,41 +216,50 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { } protected void createPackageManifestIfNotExists(String nugetId, File packageDir) { - def upmPaket = new UPMPaketPackage(packageDir) - if(packageDir.exists() && !upmPaket.packageManifest.present) { - def pkgJsonOverrides = paketUpmPackageManifests.getting(upmPaket.name).getOrElse([:]) - def pkgJson = UPMPaketPackage.basicUPMPackageManifest(nugetToUpmId.getUpmId(nugetId), nugetId, pkgJsonOverrides) + def upmPackage = new UPMPackageDirectory(packageDir) + if (upmPackage.exists() && !upmPackage.manifestFile.present) { + + // Check for overrides that were assigned on an extension > task level. + // These overrides will be used whenever there's a match for a given nuget id + def overrides = paketUpmPackageManifests.getting(upmPackage.name).getOrElse([:]) + // Generate the default manifest contents + def packageManifest = nugetToUpmCache.generateManifest(nugetId, overrides) - upmPaket.writePackageManifest(pkgJson) - logger.info("generated package.json (${pkgJson['name']}) for $packageDir") + upmPackage.writeManifest(packageManifest) + + logger.info("generated package.json (${packageManifest['name']}) for $packageDir") } } + /** + * Cleans the output directory of both output package files + * and potentially assembly definition files + */ protected void cleanOutputDirectory() { - def tree = project.fileTree(getOutputDirectory()) - logger.info("delete files in directory: ${getOutputDirectory()}") + // THIS IS A PROBLEM IF THE PACKAGES DIRECTORY IS BOTH + // FOR PAKET AND UNITY PROJECT PACKAGES. + logger.info("> Now cleaning output directories") - // If the strategy is manual, do not delete asmdefs - if (getAssemblyDefinitionFileStrategy() == AssemblyDefinitionFileStrategy.manual) { - tree.exclude("**/*.asmdef") - tree.exclude("**/*.asmdef.meta") - } - if(isPaketUpmPackageEnabled().get()) { + // UPM MODE: If we installed paket packages onto the unity packages' directory + if (paketUpmPackageEnabled.get()) { def upmPackageDirs = [] - project.file(getOutputDirectory()).eachDir { - if ( !(it.name in preInstalledUpmPackages) && new File(it, PACKAGE_JSON).exists()) { + project.file(outputDirectory).eachDir { + if (!(it.name in preInstalledUpmPackages) && new File(it, packageManifestFileName).exists()) { upmPackageDirs << it } } upmPackageDirs.each { it.deleteDir() } - } else { - project.delete(tree) + } + // PAKET-ONLY LEGACY MODE: Delete the paket directory + else { + def tree = project.fileTree(outputDirectory) + project.delete(tree.files) } def emptyDirs = [] - project.fileTree(getOutputDirectory()).visit(new FileVisitor() { + project.fileTree(outputDirectory).visit(new FileVisitor() { @Override void visitDir(FileVisitDetails dirDetails) { File f = dirDetails.file @@ -298,22 +276,32 @@ class PaketUnityInstall extends ConventionTask implements PaketUpmPackageSpec { emptyDirs.reverseEach { it.delete() } } - private File transformInputToOutputPath(File inputFile, File baseDirectory) { - def relativePath = baseDirectory.toURI().relativize(inputFile.toURI()).getPath() - def pathSegments = relativePath.split("/").toList() - // removes the intermediary paket "content" folder + /** + * @param inputFile A file from an extracted nuget package directory + * @param paketDirectory The base directory for the file. It it used to extract a relative folder structure. + * @return A file mapped to the output directory, which keeps the same relative directory structure + */ + private File transformInputToOutputPath(File inputFile) { + + // We get the relative file structure from where the file was in the paket directory + inputFile = new File(inputFile.canonicalPath) + def relativePath = paketPackagesDirectory.toURI().relativize(inputFile.toURI()).path + + // Also remove the intermediary paket "content" folder + def pathSegments = relativePath.split('/').toList() pathSegments.remove(1) - if (isPaketUpmPackageEnabled().get()) { - def paketId = pathSegments.remove(0) - if(inputFile.name in [PACKAGE_JSON, "${PACKAGE_JSON}.meta"]) { - return Paths.get(getOutputDirectory().absolutePath, nugetToUpmId.getUpmId(paketId), inputFile.name).toFile() + if (paketUpmPackageEnabled.get()) { + def nugetId = pathSegments.remove(0) + if (inputFile.name in [packageManifestFileName, "${packageManifestFileName}.meta"]) { + return Paths.get(outputDirectory.absolutePath, nugetToUpmCache.getUpmId(nugetId), inputFile.name).toFile() } - // replace the paketId with upmId - pathSegments.add(0, nugetToUpmId.getUpmId(paketId)) - return new File(getOutputDirectory(), pathSegments.join(File.separator)) + // Replace the nugetId with upmId + pathSegments.add(0, nugetToUpmCache.getUpmId(nugetId)) + return new File(outputDirectory, pathSegments.join(File.separator)) } - return new File(getOutputDirectory(), pathSegments.join(File.separator)) + def file = new File(outputDirectory, pathSegments.join(File.separator)) + return file } } diff --git a/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnwrapUPMPackages.groovy b/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnwrapUPMPackages.groovy index d81c596..73cfc3c 100644 --- a/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnwrapUPMPackages.groovy +++ b/src/main/groovy/wooga/gradle/paket/unity/tasks/PaketUnwrapUPMPackages.groovy @@ -17,16 +17,12 @@ package wooga.gradle.paket.unity.tasks -import groovy.transform.Internal + import org.gradle.api.Action -import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.api.file.FileVisitDetails import org.gradle.api.file.FileVisitor -import org.gradle.api.internal.ConventionTask -import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.InputFileDetails @@ -43,62 +39,28 @@ import wooga.gradle.paket.unity.PaketUnityPlugin * Example: *

  * {@code
- *     task unwrapUpmPackages(type:wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages) {
- *         referencesFile = file('paket.unity3D.references')
+ *     task unwrapUpmPackages(type:wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages) {*         referencesFile = file('paket.unity3D.references')
  *         lockFile = file('../paket.lock')
- *     }
- * }
+ *}*}
  * 
*/ -class PaketUnwrapUPMPackages extends ConventionTask { - - /** - * @return the path to a {@code paket.unity3d.references} file - */ - @InputFile - File referencesFile - - /** - * @return the path to a {@code paket.lock} file - */ - @InputFile - File lockFile - - /** - * @return the installation output directory - */ - @OutputDirectory - @Internal - File getOutputDirectory() { - new File(getReferencesFile().getParentFile(), "Packages") - } +class PaketUnwrapUPMPackages extends AbstractPaketUnityTask { /** * @return the paket.upm.wrapper.reference's of the wrapper packages to unwrap into the Unity3D/Packages project. */ @InputFiles FileCollection getInputFiles() { - Set files = [] - def references = new PaketUnityReferences(getReferencesFile()) - - if (!getLockFile().exists()) { - return null - } - - def locks = new PaketLock(getLockFile()) - def dependencies = locks.getAllDependencies(references.nugets) - dependencies.each { nuget -> - def depFiles = getFilesForPackage(nuget) - files << depFiles - } - - project.files(files) + collectInputFiles(nugetId -> { + if (isUPMWrapper(nugetId)) { + return [new PaketUPMWrapperReference(paketPackagesDirectory, nugetId).file] as Set + } + }) } - Set getFilesForPackage(String nuget) { - if (isUPMWrapper(nuget, project)) { - return [new PaketUPMWrapperReference(nuget, project).file] as Set - } + @Override + File getOutputDirectory() { + return new File(referencesFile.parentFile, "Packages") } PaketUnwrapUPMPackages() { @@ -121,8 +83,8 @@ class PaketUnwrapUPMPackages extends ConventionTask { cleanLocalUpmOverride(upmWrapperRef) upmWrapperRef.upmPackageURL.startsWith("http") - ? new DownloadAndUnpackTar(upmWrapperRef, getOutputDirectory()).exec(project) - : new UnwrapUpm(upmWrapperRef, getOutputDirectory()).exec(project) + ? new DownloadAndUnpackTar(upmWrapperRef, outputDirectory).exec(project) + : new UnwrapUpm(upmWrapperRef, outputDirectory).exec(project) } } } @@ -144,22 +106,19 @@ class PaketUnwrapUPMPackages extends ConventionTask { }) } - public static boolean isUPMWrapper(String packageName, Project project) { - return (new PaketUPMWrapperReference(packageName, project)).exists - } private PaketUPMWrapperReference[] getWrappedUPMPackages() { - def references = new PaketUnityReferences(getReferencesFile()) + def references = new PaketUnityReferences(referencesFile) - if (!getLockFile().exists()) { + if (!lockFile.exists()) { return null } Set packages = [] - def locks = new PaketLock(getLockFile()) + def locks = new PaketLock(lockFile) def dependencies = locks.getAllDependencies(references.nugets) - dependencies.each { nuget -> - def upmPackage = new PaketUPMWrapperReference(nuget, project) + dependencies.each { nugetId -> + def upmPackage = new PaketUPMWrapperReference(paketPackagesDirectory, nugetId) if (upmPackage.exists) { packages << upmPackage } @@ -195,4 +154,6 @@ class PaketUnwrapUPMPackages extends ConventionTask { matchingPackageOverrideDirs.reverseEach { it.deleteDir() } } + + } diff --git a/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketDependenciesSpec.groovy b/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketDependenciesSpec.groovy index 31f35d8..d95667e 100644 --- a/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketDependenciesSpec.groovy +++ b/src/test/groovy/wooga/gradle/paket/base/utils/internal/PaketDependenciesSpec.groovy @@ -169,4 +169,21 @@ nuget Wooga.SbsSchurle >= 0.1.1 def frameworks = dependencies.frameworks frameworks.contains("net35") } + + @Unroll + def "Generate dependencies content"(){ + + when: + def expected = new PaketDependencies() + expected.withNugetSource() + expected.withFrameworks("netstandard2.0") + expected.withDependency("NSubstitute", "== 5.1.0") + + then: + def text = expected.toString() + def actual = new PaketDependencies(text) + expected.frameworks == actual.frameworks + expected.sources == actual.sources + expected.nugetDependencies == actual.nugetDependencies + } }