Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shorten
Dep
serialization format in common cases (#3490)
Fixes #3417 We do a best-effort approach where we try to reverse the `Dep.parse` logic, and at the end do a `==` check to see if the round tripped `Dep` is identical to the original. There's some overhead with the round trip comparison - effectively for each write-read of a `Dep` we add an additional `read` - but this isn't a hot code path so it shouldn't be a big deal. In exchange we get a pretty good guarantee of correctness that later on when someone round-trips the same `Dep` off of disk, they get the same result. We do the same for `BoundDep` and re-use most of the `Dep` logic The sophistication of our `def parse` and `def unparse` logic can be extended over time, but this should work well for 99% of dependencies which are simple without fancy exclusions, publication, configuration, optional, transitive, etc. Added some assertions to `ResolveDepsTests` to check the round tripping for common scenarios, both simplified and not Before: ```scala lihaoyi mill$ ./mill show main.api.ivyDeps [ { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "os-lib" }, "attributes": {} }, "version": "0.10.7-M1", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "cross": { "$type": "mill.scalalib.CrossVersion.Binary", "platformed": false }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "upickle" }, "attributes": {} }, "version": "3.3.1", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "cross": { "$type": "mill.scalalib.CrossVersion.Binary", "platformed": false }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "pprint" }, "attributes": {} }, "version": "0.9.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "cross": { "$type": "mill.scalalib.CrossVersion.Binary", "platformed": false }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "fansi" }, "attributes": {} }, "version": "0.5.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "cross": { "$type": "mill.scalalib.CrossVersion.Binary", "platformed": false }, "force": false }, { "dep": { "module": { "organization": { "value": "org.scala-sbt" }, "name": { "value": "test-interface" }, "attributes": {} }, "version": "1.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "cross": { "$type": "mill.scalalib.CrossVersion.Constant", "value": "", "platformed": false }, "force": false } ] lihaoyi mill$ ./mill show main.api.transitiveIvyDeps [ { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "os-lib_2.13" }, "attributes": {} }, "version": "0.10.7-M1", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "upickle_2.13" }, "attributes": {} }, "version": "3.3.1", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "pprint_2.13" }, "attributes": {} }, "version": "0.9.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "fansi_2.13" }, "attributes": {} }, "version": "0.5.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "org.scala-sbt" }, "name": { "value": "test-interface" }, "attributes": {} }, "version": "1.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "org.scala-lang" }, "name": { "value": "scala-library" }, "attributes": {} }, "version": "2.13.14", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": true }, { "dep": { "module": { "organization": { "value": "com.lihaoyi" }, "name": { "value": "mill-moduledefs_2.13" }, "attributes": {} }, "version": "0.11.0-M2", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false }, { "dep": { "module": { "organization": { "value": "com.kohlschutter.junixsocket" }, "name": { "value": "junixsocket-core" }, "attributes": {} }, "version": "2.10.0", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": false } ] ``` After: ```scala lihaoyi mill$ ./mill show main.api.ivyDeps [ "com.lihaoyi::os-lib:0.10.7-M1", "com.lihaoyi::upickle:3.3.1", "com.lihaoyi::pprint:0.9.0", "com.lihaoyi::fansi:0.5.0", "org.scala-sbt:test-interface:1.0" ] lihaoyi mill$ ./mill show main.api.transitiveIvyDeps [ "com.lihaoyi:os-lib_2.13:0.10.7-M1", "com.lihaoyi:upickle_2.13:3.3.1", "com.lihaoyi:pprint_2.13:0.9.0", "com.lihaoyi:fansi_2.13:0.5.0", "org.scala-sbt:test-interface:1.0", { "dep": { "module": { "organization": { "value": "org.scala-lang" }, "name": { "value": "scala-library" }, "attributes": {} }, "version": "2.13.14", "configuration": { "value": "default(compile)" }, "minimizedExclusions": { "data": "coursier.core.MinimizedExclusions.ExcludeNone" }, "publication": { "name": "", "type": { "value": "" }, "ext": { "value": "" }, "classifier": { "value": "" } }, "optional": false, "transitive": true }, "force": true }, "com.lihaoyi:mill-moduledefs_2.13:0.11.0-M2", "com.kohlschutter.junixsocket:junixsocket-core:2.10.0" ] ``` Note that `org.scala-lang:scala-library` is still using the old verbose serialization, due to `.forceVersion()` which makes it unable to be parsed/unparsed into a naked string literal as it needs a `.forceVersion()` call. We could make the shorthand serialization smarter to deal with this in future, but for now this is already a huge improvement over the status quo
- Loading branch information