Skip to content
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

Support exclude attribute in Dep parser #3492

Merged
merged 2 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion docs/modules/ROOT/pages/Library_Dependencies.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ For more details about coursier, refer to the {link-coursier-doc}[coursier docum

== Dependencies in General

Mill dependencies have the form:
Mill dependencies have the simple form:

----
ivy"{organization}:{name}:{version}"
----

Additional attributes are also supported:

----
ivy"{organization}:{name}:{version}[;{attribute}={value}]*"
----

When working in other Java and Scala projects, you will find some synonyms, which typically all mean the same.

For example in the Maven ecosystem, the `organization` is called the `group` and the `name` is called the `artifact`.
Expand Down Expand Up @@ -225,6 +231,15 @@ def deps = Agg(

You can also use `.excludeOrg` or `excludeName`:

There is also a short notation available:

.Example: Shot notation to exclude `fansi_2.12` library from transitive dependency set of `pprint`.
[source,scala]
----
def deps = Agg(
ivy"com.lihaoyi::pprint:0.5.3;exclude=com.lihaoyi:fansi_2.12"
)
----

.Example: Exclude all `com.lihaoyi` libraries from transitive dependency set of `pprint`.
[source,scala]
Expand Down
13 changes: 11 additions & 2 deletions scalalib/src/mill/scalalib/Dep.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,17 @@ object Dep {
implicit def parse(signature: String): Dep = {
val parts = signature.split(';')
val module = parts.head
var exclusions = Seq.empty[(String, String)]
val attributes = parts.tail.foldLeft(coursier.Attributes()) { (as, s) =>
s.split('=') match {
case Array("classifier", v) => as.withClassifier(coursier.Classifier(v))
case Array("type", v) => as.withType(coursier.Type(v))
case Array("exclude", s"${org}:${name}") => exclusions ++= Seq((org, name)); as
case Array(k, v) => throw new Exception(s"Unrecognized attribute: [$s]")
case _ => throw new Exception(s"Unable to parse attribute specifier: [$s]")
}
}

(module.split(':') match {
case Array(a, b, c) => Dep(a, b, c, cross = empty(platformed = false))
case Array(a, b, "", c) => Dep(a, b, c, cross = empty(platformed = true))
Expand All @@ -122,7 +125,9 @@ object Dep {
case Array(a, "", "", b, c) => Dep(a, b, c, cross = Full(platformed = false))
case Array(a, "", "", b, "", c) => Dep(a, b, c, cross = Full(platformed = true))
case _ => throw new Exception(s"Unable to parse signature: [$signature]")
}).configure(attributes = attributes)
})
.exclude(exclusions.sorted: _*)
.configure(attributes = attributes)
}

@unused private implicit val depFormat: RW[Dependency] = mill.scalalib.JsonFormatters.depFormat
Expand All @@ -141,7 +146,11 @@ object Dep {
case "" => ""
case s => s";type=$s"
}
val attrs = classifierAttr + typeAttr

val excludeAttr =
dep.dep.exclusions().toSeq.sorted.map(e => s";exclude=${e._1.value}:${e._2.value}").mkString

val attrs = classifierAttr + typeAttr + excludeAttr

val prospective = dep.cross match {
case CrossVersion.Constant("", false) => Some(s"$org:$mod:$ver$attrs")
Expand Down
6 changes: 3 additions & 3 deletions scalalib/test/src/mill/scalalib/ResolveDepsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ object ResolveDepsTests extends TestSuite {

test("excludeTransitiveDeps") {
val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".exclude("com.lihaoyi" -> "fansi_2.12"))
assertRoundTrip(deps, simplified = false)
assertRoundTrip(deps, simplified = true)
val Success(paths) = evalDeps(deps)
assert(!paths.exists(_.path.toString.contains("fansi_2.12")))
}

test("excludeTransitiveDepsByOrg") {
val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".excludeOrg("com.lihaoyi"))
assertRoundTrip(deps, simplified = false)
assertRoundTrip(deps, simplified = true)
val Success(paths) = evalDeps(deps)
assert(!paths.exists(path =>
path.path.toString.contains("com/lihaoyi") && !path.path.toString.contains("pprint_2.12")
Expand All @@ -70,7 +70,7 @@ object ResolveDepsTests extends TestSuite {

test("excludeTransitiveDepsByName") {
val deps = Agg(ivy"com.lihaoyi::pprint:0.5.3".excludeName("fansi_2.12"))
assertRoundTrip(deps, simplified = false)
assertRoundTrip(deps, simplified = true)
val Success(paths) = evalDeps(deps)
assert(!paths.exists(_.path.toString.contains("fansi_2.12")))
}
Expand Down
Loading