Skip to content

Commit fa92db0

Browse files
authored
Improve formatting of long dependency reports (#12)
1 parent 6d31e7a commit fa92db0

File tree

10 files changed

+208
-86
lines changed

10 files changed

+208
-86
lines changed

build.sbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ libraryDependencies ++= Seq(
1818
).map(_ % circeVersion)
1919

2020
libraryDependencies ++= Seq(
21-
"org.scalatest" %% "scalatest" % "3.1.0" % Test
21+
"software.purpledragon" %% "text-utils" % "1.2.0",
22+
"org.scalatest" %% "scalatest" % "3.1.0" % Test
2223
)
2324

2425
organizationName := "Michael Stringer"

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sbt.version=1.3.2
1+
sbt.version=1.3.8

src/main/resources/messages.properties

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ lock.status.dependencies.none=no dependencies
2020
lock.status.dependencies.singular=1 dependency
2121
lock.status.dependencies.multiple={0} dependencies
2222

23+
# lockfile short status - artifacts ============================================
24+
lock.status.artifacts.changed.none=
25+
lock.status.artifacts.changed.singular=\ \ 1 dependency artifacts changed
26+
lock.status.artifacts.changed.multiple=\ \ {0} dependency artifacts changed
27+
2328
# lockfile full status - configurations =======================================
2429

2530
lock.status.full.configs.added.none=
@@ -44,11 +49,7 @@ lock.status.full.dependencies.changed.none=
4449
lock.status.full.dependencies.changed.singular=\ \ 1 dependency changed:\n{1}
4550
lock.status.full.dependencies.changed.multiple=\ \ {0} dependencies changed:\n{1}
4651

47-
#com.example:artifact:1.0 (compile,test)
48-
lock.status.full.dependency=\ \ \ \ {0}:{1}:{2} ({3})
49-
#com.example:artifact:[1.0]->[2.0] (compile,test)
50-
lock.status.full.dependency.changed.version=\ \ \ \ {0}:{1}:[{2}]->[{3}] ({4})
51-
#com.example:artifact:1.0 (compile,test)->(compile)
52-
lock.status.full.dependency.changed.configs=\ \ \ \ {0}:{1}:{2} ({4})->({5})
53-
#com.example:artifact:[1.0]->[2.0] (compile,test)->(compile)
54-
lock.status.full.dependency.changed.all=\ \ \ \ {0}:{1}:[{2}]->[{3}] ({4})->({5})
52+
# lockfile full status - artifacts ============================================
53+
lock.status.full.artifacts.changed.none=
54+
lock.status.full.artifacts.changed.singular=\ \ 1 dependency artifacts changed
55+
lock.status.full.artifacts.changed.multiple=\ \ {0} dependency artifacts changed

src/main/scala/software/purpledragon/sbt/lock/DependencyUtils.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import java.time.Instant
2121
import sbt._
2222
import software.purpledragon.sbt.lock.model.{DependencyLockFile, DependencyRef, ResolvedArtifact, ResolvedDependency}
2323

24-
import scala.collection.{immutable, mutable}
24+
import scala.collection.{immutable, mutable, SortedSet}
2525

2626
object DependencyUtils {
2727
def resolve(updateReport: UpdateReport, configs: Seq[ConfigRef]): DependencyLockFile = {
@@ -76,7 +76,12 @@ object DependencyUtils {
7676
ResolvedArtifact(s"${artifact.name}$qualifier.${artifact.extension}", hash)
7777
}
7878

79-
ResolvedDependency(module.module.organization, module.module.name, module.module.revision, artifacts, Set.empty)
79+
ResolvedDependency(
80+
module.module.organization,
81+
module.module.name,
82+
module.module.revision,
83+
artifacts.to[SortedSet],
84+
SortedSet.empty)
8085
}
8186

8287
private def hashFile(file: File): String = s"sha1:${Hash.toHex(Hash(file))}"

src/main/scala/software/purpledragon/sbt/lock/model/ChangedDependency.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@
1616

1717
package software.purpledragon.sbt.lock.model
1818

19+
import scala.collection.SortedSet
20+
1921
final case class ChangedDependency(
2022
org: String,
2123
name: String,
2224
oldVersion: String,
2325
newVersion: String,
24-
oldArtifacts: Seq[ResolvedArtifact],
25-
newArtifacts: Seq[ResolvedArtifact],
26-
oldConfigurations: Set[String],
27-
newConfigurations: Set[String]) {
26+
oldArtifacts: SortedSet[ResolvedArtifact],
27+
newArtifacts: SortedSet[ResolvedArtifact],
28+
oldConfigurations: SortedSet[String],
29+
newConfigurations: SortedSet[String]) {
2830

2931
def versionChanged: Boolean = oldVersion != newVersion
3032
def configurationsChanged: Boolean = oldConfigurations != newConfigurations

src/main/scala/software/purpledragon/sbt/lock/model/LockFileStatus.scala

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package software.purpledragon.sbt.lock.model
1818

1919
import software.purpledragon.sbt.lock.util.MessageUtil
20+
import software.purpledragon.text.TableFormatter
2021

2122
import scala.collection.mutable
2223

@@ -43,7 +44,8 @@ case object LockFileMatches extends LockFileStatus {
4344
LockFileDiffers(Nil, Nil, added, removed, changed)
4445
}
4546

46-
override val toShortReport: String = MessageUtil.formatMessage("lock.status.success")
47+
override val toShortReport: String =
48+
MessageUtil.formatMessage("lock.status.success")
4749
override val toLongReport: String = toShortReport
4850
}
4951

@@ -78,7 +80,9 @@ final case class LockFileDiffers(
7880
)
7981
}
8082

81-
if (addedDependencies.nonEmpty || removedDependencies.nonEmpty || changedDependencies.nonEmpty) {
83+
val (otherChanged, artifactChanged) = separateArtifactChanges(changedDependencies)
84+
85+
if (addedDependencies.nonEmpty || removedDependencies.nonEmpty || otherChanged.nonEmpty) {
8286
errors += MessageUtil.formatMessage(
8387
"lock.status.dependencies.info",
8488
MessageUtil.formatPlural("lock.status.dependencies", addedDependencies.size),
@@ -87,6 +91,10 @@ final case class LockFileDiffers(
8791
)
8892
}
8993

94+
if (artifactChanged.nonEmpty) {
95+
errors += MessageUtil.formatPlural("lock.status.artifacts.changed", artifactChanged.size)
96+
}
97+
9098
MessageUtil.formatMessage("lock.status.failed.short", errors.mkString("\n"))
9199
}
92100

@@ -108,16 +116,14 @@ final case class LockFileDiffers(
108116
}
109117

110118
def dumpDependencies(dependencies: Seq[ResolvedDependency]): String = {
111-
dependencies
112-
.map({ dep =>
113-
MessageUtil.formatMessage(
114-
"lock.status.full.dependency",
115-
dep.org,
116-
dep.name,
117-
dep.version,
118-
dep.configurations.toSeq.sorted.mkString(","))
119-
})
120-
.mkString("\n")
119+
val table =
120+
new TableFormatter(None, prefix = " ", stripTrailingNewline = true)
121+
122+
dependencies foreach { dep =>
123+
table.addRow(s"${dep.org}:${dep.name}", s"(${dep.configurations.mkString(",")})", dep.version)
124+
}
125+
126+
table.toString()
121127
}
122128

123129
if (addedDependencies.nonEmpty) {
@@ -134,31 +140,42 @@ final case class LockFileDiffers(
134140
dumpDependencies(removedDependencies))
135141
}
136142

137-
if (changedDependencies.nonEmpty) {
138-
val changeDetails = changedDependencies map { change =>
139-
val key = (change.versionChanged, change.configurationsChanged) match {
140-
case (true, true) => "lock.status.full.dependency.changed.all"
141-
case (true, false) => "lock.status.full.dependency.changed.version"
142-
case (false, true) => "lock.status.full.dependency.changed.configs"
143-
case _ => "error"
144-
}
145-
146-
MessageUtil.formatMessage(
147-
key,
148-
change.org,
149-
change.name,
143+
def dumpChanges(changes: Seq[ChangedDependency]): String = {
144+
val table = new TableFormatter(None, prefix = " ", stripTrailingNewline = true)
145+
146+
changes foreach { change =>
147+
table.addRow(
148+
s"${change.org}:${change.name}",
149+
s"(${change.oldConfigurations.mkString(",")})",
150+
if (change.configurationsChanged)
151+
s"-> (${change.newConfigurations.mkString(",")})"
152+
else "",
150153
change.oldVersion,
151-
change.newVersion,
152-
change.oldConfigurations.mkString(","),
153-
change.newConfigurations.mkString(","))
154+
if (change.versionChanged) s"-> ${change.newVersion}" else ""
155+
)
154156
}
155157

158+
table.toString()
159+
}
160+
161+
val (otherChanged, artifactChanged) = separateArtifactChanges(changedDependencies)
162+
163+
if (otherChanged.nonEmpty) {
156164
errors += MessageUtil.formatPlural(
157165
"lock.status.full.dependencies.changed",
158-
changedDependencies.size,
159-
changeDetails.mkString("\n"))
166+
otherChanged.size,
167+
dumpChanges(otherChanged))
168+
}
169+
170+
if (artifactChanged.nonEmpty) {
171+
errors += MessageUtil.formatPlural("lock.status.full.artifacts.changed", artifactChanged.size)
160172
}
161173

162174
MessageUtil.formatMessage("lock.status.failed.long", errors.mkString("\n"))
163175
}
176+
177+
private def separateArtifactChanges(
178+
changedDependencies: Seq[ChangedDependency]): (Seq[ChangedDependency], Seq[ChangedDependency]) = {
179+
changedDependencies.partition(change => change.configurationsChanged || change.versionChanged)
180+
}
164181
}

src/main/scala/software/purpledragon/sbt/lock/model/ResolvedArtifact.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@
1616

1717
package software.purpledragon.sbt.lock.model
1818

19-
final case class ResolvedArtifact(name: String, hash: String)
19+
import scala.math.Ordered.orderingToOrdered
20+
21+
final case class ResolvedArtifact(name: String, hash: String) extends Ordered[ResolvedArtifact] {
22+
override def compare(that: ResolvedArtifact): Int = {
23+
(name, hash) compare (that.name, that.hash)
24+
}
25+
}

src/main/scala/software/purpledragon/sbt/lock/model/ResolvedDependency.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616

1717
package software.purpledragon.sbt.lock.model
1818

19+
import scala.collection.SortedSet
1920
import scala.math.Ordered.orderingToOrdered
2021

2122
final case class ResolvedDependency(
2223
org: String,
2324
name: String,
2425
version: String,
25-
artifacts: Seq[ResolvedArtifact],
26-
configurations: Set[String])
26+
artifacts: SortedSet[ResolvedArtifact],
27+
configurations: SortedSet[String])
2728
extends Ordered[ResolvedDependency] {
2829

2930
override def compare(that: ResolvedDependency): Int = {

src/test/scala/software/purpledragon/sbt/lock/model/DependencyLockFileSpec.scala

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import java.time.Instant
2121
import org.scalatest.flatspec.AnyFlatSpec
2222
import org.scalatest.matchers.should.Matchers
2323

24+
import scala.collection.SortedSet
25+
2426
class DependencyLockFileSpec extends AnyFlatSpec with Matchers {
2527
private val EmptyLockFile = DependencyLockFile(1, Instant.now(), Nil, Nil)
2628
private val TestLockFile = DependencyLockFile(
@@ -32,9 +34,9 @@ class DependencyLockFileSpec extends AnyFlatSpec with Matchers {
3234
"com.example",
3335
"package-1",
3436
"1.0.0",
35-
Seq(ResolvedArtifact("package-1.jar", "hash-1")),
36-
Set("test-1")),
37-
ResolvedDependency("com.example", "package-2", "1.2.0", Nil, Set("test-2"))
37+
SortedSet(ResolvedArtifact("package-1.jar", "hash-1")),
38+
SortedSet("test-1")),
39+
ResolvedDependency("com.example", "package-2", "1.2.0", SortedSet.empty, SortedSet("test-2"))
3840
)
3941
)
4042

@@ -80,8 +82,8 @@ class DependencyLockFileSpec extends AnyFlatSpec with Matchers {
8082
"com.example",
8183
"package-3",
8284
"3.0",
83-
Seq(ResolvedArtifact("package-3.jar", "hash-3")),
84-
Set("test-1"))
85+
SortedSet(ResolvedArtifact("package-3.jar", "hash-3")),
86+
SortedSet("test-1"))
8587

