mirror of https://github.com/sbt/sbt.git
Remove coded uplication in `updateEither`
This commit reduces the code duplication in `updateEither` which was duplicating a good deal of the resolution logic to deal with the different resolution mechanisms: the simple one and the cached one. It also unifies the signatures of the helpers that are invoked by `updateEither`, removing the weirdness of the different return type signatures and ad-hoc logic handling.
This commit is contained in:
parent
b68498d013
commit
eea500d64f
|
|
@ -236,56 +236,32 @@ object IvyActions {
|
|||
logicalClock: LogicalClock,
|
||||
depDir: Option[File],
|
||||
log: Logger
|
||||
): Either[UnresolvedWarning, UpdateReport] =
|
||||
): Either[UnresolvedWarning, UpdateReport] = {
|
||||
module.withModule(log) {
|
||||
case (ivy, md, default)
|
||||
if module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined =>
|
||||
ivy.getResolveEngine match {
|
||||
case x: CachedResolutionResolveEngine =>
|
||||
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
||||
iw foreach { log.warn(_) }
|
||||
val resolveOptions = new ResolveOptions
|
||||
val resolveId = ResolveOptions.getDefaultResolveId(md)
|
||||
resolveOptions.setResolveId(resolveId)
|
||||
resolveOptions.setArtifactFilter(configuration.artifactFilter)
|
||||
resolveOptions.setLog(ivyLogLevel(configuration.logging))
|
||||
x.customResolve(
|
||||
md,
|
||||
configuration.missingOk,
|
||||
logicalClock,
|
||||
resolveOptions,
|
||||
depDir getOrElse {
|
||||
sys.error("dependency base directory is not specified")
|
||||
},
|
||||
log
|
||||
) match {
|
||||
case Left(x) =>
|
||||
Left(UnresolvedWarning(x, uwconfig))
|
||||
case Right(uReport) =>
|
||||
configuration.retrieve match {
|
||||
case Some(rConf) => Right(retrieve(log, ivy, uReport, rConf))
|
||||
case None => Right(uReport)
|
||||
}
|
||||
}
|
||||
}
|
||||
case (ivy, md, default) =>
|
||||
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
||||
iw foreach { log.warn(_) }
|
||||
val (report, err) =
|
||||
resolve(configuration.logging)(ivy, md, default, configuration.artifactFilter)
|
||||
err match {
|
||||
case Some(x) if !configuration.missingOk =>
|
||||
Left(UnresolvedWarning(x, uwconfig))
|
||||
case _ =>
|
||||
val cachedDescriptor = ivy.getSettings.getResolutionCacheManager
|
||||
.getResolvedIvyFileInCache(md.getModuleRevisionId)
|
||||
val uReport = IvyRetrieve.updateReport(report, cachedDescriptor)
|
||||
configuration.retrieve match {
|
||||
case Some(rConf) => Right(retrieve(log, ivy, uReport, rConf))
|
||||
case None => Right(uReport)
|
||||
}
|
||||
case (ivy, moduleDescriptor, defaultConf) =>
|
||||
// Warn about duplicated and inconsistent dependencies
|
||||
val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor)
|
||||
iw.foreach(log.warn(_))
|
||||
|
||||
// Create inputs, resolve and retrieve the module descriptor
|
||||
val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log)
|
||||
val resolutionResult: Either[ResolveException, UpdateReport] = {
|
||||
if (module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined) {
|
||||
val cache = depDir.getOrElse(sys.error("Missing directory for cached resolution."))
|
||||
cachedResolveAndRetrieve(inputs, logicalClock, cache)
|
||||
} else resolveAndRetrieve(inputs, defaultConf)
|
||||
}
|
||||
|
||||
// Convert to unresolved warning or retrieve update report
|
||||
resolutionResult.fold(
|
||||
exception => Left(UnresolvedWarning(exception, uwconfig)),
|
||||
updateReport => {
|
||||
val retrieveConf = configuration.retrieve
|
||||
Right(retrieveConf.map(retrieve(log, ivy, updateReport, _)).getOrElse(updateReport))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@deprecated("No longer used.", "0.13.6")
|
||||
def processUnresolved(err: ResolveException, log: Logger): Unit = ()
|
||||
def groupedConflicts[T](moduleFilter: ModuleFilter, grouping: ModuleID => T)(
|
||||
|
|
@ -496,38 +472,104 @@ object IvyActions {
|
|||
.withConfigurations(if (confs) m.configurations else None)
|
||||
.branch(m.branchName)
|
||||
|
||||
private[this] def resolve(logging: UpdateLogging)(
|
||||
/**
|
||||
* Represents the inputs to pass in to [[resolveAndRetrieve]] and [[cachedResolveAndRetrieve]].
|
||||
*
|
||||
* @param ivy The ivy instance to resolve and retrieve dependencies.
|
||||
* @param module The module descriptor to be resolved.
|
||||
* @param updateConfiguration The update configuration for [[ResolveOptions]].
|
||||
* @param log The logger.
|
||||
*/
|
||||
private case class ResolutionInputs(
|
||||
ivy: Ivy,
|
||||
module: DefaultModuleDescriptor,
|
||||
defaultConf: String,
|
||||
filter: ArtifactTypeFilter
|
||||
): (ResolveReport, Option[ResolveException]) = {
|
||||
updateConfiguration: UpdateConfiguration,
|
||||
log: Logger
|
||||
)
|
||||
|
||||
/**
|
||||
* Defines the internal entrypoint of module resolution and retrieval.
|
||||
*
|
||||
* This method is the responsible of populating [[ResolveOptions]] and pass
|
||||
* it in to the ivy instance to perform the module resolution.
|
||||
*
|
||||
* It returns an already resolved [[UpdateReport]] instead of a [[ResolveReport]]
|
||||
* like its counterpart [[CachedResolutionResolveEngine.customResolve]].
|
||||
*
|
||||
* @param inputs The resolution inputs.
|
||||
* @param defaultModuleConfiguration The default ivy configuration.
|
||||
* @return The result of the resolution.
|
||||
*/
|
||||
private[this] def resolveAndRetrieve(
|
||||
inputs: ResolutionInputs,
|
||||
defaultModuleConfiguration: String
|
||||
): Either[ResolveException, UpdateReport] = {
|
||||
// Populate resolve options from the passed arguments
|
||||
val ivyInstance = inputs.ivy
|
||||
val moduleDescriptor = inputs.module
|
||||
val updateConfiguration = inputs.updateConfiguration
|
||||
val logging = updateConfiguration.logging
|
||||
val resolveOptions = new ResolveOptions
|
||||
val resolveId = ResolveOptions.getDefaultResolveId(module)
|
||||
val resolveId = ResolveOptions.getDefaultResolveId(moduleDescriptor)
|
||||
resolveOptions.setResolveId(resolveId)
|
||||
resolveOptions.setArtifactFilter(filter)
|
||||
resolveOptions.setArtifactFilter(updateConfiguration.artifactFilter)
|
||||
resolveOptions.setLog(ivyLogLevel(logging))
|
||||
ResolutionCache.cleanModule(
|
||||
module.getModuleRevisionId,
|
||||
moduleDescriptor.getModuleRevisionId,
|
||||
resolveId,
|
||||
ivy.getSettings.getResolutionCacheManager
|
||||
ivyInstance.getSettings.getResolutionCacheManager
|
||||
)
|
||||
val resolveReport = ivy.resolve(module, resolveOptions)
|
||||
val err =
|
||||
if (resolveReport.hasError) {
|
||||
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
||||
val failedPaths = Map(resolveReport.getUnresolvedDependencies map { node =>
|
||||
val m = IvyRetrieve.toModuleID(node.getId)
|
||||
val path = IvyRetrieve.findPath(node, module.getModuleRevisionId) map { x =>
|
||||
IvyRetrieve.toModuleID(x.getId)
|
||||
}
|
||||
m -> path
|
||||
}: _*)
|
||||
val failed = failedPaths.keys.toSeq
|
||||
Some(new ResolveException(messages, failed, failedPaths))
|
||||
} else None
|
||||
(resolveReport, err)
|
||||
|
||||
val resolveReport = ivyInstance.resolve(moduleDescriptor, resolveOptions)
|
||||
if (resolveReport.hasError && !inputs.updateConfiguration.missingOk) {
|
||||
// If strict error, collect report information and generated UnresolvedWarning
|
||||
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
||||
val failedPaths = resolveReport.getUnresolvedDependencies.map { node =>
|
||||
val moduleID = IvyRetrieve.toModuleID(node.getId)
|
||||
val path = IvyRetrieve
|
||||
.findPath(node, moduleDescriptor.getModuleRevisionId)
|
||||
.map(x => IvyRetrieve.toModuleID(x.getId))
|
||||
moduleID -> path
|
||||
}.toMap
|
||||
val failedModules = failedPaths.keys.toSeq
|
||||
Left(new ResolveException(messages, failedModules, failedPaths))
|
||||
} else {
|
||||
// If no strict error, we convert the resolve report into an update report
|
||||
val cachedDescriptor = ivyInstance.getSettings.getResolutionCacheManager
|
||||
.getResolvedIvyFileInCache(moduleDescriptor.getModuleRevisionId)
|
||||
Right(IvyRetrieve.updateReport(resolveReport, cachedDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and retrieves a module with a cache mechanism defined
|
||||
* <a href="http://www.scala-sbt.org/0.13/docs/Cached-Resolution.html">here</a>.
|
||||
*
|
||||
* It's the cached version of [[resolveAndRetrieve]].
|
||||
*
|
||||
* @param inputs The resolution inputs.
|
||||
* @param logicalClock The clock to check if a file is outdated or not.
|
||||
* @param cache The optional cache dependency.
|
||||
* @return The result of the cached resolution.
|
||||
*/
|
||||
private[this] def cachedResolveAndRetrieve(
|
||||
inputs: ResolutionInputs,
|
||||
logicalClock: LogicalClock,
|
||||
cache: File
|
||||
): Either[ResolveException, UpdateReport] = {
|
||||
val log = inputs.log
|
||||
val descriptor = inputs.module
|
||||
val updateConfiguration = inputs.updateConfiguration
|
||||
val resolver = inputs.ivy.getResolveEngine.asInstanceOf[CachedResolutionResolveEngine]
|
||||
val resolveOptions = new ResolveOptions
|
||||
val resolveId = ResolveOptions.getDefaultResolveId(descriptor)
|
||||
resolveOptions.setResolveId(resolveId)
|
||||
resolveOptions.setArtifactFilter(updateConfiguration.artifactFilter)
|
||||
resolveOptions.setLog(ivyLogLevel(updateConfiguration.logging))
|
||||
val acceptError = updateConfiguration.missingOk
|
||||
resolver.customResolve(descriptor, acceptError, logicalClock, resolveOptions, cache, log)
|
||||
}
|
||||
|
||||
private def retrieve(
|
||||
log: Logger,
|
||||
ivy: Ivy,
|
||||
|
|
|
|||
Loading…
Reference in New Issue