diff --git a/librarymanagement/src/main/contraband/librarymanagement.json b/librarymanagement/src/main/contraband/librarymanagement.json index 810ecc1ac..d28da3b69 100644 --- a/librarymanagement/src/main/contraband/librarymanagement.json +++ b/librarymanagement/src/main/contraband/librarymanagement.json @@ -635,7 +635,8 @@ { "name": "missingOk", "type": "boolean" }, { "name": "logging", "type": "sbt.librarymanagement.UpdateLogging" }, { "name": "artifactFilter", "type": "sbt.librarymanagement.ArtifactTypeFilter" }, - { "name": "offline", "type": "boolean" } + { "name": "offline", "type": "boolean" }, + { "name": "frozen", "type": "boolean" } ] }, { diff --git a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/IvyActions.scala b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/IvyActions.scala index 4d8465a10..638aa4770 100644 --- a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/IvyActions.scala +++ b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/IvyActions.scala @@ -469,6 +469,10 @@ object IvyActions { resolveOptions.setArtifactFilter(updateConfiguration.artifactFilter) resolveOptions.setUseCacheOnly(updateConfiguration.offline) resolveOptions.setLog(ivyLogLevel(logging)) + if (updateConfiguration.frozen) { + resolveOptions.setTransitive(false) + resolveOptions.setCheckIfChanged(false) + } ResolutionCache.cleanModule( moduleDescriptor.getModuleRevisionId, resolveId, @@ -522,6 +526,10 @@ object IvyActions { resolveOptions.setArtifactFilter(updateConfiguration.artifactFilter) resolveOptions.setUseCacheOnly(updateConfiguration.offline) resolveOptions.setLog(ivyLogLevel(updateConfiguration.logging)) + if (updateConfiguration.frozen) { + resolveOptions.setTransitive(false) + resolveOptions.setCheckIfChanged(false) + } val acceptError = updateConfiguration.missingOk resolver.customResolve(descriptor, acceptError, logicalClock, resolveOptions, cache, log) } diff --git a/librarymanagement/src/main/scala/sbt/librarymanagement/DefaultLibraryManagement.scala b/librarymanagement/src/main/scala/sbt/librarymanagement/DefaultLibraryManagement.scala index 3c5d38167..49af3cb71 100644 --- a/librarymanagement/src/main/scala/sbt/librarymanagement/DefaultLibraryManagement.scala +++ b/librarymanagement/src/main/scala/sbt/librarymanagement/DefaultLibraryManagement.scala @@ -69,6 +69,7 @@ class DefaultLibraryManagement(ivyConfiguration: IvyConfiguration, log: Logger) true, UpdateLogging.DownloadOnly, artifactFilter, + false, false ) diff --git a/librarymanagement/src/test/scala/BaseIvySpecification.scala b/librarymanagement/src/test/scala/BaseIvySpecification.scala index 20041ab04..d87baa862 100644 --- a/librarymanagement/src/test/scala/BaseIvySpecification.scala +++ b/librarymanagement/src/test/scala/BaseIvySpecification.scala @@ -74,7 +74,8 @@ trait BaseIvySpecification extends UnitSpec { false, UpdateLogging.Full, ArtifactTypeFilter.forbid(Set("src", "doc")), - offline) + offline, + false) } def ivyUpdateEither(module: IvySbt#Module): Either[UnresolvedWarning, UpdateReport] = { diff --git a/librarymanagement/src/test/scala/FrozenModeSpec.scala b/librarymanagement/src/test/scala/FrozenModeSpec.scala new file mode 100644 index 000000000..e84abfe99 --- /dev/null +++ b/librarymanagement/src/test/scala/FrozenModeSpec.scala @@ -0,0 +1,55 @@ +package sbt.librarymanagement + +import sbt.internal.librarymanagement._ +import sbt.internal.librarymanagement.impl.DependencyBuilders + +class FrozenModeSpec extends BaseIvySpecification with DependencyBuilders { + private final val targetDir = Some(currentDependency) + private final val onlineConf = makeUpdateConfiguration(false) + private final val frozenConf = makeUpdateConfiguration(false).withFrozen(true) + private final val noClock = LogicalClock.unknown + private final val warningConf = UnresolvedWarningConfiguration() + private final val normalOptions = UpdateOptions() + + final val stoml = Vector("me.vican.jorge" % "stoml_2.12" % "0.4" % "compile") + + /* https://repo1.maven.org/maven2/me/vican/jorge/stoml_2.12/0.4/stoml_2.12-0.4.jar + * https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.0/scala-library-2.12.0.jar + * https://repo1.maven.org/maven2/com/lihaoyi/fastparse_2.12/0.4.2/fastparse_2.12-0.4.2.jar + * https://repo1.maven.org/maven2/com/lihaoyi/fastparse-utils_2.12/0.4.2/fastparse-utils_2.12-0.4.2.jar + * https://repo1.maven.org/maven2/com/lihaoyi/sourcecode_2.12/0.1.3/sourcecode_2.12-0.1.3.jar */ + final val explicitStoml = Vector( + "me.vican.jorge" % "stoml_2.12" % "0.4" % "compile", + "org.scala-lang" % "scala-library" % "2.12.0" % "compile", + "com.lihaoyi" % "fastparse_2.12" % "0.4.2" % "compile", + "com.lihaoyi" % "fastparse-utils_2.12" % "0.4.2" % "compile", + "com.lihaoyi" % "sourcecode_2.12" % "0.1.3" % "compile" + ) + + it should "fail when artifacts are missing in the cache" in { + cleanIvyCache() + def update(module: IvySbt#Module, conf: UpdateConfiguration) = + IvyActions.updateEither(module, conf, warningConf, noClock, targetDir, log) + + val toResolve = module(defaultModuleId, stoml, None, normalOptions) + val onlineResolution = update(toResolve, onlineConf) + assert(onlineResolution.isRight) + val numberResolved = onlineResolution.right.get.allModules.size + + cleanIvyCache() + val singleFrozenResolution = update(toResolve, frozenConf) + assert(singleFrozenResolution.isRight) + assert( + singleFrozenResolution.right.get.allModules.size == 1, + s"The number of explicit modules in frozen mode should 1" + ) + + cleanIvyCache() + // This relies on the fact that stoml has 5 transitive dependencies + val toExplicitResolve = module(defaultModuleId, explicitStoml, None, normalOptions) + val frozenResolution = update(toExplicitResolve, frozenConf) + assert(frozenResolution.isRight) + assert(frozenResolution.right.get.allModules.size == numberResolved, + s"The number of explicit modules in frozen mode should be equal than $numberResolved") + } +}