mirror of https://github.com/sbt/sbt.git
Merge pull request #91 from scalacenter/clean-update
Deduplicate and remove deprecations in `IvyActions`
This commit is contained in:
commit
a3eb9fd1a2
|
|
@ -183,15 +183,10 @@ final class IvySbt(val configuration: IvyConfiguration) { self =>
|
||||||
*
|
*
|
||||||
* @param md - module descriptor of the original Ivy graph.
|
* @param md - module descriptor of the original Ivy graph.
|
||||||
*/
|
*/
|
||||||
private[sbt] def cleanCachedResolutionCache(md: ModuleDescriptor, log: Logger): Unit =
|
private[sbt] def cleanCachedResolutionCache(md: ModuleDescriptor, log: Logger): Unit = {
|
||||||
withIvy(log) { i =>
|
if (!configuration.updateOptions.cachedResolution) ()
|
||||||
val prOpt = Option(i.getSettings.getResolver(ProjectResolver.InterProject)) map {
|
else IvySbt.cachedResolutionResolveCache.clean()
|
||||||
case pr: ProjectResolver => pr
|
}
|
||||||
}
|
|
||||||
if (configuration.updateOptions.cachedResolution) {
|
|
||||||
IvySbt.cachedResolutionResolveCache.clean(md, prOpt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class Module(rawModuleSettings: ModuleSettings) {
|
final class Module(rawModuleSettings: ModuleSettings) {
|
||||||
val moduleSettings: ModuleSettings = IvySbt.substituteCross(rawModuleSettings)
|
val moduleSettings: ModuleSettings = IvySbt.substituteCross(rawModuleSettings)
|
||||||
|
|
|
||||||
|
|
@ -203,31 +203,18 @@ object IvyActions {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
* Updates one module's dependencies performing a dependency resolution and retrieval.
|
||||||
* 'updateConfig' configures the actual resolution and retrieval process.
|
*
|
||||||
*/
|
* The following mechanism uses ivy under the hood.
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
*
|
||||||
def update(
|
* @param module The module to be resolved.
|
||||||
module: IvySbt#Module,
|
* @param configuration The update configuration.
|
||||||
configuration: UpdateConfiguration,
|
* @param uwconfig The configuration to handle unresolved warnings.
|
||||||
log: Logger
|
* @param logicalClock The clock necessary to cache ivy.
|
||||||
): UpdateReport =
|
* @param depDir The base directory used for caching resolution.
|
||||||
updateEither(
|
* @param log The logger.
|
||||||
module,
|
* @return The result, either an unresolved warning or an update report. Note that this
|
||||||
configuration,
|
* update report will or will not be successful depending on the `missingOk` option.
|
||||||
UnresolvedWarningConfiguration(),
|
|
||||||
LogicalClock.unknown,
|
|
||||||
None,
|
|
||||||
log
|
|
||||||
) match {
|
|
||||||
case Right(r) => r
|
|
||||||
case Left(w) =>
|
|
||||||
throw w.resolveException
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
|
||||||
* 'updateConfig' configures the actual resolution and retrieval process.
|
|
||||||
*/
|
*/
|
||||||
private[sbt] def updateEither(
|
private[sbt] def updateEither(
|
||||||
module: IvySbt#Module,
|
module: IvySbt#Module,
|
||||||
|
|
@ -236,58 +223,33 @@ object IvyActions {
|
||||||
logicalClock: LogicalClock,
|
logicalClock: LogicalClock,
|
||||||
depDir: Option[File],
|
depDir: Option[File],
|
||||||
log: Logger
|
log: Logger
|
||||||
): Either[UnresolvedWarning, UpdateReport] =
|
): Either[UnresolvedWarning, UpdateReport] = {
|
||||||
module.withModule(log) {
|
module.withModule(log) {
|
||||||
case (ivy, md, default)
|
case (ivy, moduleDescriptor, defaultConf) =>
|
||||||
if module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined =>
|
// Warn about duplicated and inconsistent dependencies
|
||||||
ivy.getResolveEngine match {
|
val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor)
|
||||||
case x: CachedResolutionResolveEngine =>
|
iw.foreach(log.warn(_))
|
||||||
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
|
||||||
iw foreach { log.warn(_) }
|
// Create inputs, resolve and retrieve the module descriptor
|
||||||
val resolveOptions = new ResolveOptions
|
val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log)
|
||||||
val resolveId = ResolveOptions.getDefaultResolveId(md)
|
val resolutionResult: Either[ResolveException, UpdateReport] = {
|
||||||
resolveOptions.setResolveId(resolveId)
|
if (module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined) {
|
||||||
resolveOptions.setArtifactFilter(configuration.artifactFilter)
|
val cache = depDir.getOrElse(sys.error("Missing directory for cached resolution."))
|
||||||
resolveOptions.setLog(ivyLogLevel(configuration.logging))
|
cachedResolveAndRetrieve(inputs, logicalClock, cache)
|
||||||
x.customResolve(
|
} else resolveAndRetrieve(inputs, defaultConf)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)(
|
def groupedConflicts[T](moduleFilter: ModuleFilter, grouping: ModuleID => T)(
|
||||||
report: UpdateReport
|
report: UpdateReport
|
||||||
): Map[T, Set[String]] =
|
): Map[T, Set[String]] =
|
||||||
|
|
@ -302,23 +264,6 @@ object IvyActions {
|
||||||
def grouped[T](grouping: ModuleID => T)(mods: Seq[ModuleID]): Map[T, Set[String]] =
|
def grouped[T](grouping: ModuleID => T)(mods: Seq[ModuleID]): Map[T, Set[String]] =
|
||||||
mods groupBy (grouping) mapValues (_.map(_.revision).toSet)
|
mods groupBy (grouping) mapValues (_.map(_.revision).toSet)
|
||||||
|
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
|
||||||
def transitiveScratch(
|
|
||||||
ivySbt: IvySbt,
|
|
||||||
label: String,
|
|
||||||
config: GetClassifiersConfiguration,
|
|
||||||
log: Logger
|
|
||||||
): UpdateReport =
|
|
||||||
transitiveScratch(
|
|
||||||
ivySbt,
|
|
||||||
label,
|
|
||||||
config,
|
|
||||||
UnresolvedWarningConfiguration(),
|
|
||||||
LogicalClock.unknown,
|
|
||||||
None,
|
|
||||||
log
|
|
||||||
)
|
|
||||||
|
|
||||||
private[sbt] def transitiveScratch(
|
private[sbt] def transitiveScratch(
|
||||||
ivySbt: IvySbt,
|
ivySbt: IvySbt,
|
||||||
label: String,
|
label: String,
|
||||||
|
|
@ -341,21 +286,6 @@ object IvyActions {
|
||||||
val newConfig = config.copy(module = mod.copy(modules = report.allModules))
|
val newConfig = config.copy(module = mod.copy(modules = report.allModules))
|
||||||
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, Vector(), log)
|
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, Vector(), log)
|
||||||
}
|
}
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
|
||||||
def updateClassifiers(
|
|
||||||
ivySbt: IvySbt,
|
|
||||||
config: GetClassifiersConfiguration,
|
|
||||||
log: Logger
|
|
||||||
): UpdateReport =
|
|
||||||
updateClassifiers(
|
|
||||||
ivySbt,
|
|
||||||
config,
|
|
||||||
UnresolvedWarningConfiguration(),
|
|
||||||
LogicalClock.unknown,
|
|
||||||
None,
|
|
||||||
Vector(),
|
|
||||||
log
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates explicit artifacts for each classifier in `config.module`, and then attempts to resolve them directly. This
|
* Creates explicit artifacts for each classifier in `config.module`, and then attempts to resolve them directly. This
|
||||||
|
|
@ -496,64 +426,114 @@ object IvyActions {
|
||||||
.withConfigurations(if (confs) m.configurations else None)
|
.withConfigurations(if (confs) m.configurations else None)
|
||||||
.branch(m.branchName)
|
.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,
|
ivy: Ivy,
|
||||||
module: DefaultModuleDescriptor,
|
module: DefaultModuleDescriptor,
|
||||||
defaultConf: String,
|
updateConfiguration: UpdateConfiguration,
|
||||||
filter: ArtifactTypeFilter
|
log: Logger
|
||||||
): (ResolveReport, Option[ResolveException]) = {
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 resolveOptions = new ResolveOptions
|
||||||
val resolveId = ResolveOptions.getDefaultResolveId(module)
|
val resolveId = ResolveOptions.getDefaultResolveId(moduleDescriptor)
|
||||||
resolveOptions.setResolveId(resolveId)
|
resolveOptions.setResolveId(resolveId)
|
||||||
resolveOptions.setArtifactFilter(filter)
|
resolveOptions.setArtifactFilter(updateConfiguration.artifactFilter)
|
||||||
resolveOptions.setLog(ivyLogLevel(logging))
|
resolveOptions.setLog(ivyLogLevel(logging))
|
||||||
ResolutionCache.cleanModule(
|
ResolutionCache.cleanModule(
|
||||||
module.getModuleRevisionId,
|
moduleDescriptor.getModuleRevisionId,
|
||||||
resolveId,
|
resolveId,
|
||||||
ivy.getSettings.getResolutionCacheManager
|
ivyInstance.getSettings.getResolutionCacheManager
|
||||||
)
|
)
|
||||||
val resolveReport = ivy.resolve(module, resolveOptions)
|
|
||||||
val err =
|
val resolveReport = ivyInstance.resolve(moduleDescriptor, resolveOptions)
|
||||||
if (resolveReport.hasError) {
|
if (resolveReport.hasError && !inputs.updateConfiguration.missingOk) {
|
||||||
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
// If strict error, collect report information and generated UnresolvedWarning
|
||||||
val failedPaths = Map(resolveReport.getUnresolvedDependencies map { node =>
|
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
||||||
val m = IvyRetrieve.toModuleID(node.getId)
|
val failedPaths = resolveReport.getUnresolvedDependencies.map { node =>
|
||||||
val path = IvyRetrieve.findPath(node, module.getModuleRevisionId) map { x =>
|
val moduleID = IvyRetrieve.toModuleID(node.getId)
|
||||||
IvyRetrieve.toModuleID(x.getId)
|
val path = IvyRetrieve
|
||||||
}
|
.findPath(node, moduleDescriptor.getModuleRevisionId)
|
||||||
m -> path
|
.map(x => IvyRetrieve.toModuleID(x.getId))
|
||||||
}: _*)
|
moduleID -> path
|
||||||
val failed = failedPaths.keys.toSeq
|
}.toMap
|
||||||
Some(new ResolveException(messages, failed, failedPaths))
|
val failedModules = failedPaths.keys.toSeq
|
||||||
} else None
|
Left(new ResolveException(messages, failedModules, failedPaths))
|
||||||
(resolveReport, err)
|
} 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,
|
|
||||||
report: UpdateReport,
|
|
||||||
config: RetrieveConfiguration
|
|
||||||
): UpdateReport =
|
|
||||||
retrieve(
|
|
||||||
log,
|
|
||||||
ivy,
|
|
||||||
report,
|
|
||||||
config.retrieveDirectory,
|
|
||||||
config.outputPattern,
|
|
||||||
config.sync,
|
|
||||||
config.configurationsToRetrieve
|
|
||||||
)
|
|
||||||
|
|
||||||
private def retrieve(
|
private def retrieve(
|
||||||
log: Logger,
|
log: Logger,
|
||||||
ivy: Ivy,
|
ivy: Ivy,
|
||||||
report: UpdateReport,
|
report: UpdateReport,
|
||||||
base: File,
|
config: RetrieveConfiguration
|
||||||
pattern: String,
|
|
||||||
sync: Boolean,
|
|
||||||
configurationsToRetrieve: Option[Set[Configuration]]
|
|
||||||
): UpdateReport = {
|
): UpdateReport = {
|
||||||
val configurationNames = configurationsToRetrieve match {
|
val toRetrieve = config.configurationsToRetrieve
|
||||||
|
val base = config.retrieveDirectory
|
||||||
|
val pattern = config.outputPattern
|
||||||
|
val configurationNames = toRetrieve match {
|
||||||
case None => None
|
case None => None
|
||||||
case Some(configs) => Some(configs.map(_.name))
|
case Some(configs) => Some(configs.map(_.name))
|
||||||
}
|
}
|
||||||
|
|
@ -569,7 +549,7 @@ object IvyActions {
|
||||||
}
|
}
|
||||||
IO.copy(toCopy)
|
IO.copy(toCopy)
|
||||||
val resolvedFiles = toCopy.map(_._2)
|
val resolvedFiles = toCopy.map(_._2)
|
||||||
if (sync) {
|
if (config.sync) {
|
||||||
val filesToDelete = existingFiles.filterNot(resolvedFiles.contains)
|
val filesToDelete = existingFiles.filterNot(resolvedFiles.contains)
|
||||||
filesToDelete foreach { f =>
|
filesToDelete foreach { f =>
|
||||||
log.info(s"Deleting old dependency: ${f.getAbsolutePath}")
|
log.info(s"Deleting old dependency: ${f.getAbsolutePath}")
|
||||||
|
|
@ -659,7 +639,8 @@ object IvyActions {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final class ResolveException(
|
|
||||||
|
private[sbt] final class ResolveException(
|
||||||
val messages: Seq[String],
|
val messages: Seq[String],
|
||||||
val failed: Seq[ModuleID],
|
val failed: Seq[ModuleID],
|
||||||
val failedPaths: Map[ModuleID, Seq[ModuleID]]
|
val failedPaths: Map[ModuleID, Seq[ModuleID]]
|
||||||
|
|
@ -697,13 +678,9 @@ object UnresolvedWarning {
|
||||||
(id, modulePosition(id))
|
(id, modulePosition(id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply(err, failedPaths)
|
|
||||||
}
|
|
||||||
private[sbt] def apply(
|
|
||||||
err: ResolveException,
|
|
||||||
failedPaths: Seq[Seq[(ModuleID, Option[SourcePosition])]]
|
|
||||||
): UnresolvedWarning =
|
|
||||||
new UnresolvedWarning(err, failedPaths)
|
new UnresolvedWarning(err, failedPaths)
|
||||||
|
}
|
||||||
|
|
||||||
private[sbt] def sourcePosStr(posOpt: Option[SourcePosition]): String =
|
private[sbt] def sourcePosStr(posOpt: Option[SourcePosition]): String =
|
||||||
posOpt match {
|
posOpt match {
|
||||||
case Some(LinePosition(path, start)) => s" ($path#L$start)"
|
case Some(LinePosition(path, start)) => s" ($path#L$start)"
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,8 @@ private[sbt] class CachedResolutionResolveCache {
|
||||||
val maxConflictCacheSize: Int = 1024
|
val maxConflictCacheSize: Int = 1024
|
||||||
val maxUpdateReportCacheSize: Int = 1024
|
val maxUpdateReportCacheSize: Int = 1024
|
||||||
|
|
||||||
def clean(md0: ModuleDescriptor, prOpt: Option[ProjectResolver]): Unit = {
|
def clean(): Unit = updateReportCache.clear
|
||||||
updateReportCache.clear
|
|
||||||
}
|
|
||||||
def directDependencies(md0: ModuleDescriptor): Vector[DependencyDescriptor] =
|
def directDependencies(md0: ModuleDescriptor): Vector[DependencyDescriptor] =
|
||||||
md0.getDependencies.toVector
|
md0.getDependencies.toVector
|
||||||
// Returns a vector of (module descriptor, changing, dd)
|
// Returns a vector of (module descriptor, changing, dd)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue