-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IGN-10612 WIP DO NOT MERGE just for sharing code easily #57
Changes from 1 commit
54b121e
44ee58a
06930b7
6539bdb
738a9f5
376f0a2
22946e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,10 +28,11 @@ enum class IgnitionScope(val code: String) { | |
GATEWAY_DESIGNER("DG"), | ||
GATEWAY_DESIGNER_VISION_CLIENT("CDG"), | ||
GATEWAY_VISION_CLIENT("CG"), | ||
ALL("A"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mirrors the same thing in the Ignition codebase. |
||
NONE(""); | ||
|
||
companion object { | ||
private val VALID_SCOPES = Regex("^[GCD]+\$") | ||
private val VALID_SCOPES = Regex("^[AGCD]+\$") | ||
|
||
/** | ||
* Applies simplistic validation to the string and returns the corresponding scope if it can be determined. | ||
|
@@ -60,8 +61,20 @@ enum class IgnitionScope(val code: String) { | |
"CDG" -> GATEWAY_DESIGNER_VISION_CLIENT | ||
"DG" -> GATEWAY_DESIGNER | ||
"CG" -> GATEWAY_VISION_CLIENT | ||
"A" -> ALL | ||
else -> throw Exception("Could not determine IgnitionScope for shorthand '$code'") | ||
} | ||
} | ||
|
||
/** | ||
* Performs 'CDG'-to-'A' transform when applicable. | ||
*/ | ||
@JvmStatic | ||
@Throws(ModuleConfigException::class) | ||
fun promoteToAllWhenImplied(scopes: String): IgnitionScope = | ||
forShorthand(scopes).let { scope -> | ||
if (scope == GATEWAY_DESIGNER_VISION_CLIENT) | ||
ALL else scope | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ package io.ia.sdk.gradle.modl.task | |
|
||
import io.ia.sdk.gradle.modl.PLUGIN_TASK_GROUP | ||
import io.ia.sdk.gradle.modl.extension.ModuleDependencySpec | ||
import io.ia.sdk.gradle.modl.model.ArtifactManifest | ||
import io.ia.sdk.gradle.modl.model.IgnitionScope | ||
import io.ia.sdk.gradle.modl.model.artifactManifestFromJson | ||
import org.gradle.api.DefaultTask | ||
import org.gradle.api.file.RegularFile | ||
|
@@ -14,6 +16,7 @@ import org.gradle.api.tasks.InputFiles | |
import org.gradle.api.tasks.Optional | ||
import org.gradle.api.tasks.OutputFile | ||
import org.gradle.api.tasks.TaskAction | ||
import org.gradle.api.tasks.options.Option | ||
import org.redundent.kotlin.xml.PrintOptions | ||
import org.redundent.kotlin.xml.xml | ||
import java.io.File | ||
|
@@ -98,6 +101,23 @@ open class WriteModuleXml @Inject constructor(_objects: ObjectFactory) : Default | |
@get:Optional | ||
val docIndexPath: Property<String> = _objects.property(String::class.java) | ||
|
||
/** | ||
* Whether to fold and sort duplicate jars dependencies when the same appear | ||
* in more than one scope. | ||
* | ||
* Also converts implicit all scope string 'CDG' to 'A' and sorts jars by | ||
* scope string. | ||
* | ||
* Default is `false`. | ||
*/ | ||
@get:Input | ||
@get:Optional | ||
@Option( | ||
description = "Folds jars from multiple scopes into a single jar entry." | ||
) | ||
val foldJars: Property<Boolean> = _objects.property(Boolean::class.java) | ||
.convention(false) | ||
|
||
@OutputFile | ||
fun getModuleXmlFile(): File { | ||
return project.file("${project.buildDir}/moduleContent/module.xml") | ||
|
@@ -214,31 +234,70 @@ open class WriteModuleXml @Inject constructor(_objects: ObjectFactory) : Default | |
return false | ||
} | ||
|
||
// Manifests' artifacts, collect + sort by distinct scopes to de-dup them | ||
// Manifests' artifacts | ||
private fun manifests(): List<Pair<String, String>> = | ||
artifactManifests.get().map { manifest -> | ||
artifactManifestFromJson(manifest.asFile.readText(Charsets.UTF_8)) | ||
}.let { manifests -> | ||
manifests | ||
.flatMap { mani -> mani.artifacts } | ||
.groupBy { arti -> arti.jarName } | ||
.map { (jar, artifacts) -> | ||
val combinedScope = artifacts.fold(setOf<Char>()) { scope, arti -> | ||
scope.union( | ||
manifests | ||
.filter { mani -> arti in mani.artifacts } | ||
.flatMap { mani -> mani.scope.toList() } | ||
) | ||
}.joinToString("") | ||
|
||
jar to combinedScope | ||
}.sortedWith( | ||
compareByDescending<Pair<String, String>> { (_, scope) -> scope.length } | ||
.thenBy { (_, scope) -> scope } | ||
.thenBy { (jar, _) -> jar } | ||
) | ||
if (foldJars.get()) | ||
// more compact or else legacy dup-prone | ||
deduplicatedJars(manifests) else rawScopedJars(manifests) | ||
} | ||
|
||
// Collapse duplicate artifacts in different scopes to single scope string. | ||
// | ||
// IGN-10168 is backlogged to handle at least some of this upstream, | ||
// probably in or near `collectModlDependencies`. | ||
private fun deduplicatedJars( | ||
manifests: List<ArtifactManifest> | ||
): List<Pair<String, String>> = | ||
manifests | ||
.flatMap { mani -> mani.artifacts } | ||
.groupBy { arti -> arti.jarName } | ||
.map { (jar, artifacts) -> | ||
val combinedScope = artifacts.fold(setOf<Char>()) { scope, arti -> | ||
scope.union( | ||
manifests | ||
.filter { mani -> arti in mani.artifacts } | ||
.flatMap { mani -> mani.scope.toList() } | ||
) | ||
}.joinToString("") | ||
.let { scope -> | ||
// CDG > A formalized b/c we'll want it for IGN-10168 | ||
IgnitionScope.promoteToAllWhenImplied(scope).code | ||
} | ||
|
||
jar to combinedScope | ||
}.sortedWith( | ||
compareByDescending<Pair<String, String>> { (_, scope) -> scope.length } | ||
.thenBy { (_, scope) -> scope } | ||
.thenBy { (jar, _) -> jar } | ||
) | ||
|
||
// Leave duplicate artifacts largely as-is, even if present in 2+ scopes. | ||
// This is legacy behavior. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I regression tested this not only via unit test coverage in The only thing that failed--as expected--was the new So I'm pretty sure the logic that follows is equivalent to that before these PRs. I think the biggest difference is just refactoring to do pure transforms instead of nested |
||
private fun rawScopedJars( | ||
manifests: List<ArtifactManifest> | ||
): List<Pair<String, String>> = | ||
manifests | ||
.groupBy { mani -> mani.scope } | ||
.map { (scope, manis) -> | ||
val distinctJars = | ||
manis | ||
.flatMap { mani -> mani.artifacts } | ||
.fold(mutableSetOf<String>()) { jars, arti -> | ||
jars.apply { add(arti.jarName) } | ||
} | ||
|
||
scope to distinctJars | ||
}.fold(mutableListOf<Pair<String, String>>()) { lst, (scope, jars) -> | ||
lst.apply { | ||
addAll( | ||
jars.map { jar -> jar to scope } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Essentially, flipflop keys and values while flattening the original values. |
||
) | ||
} | ||
} | ||
|
||
fun writeXml(outputFile: File, moduleXml: String) { | ||
outputFile.writeText(moduleXml) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tricks everybody. Me. Others at IA. Probably everybody who has used it and the underlying JUnit call.