8688
val left = TestLockFile
8789
val right = left.copy(dependencies = left.dependencies :+ newDependency)
@@ -103,8 +105,8 @@ class DependencyLockFileSpec extends AnyFlatSpec with Matchers {
103105
"com.example",
104106
"package-1",
105107
"2.0.0",
106-
Seq(ResolvedArtifact("package-1.jar", "hash-1a")),
107-
Set("test-1", "test-2"))
108+
SortedSet(ResolvedArtifact("package-1.jar", "hash-1a")),
109+
SortedSet("test-1", "test-2"))
108110
)
109111

110112
left.findChanges(right) shouldBe LockFileDiffers(
@@ -118,10 +120,10 @@ class DependencyLockFileSpec extends AnyFlatSpec with Matchers {
118120
"package-1",
119121
"1.0.0",
120122
"2.0.0",
121-
Seq(ResolvedArtifact("package-1.jar", "hash-1")),
122-
Seq(ResolvedArtifact("package-1.jar", "hash-1a")),
123-
Set("test-1"),
124-
Set("test-1", "test-2")
123+
SortedSet(ResolvedArtifact("package-1.jar", "hash-1")),
124+
SortedSet(ResolvedArtifact("package-1.jar", "hash-1a")),
125+
SortedSet("test-1"),
126+
SortedSet("test-1", "test-2")
125127
))
126128
)
127129
}

0 commit comments

Comments
 (0)