@@ -23,6 +23,44 @@ import org.scalasteward.core.repoconfig.PullRequestGroup
2323import org .scalasteward .core .util
2424import org .scalasteward .core .util .Nel
2525
26+ case class ArtifactForUpdate (
27+ crossDependency : CrossDependency ,
28+ newerGroupId : Option [GroupId ] = None ,
29+ newerArtifactId : Option [String ] = None
30+ ) {
31+ private val headDependency : Dependency = crossDependency.head
32+ def groupId : GroupId = headDependency.groupId
33+ def artifactId : ArtifactId = headDependency.artifactId
34+ def currentVersion : Version = headDependency.version
35+ }
36+
37+ trait ArtifactUpdateVersions {
38+ val artifactForUpdate : ArtifactForUpdate
39+
40+ val refersToUpdateVersions : Nel [Version ]
41+
42+ def show : String
43+ }
44+
45+ /**
46+ * Captures possible ''candidate'' newer versions that we may update an artifact to.
47+ *
48+ * Compare with the other subclass of [[ArtifactUpdateVersions ]], [[Update.ForArtifactId ]],
49+ * which denotes the specific ''single'' next version ultimately used in a PR.
50+ */
51+ case class ArtifactUpdateCandidates (
52+ artifactForUpdate : ArtifactForUpdate ,
53+ newerVersions : Nel [Version ]
54+ ) extends ArtifactUpdateVersions {
55+ override val refersToUpdateVersions : Nel [Version ] = newerVersions
56+
57+ def asSpecificUpdate (nextVersion : Version ): Update .ForArtifactId =
58+ Update .ForArtifactId (artifactForUpdate, nextVersion)
59+
60+ override def show : String =
61+ s " ${artifactForUpdate.groupId}: ${artifactForUpdate.crossDependency.showArtifactNames} : ${Version .show((artifactForUpdate.currentVersion +: refersToUpdateVersions.toList)* )}"
62+ }
63+
2664sealed trait Update {
2765
2866 def on [A ](update : Update .Single => A , grouped : Update .Grouped => A ): A = this match {
@@ -37,6 +75,13 @@ sealed trait Update {
3775
3876object Update {
3977
78+ /**
79+ * Denotes the update of one or more artifacts, which have all matched the same
80+ * `pullRequests.grouping` config rule.
81+ *
82+ * An `Update.Grouped` PR looks like this:
83+ * [[https://github.com/guardian/etag-caching/pull/62 ]]
84+ */
4085 final case class Grouped (
4186 name : String ,
4287 title : Option [String ],
@@ -49,47 +94,55 @@ object Update {
4994
5095 sealed trait Single extends Product with Serializable with Update {
5196 override val asSingleUpdates : List [Update .Single ] = List (this )
97+ def artifactsForUpdate : Nel [ArtifactForUpdate ]
5298 def forArtifactIds : Nel [ForArtifactId ]
5399 def crossDependencies : Nel [CrossDependency ]
54100 def dependencies : Nel [Dependency ]
55101 def groupId : GroupId
56102 def artifactIds : Nel [ArtifactId ]
57103 def mainArtifactId : String
104+ def showArtifacts : String
58105 def groupAndMainArtifactId : (GroupId , String ) = (groupId, mainArtifactId)
59106 def currentVersion : Version
60- def newerVersions : Nel [ Version ]
107+ def nextVersion : Version
61108
62109 final def name : String = Update .nameOf(groupId, mainArtifactId)
63110
64- final def nextVersion : Version = newerVersions.head
111+ final override def show : String =
112+ s " $groupId: $showArtifacts : ${Version .show(currentVersion, nextVersion)}"
65113
66- final override def show : String = {
67- val artifacts = this match {
68- case s : ForArtifactId => s.crossDependency.showArtifactNames
69- case g : ForGroupId => g.crossDependencies.map(_.showArtifactNames).mkString_(" {" , " , " , " }" )
70- }
71- val versions = {
72- val vs0 = (currentVersion :: newerVersions).toList
73- val vs1 = if (vs0.size > 6 ) vs0.take(3 ) ++ (" ..." :: vs0.takeRight(3 )) else vs0
74- vs1.mkString(" " , " -> " , " " )
75- }
76- s " $groupId: $artifacts : $versions"
77- }
78-
79- def withNewerVersions (versions : Nel [Version ]): Update .Single = this match {
80- case s @ ForArtifactId (_, _, _, _) =>
81- s.copy(newerVersions = versions)
82- case ForGroupId (forArtifactIds) =>
83- ForGroupId (forArtifactIds.map(_.copy(newerVersions = versions)))
114+ def withNextVersion (nextVersion : Version ): Update .Single = this match {
115+ case s : ForArtifactId =>
116+ s.copy(nextVersion = nextVersion)
117+ case g : ForGroupId =>
118+ g.copy(nextVersion = nextVersion)
84119 }
85120 }
86121
122+ /**
123+ * Denotes the update of a specific single artifact to some particular chosen next version.
124+ *
125+ * An update PR with a single `Update.ForArtifactId` looks like this:
126+ * [[https://github.com/guardian/etag-caching/pull/125 ]]
127+ *
128+ * In the other subclass of [[ArtifactUpdateVersions ]], [[ArtifactUpdateCandidates ]], _multiple_ possible candidate
129+ * newer versions are stored.
130+ */
87131 final case class ForArtifactId (
88- crossDependency : CrossDependency ,
89- newerVersions : Nel [Version ],
90- newerGroupId : Option [GroupId ] = None ,
91- newerArtifactId : Option [String ] = None
92- ) extends Single {
132+ artifactForUpdate : ArtifactForUpdate ,
133+ nextVersion : Version
134+ ) extends Single
135+ with ArtifactUpdateVersions {
136+ val crossDependency : CrossDependency = artifactForUpdate.crossDependency
137+
138+ override val refersToUpdateVersions : Nel [Version ] = Nel .one(nextVersion)
139+
140+ override def artifactsForUpdate : Nel [ArtifactForUpdate ] = Nel .one(artifactForUpdate)
141+
142+ override def showArtifacts : String = crossDependency.showArtifactNames
143+
144+ lazy val versionUpdate : Version .Update = Version .Update (currentVersion, nextVersion)
145+
93146 override def forArtifactIds : Nel [ForArtifactId ] =
94147 Nel .one(this )
95148
@@ -100,7 +153,7 @@ object Update {
100153 crossDependency.dependencies
101154
102155 override def groupId : GroupId =
103- crossDependency.head .groupId
156+ artifactForUpdate .groupId
104157
105158 override def artifactIds : Nel [ArtifactId ] =
106159 dependencies.map(_.artifactId)
@@ -109,17 +162,30 @@ object Update {
109162 artifactId.name
110163
111164 override def currentVersion : Version =
112- crossDependency.head.version
165+ artifactForUpdate.currentVersion
113166
114167 def artifactId : ArtifactId =
115- crossDependency.head .artifactId
168+ artifactForUpdate .artifactId
116169 }
117170
171+ /**
172+ * Denotes the update of several artifacts which all have the same Maven group-id,
173+ * and also are all are being updated ''from'' the same version, and updated ''to'' the same `nextVersion`.
174+ *
175+ * An `Update.ForGroupId` PR looks like this:
176+ * [[https://github.com/guardian/etag-caching/pull/128 ]]
177+ *
178+ */
118179 final case class ForGroupId (
119- forArtifactIds : Nel [ForArtifactId ]
180+ artifactsForUpdate : Nel [ArtifactForUpdate ],
181+ nextVersion : Version
120182 ) extends Single {
183+
184+ override def forArtifactIds : Nel [ForArtifactId ] =
185+ artifactsForUpdate.map(ForArtifactId (_, nextVersion))
186+
121187 override def crossDependencies : Nel [CrossDependency ] =
122- forArtifactIds .map(_.crossDependency)
188+ artifactsForUpdate .map(_.crossDependency)
123189
124190 override def dependencies : Nel [Dependency ] =
125191 crossDependencies.flatMap(_.dependencies)
@@ -142,12 +208,12 @@ object Update {
142208 .getOrElse(artifactIds.head.name)
143209 }
144210
211+ override def showArtifacts : String =
212+ crossDependencies.map(_.showArtifactNames).mkString_(" {" , " , " , " }" )
213+
145214 override def currentVersion : Version =
146215 dependencies.head.version
147216
148- override def newerVersions : Nel [Version ] =
149- forArtifactIds.head.newerVersions
150-
151217 def artifactIdsPrefix : Option [String ] =
152218 util.string.longestCommonPrefixGteq(artifactIds.map(_.name), 3 )
153219 }
@@ -163,19 +229,23 @@ object Update {
163229
164230 def groupByArtifactIdName (updates : List [ForArtifactId ]): List [ForArtifactId ] = {
165231 val groups0 =
166- updates.groupByNel(s => (s.groupId, s.artifactId.name, s.currentVersion, s.newerVersions ))
232+ updates.groupByNel(s => (s.groupId, s.artifactId.name, s.currentVersion, s.nextVersion ))
167233 val groups1 = groups0.values.map { group =>
168- val dependencies = group.flatMap(_.crossDependency.dependencies).distinct.sorted
169- group.head.copy(crossDependency = CrossDependency (dependencies))
234+ val dependencies = group.flatMap(_.dependencies).distinct.sorted
235+ val update : Update .ForArtifactId = group.head
236+ update.copy(artifactForUpdate =
237+ update.artifactForUpdate.copy(crossDependency = CrossDependency (dependencies))
238+ )
170239 }
171240 groups1.toList.distinct.sortBy(u => u : Update .Single )
172241 }
173242
174243 def groupByGroupId (updates : List [ForArtifactId ]): List [Single ] = {
175244 val groups0 =
176- updates.groupByNel(s => (s.groupId, s.currentVersion, s.newerVersions))
177- val groups1 = groups0.values.map { group =>
178- if (group.tail.isEmpty) group.head else ForGroupId (group)
245+ updates.groupByNel(s => (s.groupId, s.versionUpdate))
246+ val groups1 = groups0.map { case ((_, versionUpdate), group) =>
247+ if (group.tail.isEmpty) group.head
248+ else ForGroupId (group.map(_.artifactForUpdate), versionUpdate.nextVersion)
179249 }
180250 groups1.toList.distinct.sorted
181251 }
@@ -197,7 +267,7 @@ object Update {
197267 }
198268
199269 implicit val SingleOrder : Order [Single ] =
200- Order .by((u : Single ) => (u.crossDependencies, u.newerVersions ))
270+ Order .by((u : Single ) => (u.crossDependencies, u.nextVersion ))
201271
202272 // Encoder and Decoder instances
203273
@@ -206,19 +276,28 @@ object Update {
206276 implicit private val forArtifactIdEncoder : Encoder [ForArtifactId ] =
207277 Encoder .forProduct1(" ForArtifactId" )(identity[ForArtifactId ]) {
208278 Encoder .forProduct4(" crossDependency" , " newerVersions" , " newerGroupId" , " newerArtifactId" ) {
209- s => (s.crossDependency, s.newerVersions, s.newerGroupId, s.newerArtifactId)
279+ s =>
280+ (
281+ s.crossDependency,
282+ Seq (s.nextVersion),
283+ s.artifactForUpdate.newerGroupId,
284+ s.artifactForUpdate.newerArtifactId
285+ )
210286 }
211287 }
212288
213289 private val unwrappedForArtifactIdDecoder : Decoder [ForArtifactId ] =
214290 Decoder .forProduct4(" crossDependency" , " newerVersions" , " newerGroupId" , " newerArtifactId" ) {
215291 (
216292 crossDependency : CrossDependency ,
217- newerVersions : Nel [Version ],
293+ newerVersions : List [Version ],
218294 newerGroupId : Option [GroupId ],
219295 newerArtifactId : Option [String ]
220296 ) =>
221- ForArtifactId (crossDependency, newerVersions, newerGroupId, newerArtifactId)
297+ ForArtifactId (
298+ ArtifactForUpdate (crossDependency, newerGroupId, newerArtifactId),
299+ newerVersions.head
300+ )
222301 }
223302
224303 private val forArtifactIdDecoderV2 =
@@ -236,7 +315,7 @@ object Update {
236315
237316 private val unwrappedForGroupIdDecoderV3 : Decoder [ForGroupId ] =
238317 Decoder .forProduct1(" forArtifactIds" ) { (forArtifactIds : Nel [ForArtifactId ]) =>
239- ForGroupId (forArtifactIds)
318+ ForGroupId (forArtifactIds.map(_.artifactForUpdate), forArtifactIds.head.nextVersion )
240319 }
241320
242321 private val forGroupIdDecoderV3 : Decoder [ForGroupId ] =
0 commit comments