diff --git a/.travis.yml b/.travis.yml index d37eb6afa..edc99e178 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,14 @@ env: # WHITESOURCE_PASSWORD= - secure: d3bu2KNwsVHwfhbGgO+gmRfDKBJhfICdCJFGWKf2w3Gv86AJZX9nuTYRxz0KtdvEHO5Xw8WTBZLPb2thSJqhw9OCm4J8TBAVqCP0ruUj4+aqBUFy4bVexQ6WKE6nWHs4JPzPk8c6uC1LG3hMuzlC8RGETXtL/n81Ef1u7NjyXjs= matrix: - - SBT_CMD=";mimaReportBinaryIssues ;scalafmtCheckAll ;headerCheck ;test:headerCheck ;whitesourceOnPush ;test:compile ;mainSettingsProj/test ;safeUnitTests ;otherUnitTests; doc" + - SBT_CMD=";mimaReportBinaryIssues ;scalafmtCheckAll ;headerCheck ;test:headerCheck ;whitesourceOnPush ;test:compile; publishLocal ;mainSettingsProj/test ;safeUnitTests ;otherUnitTests; doc" - SBT_CMD="scripted actions/*" - SBT_CMD="scripted apiinfo/* compiler-project/* ivy-deps-management/*" - SBT_CMD="scripted dependency-management/*1of4" - SBT_CMD="scripted dependency-management/*2of4" - SBT_CMD="scripted dependency-management/*3of4" - SBT_CMD="scripted dependency-management/*4of4" + - SBT_CMD="scripted plugins/*" - SBT_CMD="scripted package/* reporter/* run/* project-load/*" - SBT_CMD="scripted project/*1of2" - SBT_CMD="scripted project/*2of2" diff --git a/build.sbt b/build.sbt index 1175d3216..344d3da69 100644 --- a/build.sbt +++ b/build.sbt @@ -606,7 +606,12 @@ lazy val mainProj = (project in file("main")) if (xs exists { s => s.contains(s""""$sv"""") }) () else sys.error("PluginCross.scala does not match up with the scalaVersion " + sv) }, - libraryDependencies ++= scalaXml.value ++ Seq(launcherInterface) ++ log4jDependencies ++ Seq(scalaCacheCaffeine), + libraryDependencies ++= { + scalaXml.value ++ + Seq(launcherInterface) ++ + log4jDependencies ++ + Seq(scalaCacheCaffeine, lmCoursierShaded) + }, Compile / scalacOptions -= "-Xfatal-warnings", managedSourceDirectories in Compile += baseDirectory.value / "src" / "main" / "contraband-scala", @@ -666,6 +671,7 @@ lazy val sbtProj = (project in file("sbt")) ) .configure(addSbtIO, addSbtCompilerBridge) +/* lazy val sbtBig = (project in file(".big")) .dependsOn(sbtProj) .settings( @@ -701,6 +707,7 @@ lazy val sbtBig = (project in file(".big")) }).transform(node).head }, ) +*/ lazy val sbtIgnoredProblems = { Vector( diff --git a/main-settings/src/main/scala/sbt/std/TaskMacro.scala b/main-settings/src/main/scala/sbt/std/TaskMacro.scala index 650914c7a..198b4adb1 100644 --- a/main-settings/src/main/scala/sbt/std/TaskMacro.scala +++ b/main-settings/src/main/scala/sbt/std/TaskMacro.scala @@ -450,6 +450,7 @@ object TaskMacro { def expand(nme: String, tpe: Type, tree: Tree): Converted[c.type] = nme match { case WrapInitTaskName => Converted.Success(wrapInitTask(tree)(c.WeakTypeTag(tpe))) + case WrapPreviousName => Converted.Success(wrapInitTask(tree)(c.WeakTypeTag(tpe))) case ParserInput.WrapInitName => Converted.Success(wrapInitParser(tree)(c.WeakTypeTag(tpe))) case WrapInitInputName => Converted.Success(wrapInitInput(tree)(c.WeakTypeTag(tpe))) case WrapInputName => Converted.Success(wrapInput(tree)(c.WeakTypeTag(tpe))) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 9d6232a41..7e82015ac 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -12,6 +12,7 @@ import java.net.{ URI, URL, URLClassLoader } import java.util.Optional import java.util.concurrent.{ Callable, TimeUnit } +import lmcoursier.definitions.{ Configuration => CConfiguration } import org.apache.ivy.core.module.descriptor.ModuleDescriptor import org.apache.ivy.core.module.id.ModuleRevisionId import sbt.Def.{ Initialize, ScopedKey, Setting, SettingsDefinition } @@ -200,6 +201,7 @@ object Defaults extends BuildCommon { exportJars :== false, trackInternalDependencies :== TrackLevel.TrackAlways, exportToInternal :== TrackLevel.TrackAlways, + useCoursier :== LibraryManagement.defaultUseCoursier, retrieveManaged :== false, retrieveManagedSync :== false, configurationsToRetrieve :== None, @@ -213,7 +215,7 @@ object Defaults extends BuildCommon { crossVersion :== Disabled(), buildDependencies := Classpaths.constructBuildDependencies.value, version :== "0.1.0-SNAPSHOT", - classpathTypes :== Set("jar", "bundle") ++ CustomPomParser.JarPackagings, + classpathTypes :== Set("jar", "bundle", "maven-plugin", "test-jar") ++ CustomPomParser.JarPackagings, artifactClassifier :== None, checksums := Classpaths.bootChecksums(appConfiguration.value), conflictManager := ConflictManager.default, @@ -224,7 +226,12 @@ object Defaults extends BuildCommon { pomAllRepositories :== false, pomIncludeRepository :== Classpaths.defaultRepositoryFilter, updateOptions := UpdateOptions(), - forceUpdatePeriod :== None + forceUpdatePeriod :== None, + // coursier settings + csrExtraCredentials :== Nil, + csrLogger :== None, + csrCachePath :== LMCoursier.defaultCacheLocation, + csrMavenProfiles :== Set.empty, ) /** Core non-plugin settings for sbt builds. These *must* be on every build or the sbt engine will fail to run at all. */ @@ -1909,6 +1916,7 @@ object Classpaths { managedClasspath := { val isMeta = isMetaBuild.value val force = reresolveSbtArtifacts.value + val csr = useCoursier.value val app = appConfiguration.value val sbtCp0 = app.provider.mainClasspath.toList val sbtCp = sbtCp0 map { Attributed.blank(_) } @@ -1917,7 +1925,7 @@ object Classpaths { classpathTypes.value, update.value ) - if (isMeta && !force) mjars ++ sbtCp + if (isMeta && !force && !csr) mjars ++ sbtCp else mjars }, exportedProducts := trackedExportedProducts(TrackLevel.TrackAlways).value, @@ -2125,6 +2133,18 @@ object Classpaths { }).value, moduleName := normalizedName.value, ivyPaths := IvyPaths(baseDirectory.value, bootIvyHome(appConfiguration.value)), + csrCachePath := { + val old = csrCachePath.value + val ip = ivyPaths.value + val defaultIvyCache = bootIvyHome(appConfiguration.value) + if (old != LMCoursier.defaultCacheLocation) old + else if (ip.ivyHome == defaultIvyCache) old + else + ip.ivyHome match { + case Some(home) => home / "coursier-cache" + case _ => old + } + }, dependencyCacheDirectory := { val st = state.value BuildPaths.getDependencyDirectory(st, BuildPaths.getGlobalBase(st)) @@ -2181,10 +2201,7 @@ object Classpaths { ) else None }, - dependencyResolution := IvyDependencyResolution( - ivyConfiguration.value, - CustomHttp.okhttpClient.value - ), + dependencyResolution := LibraryManagement.dependencyResolutionTask.value, publisher := IvyPublisher(ivyConfiguration.value, CustomHttp.okhttpClient.value), ivyConfiguration := mkIvyConfiguration.value, ivyConfigurations := { @@ -2198,6 +2215,44 @@ object Classpaths { if (managedScalaInstance.value && scalaHome.value.isEmpty) Configurations.ScalaTool :: Nil else Nil }, + // Coursier needs these + ivyConfigurations := { + val confs = ivyConfigurations.value + val names = confs.map(_.name).toSet + val extraSources = + if (names("sources")) + None + else + Some( + Configuration.of( + id = "Sources", + name = "sources", + description = "", + isPublic = true, + extendsConfigs = Vector.empty, + transitive = false + ) + ) + + val extraDocs = + if (names("docs")) + None + else + Some( + Configuration.of( + id = "Docs", + name = "docs", + description = "", + isPublic = true, + extendsConfigs = Vector.empty, + transitive = false + ) + ) + + val use = useCoursier.value + if (use) confs ++ extraSources.toSeq ++ extraDocs.toSeq + else confs + }, moduleSettings := moduleSettings0.value, makePomConfiguration := MakePomConfiguration() .withFile((artifactPath in makePom).value) @@ -2278,7 +2333,8 @@ object Classpaths { unresolvedWarningConfiguration in update := UnresolvedWarningConfiguration( dependencyPositions.value ), - update := (updateTask tag (Tags.Update, Tags.Network)).value, + updateFull := (updateTask tag (Tags.Update, Tags.Network)).value, + update := (updateWithoutDetails("update") tag (Tags.Update, Tags.Network)).value, update := { val report = update.value val log = streams.value.log @@ -2297,52 +2353,70 @@ object Classpaths { ew.infoAllTheThings foreach { log.info(_) } ew }, - classifiersModule in updateClassifiers := { - implicit val key = (m: ModuleID) => (m.organization, m.name, m.revision) - val projectDeps = projectDependencies.value.iterator.map(key).toSet - val externalModules = update.value.allModules.filterNot(m => projectDeps contains key(m)) - GetClassifiersModule( - projectID.value, - None, - externalModules, - ivyConfigurations.in(updateClassifiers).value.toVector, - transitiveClassifiers.in(updateClassifiers).value.toVector + ) ++ + inTask(updateClassifiers)( + Seq( + classifiersModule := { + implicit val key = (m: ModuleID) => (m.organization, m.name, m.revision) + val projectDeps = projectDependencies.value.iterator.map(key).toSet + val externalModules = update.value.allModules.filterNot(m => projectDeps contains key(m)) + GetClassifiersModule( + projectID.value, + None, + externalModules, + ivyConfigurations.value.toVector, + transitiveClassifiers.value.toVector + ) + }, + dependencyResolution := LibraryManagement.dependencyResolutionTask.value, + csrConfiguration := LMCoursier.coursierConfigurationTask(true, false).value, + updateClassifiers in TaskGlobal := (Def.task { + val s = streams.value + val is = ivySbt.value + val lm = dependencyResolution.value + val mod = classifiersModule.value + val updateConfig0 = updateConfiguration.value + val updateConfig = updateConfig0 + .withMetadataDirectory(dependencyCacheDirectory.value) + .withArtifactFilter( + updateConfig0.artifactFilter.map(af => af.withInverted(!af.inverted)) + ) + val app = appConfiguration.value + val srcTypes = sourceArtifactTypes.value + val docTypes = docArtifactTypes.value + val out = is.withIvy(s.log)(_.getSettings.getDefaultIvyUserDir) + val uwConfig = (unresolvedWarningConfiguration in update).value + withExcludes(out, mod.classifiers, lock(app)) { excludes => + lm.updateClassifiers( + GetClassifiersConfiguration( + mod, + excludes.toVector, + updateConfig, + // scalaModule, + srcTypes.toVector, + docTypes.toVector + ), + uwConfig, + Vector.empty, + s.log + ) match { + case Left(_) => ??? + case Right(ur) => ur + } + } + } tag (Tags.Update, Tags.Network)).value, ) - }, - updateClassifiers := (Def.task { - val s = streams.value - val is = ivySbt.value - val lm = dependencyResolution.value - val mod = (classifiersModule in updateClassifiers).value - val updateConfig0 = updateConfiguration.value - val updateConfig = updateConfig0 - .withMetadataDirectory(dependencyCacheDirectory.value) - .withArtifactFilter(updateConfig0.artifactFilter.map(af => af.withInverted(!af.inverted))) - val app = appConfiguration.value - val srcTypes = sourceArtifactTypes.value - val docTypes = docArtifactTypes.value - val out = is.withIvy(s.log)(_.getSettings.getDefaultIvyUserDir) - val uwConfig = (unresolvedWarningConfiguration in update).value - withExcludes(out, mod.classifiers, lock(app)) { excludes => - lm.updateClassifiers( - GetClassifiersConfiguration( - mod, - excludes.toVector, - updateConfig, - // scalaModule, - srcTypes.toVector, - docTypes.toVector - ), - uwConfig, - Vector.empty, - s.log - ) match { - case Left(_) => ??? - case Right(ur) => ur - } - } - } tag (Tags.Update, Tags.Network)).value - ) + ) ++ Seq( + csrProject := CoursierInputsTasks.coursierProjectTask.value, + csrConfiguration := LMCoursier.coursierConfigurationTask(false, false).value, + csrResolvers := CoursierRepositoriesTasks.coursierResolversTask.value, + csrRecursiveResolvers := CoursierRepositoriesTasks.coursierRecursiveResolversTask.value, + csrSbtResolvers := LMCoursier.coursierSbtResolversTask.value, + csrInterProjectDependencies := CoursierInputsTasks.coursierInterProjectDependenciesTask.value, + csrFallbackDependencies := CoursierInputsTasks.coursierFallbackDependenciesTask.value, + ) ++ + IvyXml.generateIvyXmlSettings() ++ + LMCoursier.publicationsSetting(Seq(Compile, Test).map(c => c -> CConfiguration(c.name))) val jvmBaseSettings: Seq[Setting[_]] = Seq( libraryDependencies ++= autoLibraryDependency( @@ -2375,19 +2449,18 @@ object Classpaths { val isMeta = isMetaBuild.value val force = reresolveSbtArtifacts.value val excludes = excludeDependencies.value - val sbtModules = Vector( - "sbt", - "zinc_2.12", - "librarymanagement-core_2.12", - "librarymanagement-ivy_2.12", - "util-logging_2.12", - "util-position_2.12", - "io_2.12" + val csr = useCoursier.value + val o = sbtdeps.organization + val sbtModulesExcludes = Vector[ExclusionRule]( + o % "sbt", + o %% "scripted-plugin", + o %% "librarymanagement-core", + o %% "librarymanagement-ivy", + o %% "util-logging", + o %% "util-position", + o %% "io" ) - val sbtModulesExcludes = sbtModules map { nm: String => - ExclusionRule(organization = sbtdeps.organization, name = nm) - } - if (isMeta && !force) excludes.toVector ++ sbtModulesExcludes + if (isMeta && !force && !csr) excludes.toVector ++ sbtModulesExcludes else excludes }, dependencyOverrides ++= { @@ -2503,10 +2576,8 @@ object Classpaths { ).withScalaOrganization(scalaOrganization.value) ) }, - dependencyResolution := IvyDependencyResolution( - ivyConfiguration.value, - CustomHttp.okhttpClient.value - ), + dependencyResolution := LibraryManagement.dependencyResolutionTask.value, + csrConfiguration := LMCoursier.coursierConfigurationTask(false, true).value, updateSbtClassifiers in TaskGlobal := (Def.task { val lm = dependencyResolution.value val s = streams.value @@ -2656,9 +2727,23 @@ object Classpaths { } } - def updateTask: Initialize[Task[UpdateReport]] = Def.task { + def updateTask: Initialize[Task[UpdateReport]] = updateTask0("updateFull", true, true) + def updateWithoutDetails(label: String): Initialize[Task[UpdateReport]] = + updateTask0(label, false, false) + + /** + * cacheLabel - label to identify an update cache + * includeCallers - include the caller information + * includeDetails - include module reports for the evicted modules + */ + private def updateTask0( + cacheLabel: String, + includeCallers: Boolean, + includeDetails: Boolean + ): Initialize[Task[UpdateReport]] = Def.task { val s = streams.value - val cacheDirectory = streams.value.cacheDirectory + val cacheDirectory = crossTarget.value / cacheLabel / updateCacheName.value + val cacheStoreFactory: CacheStoreFactory = CacheStoreFactory.directory(cacheDirectory) val isRoot = executionRoots.value contains resolvedScoped.value val shouldForce = isRoot || { @@ -2721,7 +2806,7 @@ object Classpaths { lm = dependencyResolution.value, // Ivy-free ModuleDescriptor module = ivyModule.value, - s.cacheStoreFactory.sub(updateCacheName.value), + cacheStoreFactory = cacheStoreFactory, label = label, updateConf, substituteScalaFiles(scalaOrganization.value, _)(providedScalaJars), @@ -2732,6 +2817,8 @@ object Classpaths { ewo = evictionOptions, mavenStyle = publishMavenStyle.value, compatWarning = compatibilityWarningOptions.value, + includeCallers = includeCallers, + includeDetails = includeDetails, log = s.log ) } diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 0f5894bbf..500e02f7c 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -32,6 +32,8 @@ import sbt.librarymanagement.ivy.{ Credentials, IvyConfiguration, IvyPaths, Upda import sbt.testing.Framework import sbt.util.{ Level, Logger } import xsbti.compile._ +import lmcoursier.definitions.CacheLogger +import lmcoursier.{ CoursierConfiguration, FallbackDependency } import scala.concurrent.duration.{ Duration, FiniteDuration } import scala.xml.{ NodeSeq, Node => XNode } @@ -351,6 +353,20 @@ object Keys { val fullClasspathAsJars = taskKey[Classpath]("The exported classpath, consisting of build products and unmanaged and managed, internal and external dependencies, all as JARs.") val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on") + val useCoursier = settingKey[Boolean]("Use Coursier for dependency resolution.").withRank(BSetting) + val csrCachePath = settingKey[File]("Coursier cache path").withRank(CSetting) + val csrMavenProfiles = settingKey[Set[String]]("").withRank(CSetting) + private[sbt] val csrConfiguration = taskKey[CoursierConfiguration]("General dependency management (Coursier) settings, such as the resolvers and options to use.").withRank(DTask) + private[sbt] val csrProject = taskKey[lmcoursier.definitions.Project]("") + private[sbt] val csrResolvers = taskKey[Seq[Resolver]]("") + private[sbt] val csrRecursiveResolvers = taskKey[Seq[Resolver]]("Resolvers of the current project, plus those of all from its inter-dependency projects") + private[sbt] val csrSbtResolvers = taskKey[Seq[Resolver]]("Resolvers used for sbt artifacts.") + private[sbt] val csrInterProjectDependencies = taskKey[Seq[lmcoursier.definitions.Project]]("Projects the current project depends on, possibly transitively") + private[sbt] val csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("") + private[sbt] val csrLogger = taskKey[Option[CacheLogger]]("") + private[sbt] val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("") + private[sbt] val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("") + val internalConfigurationMap = settingKey[Configuration => Configuration]("Maps configurations to the actual configuration used to define the classpath.").withRank(CSetting) val classpathConfiguration = taskKey[Configuration]("The configuration used to define the classpath.").withRank(CTask) val ivyConfiguration = taskKey[IvyConfiguration]("General dependency management (Ivy) settings, such as the resolvers and paths to use.").withRank(DTask) @@ -370,6 +386,7 @@ object Keys { val ivyModule = taskKey[IvySbt#Module]("Provides the sbt interface to a configured Ivy module.").withRank(CTask) val updateCacheName = taskKey[String]("Defines the directory name used to store the update cache files (inside the streams cacheDirectory).").withRank(DTask) val update = taskKey[UpdateReport]("Resolves and optionally retrieves dependencies, producing a report.").withRank(ATask) + val updateFull = taskKey[UpdateReport]("Resolves and optionally retrieves dependencies, producing a full report with callers.").withRank(CTask) val evicted = taskKey[EvictionWarning]("Display detailed eviction warnings.").withRank(CTask) val evictionWarningOptions = settingKey[EvictionWarningOptions]("Options on eviction warnings after resolving managed dependencies.").withRank(DSetting) val transitiveUpdate = taskKey[Seq[UpdateReport]]("UpdateReports for the internal dependencies of this project.").withRank(DTask) diff --git a/main/src/main/scala/sbt/Project.scala b/main/src/main/scala/sbt/Project.scala index 9a55a760a..d570c3432 100755 --- a/main/src/main/scala/sbt/Project.scala +++ b/main/src/main/scala/sbt/Project.scala @@ -758,6 +758,28 @@ object Project extends ProjectExtra { def updateExtraBuilds(s: State, f: List[URI] => List[URI]): State = setExtraBuilds(s, f(extraBuilds(s))) + // used by Coursier integration + private[sbt] def transitiveInterDependencies( + state: State, + projectRef: ProjectRef + ): Seq[ProjectRef] = { + def dependencies(map: Map[ProjectRef, Seq[ProjectRef]], id: ProjectRef): Set[ProjectRef] = { + def helper(map: Map[ProjectRef, Seq[ProjectRef]], acc: Set[ProjectRef]): Set[ProjectRef] = + if (acc.exists(map.contains)) { + val (kept, rem) = map.partition { case (k, _) => acc(k) } + helper(rem, acc ++ kept.valuesIterator.flatten) + } else + acc + helper(map - id, map.getOrElse(id, Nil).toSet) + } + val allProjectsDeps: Map[ProjectRef, Seq[ProjectRef]] = + (for { + (p, ref) <- Project.structure(state).allProjectPairs + } yield ref -> p.dependencies.map(_.project)).toMap + val deps = dependencies(allProjectsDeps.toMap, projectRef) + Project.structure(state).allProjectRefs.filter(p => deps(p)) + } + object LoadAction extends Enumeration { val Return, Current, Plugins = Value } diff --git a/main/src/main/scala/sbt/internal/BuildStructure.scala b/main/src/main/scala/sbt/internal/BuildStructure.scala index a1b556fe5..309e72844 100644 --- a/main/src/main/scala/sbt/internal/BuildStructure.scala +++ b/main/src/main/scala/sbt/internal/BuildStructure.scala @@ -38,6 +38,12 @@ final class BuildStructure( case (build, unit) => refs(build, unit.defined.values.toSeq) } def allProjectRefs(build: URI): Seq[ProjectRef] = refs(build, allProjects(build)) + def allProjectPairs: Seq[(ResolvedProject, ProjectRef)] = + for { + (build, unit) <- units.toSeq + p: ResolvedProject <- unit.defined.values.toSeq + } yield (p, ProjectRef(build, p.id)) + val extra: BuildUtil[ResolvedProject] = BuildUtil(root, units, index.keyIndex, data) private[this] def refs(build: URI, projects: Seq[ResolvedProject]): Seq[ProjectRef] = projects.map { p => diff --git a/main/src/main/scala/sbt/internal/LMCoursier.scala b/main/src/main/scala/sbt/internal/LMCoursier.scala new file mode 100644 index 000000000..ab159b13e --- /dev/null +++ b/main/src/main/scala/sbt/internal/LMCoursier.scala @@ -0,0 +1,126 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal + +import java.io.File +import lmcoursier.definitions.{ Classifier, Configuration => CConfiguration } +import lmcoursier._ +import sbt.librarymanagement._ +import Keys._ +import sbt.internal.librarymanagement.{ CoursierArtifactsTasks, CoursierInputsTasks } + +private[sbt] object LMCoursier { + def defaultCacheLocation: File = CoursierDependencyResolution.defaultCacheLocation + + def coursierConfigurationTask( + withClassifiers: Boolean, + sbtClassifiers: Boolean + ): Def.Initialize[Task[CoursierConfiguration]] = + Def.taskDyn { + val s = streams.value + val log = s.log + val resolversTask = + if (sbtClassifiers) + csrSbtResolvers + else + csrRecursiveResolvers + val classifiersTask: sbt.Def.Initialize[sbt.Task[Option[Seq[Classifier]]]] = + if (withClassifiers && !sbtClassifiers) + Def.task(Some(sbt.Keys.transitiveClassifiers.value.map(Classifier(_)))) + else + Def.task(None) + Def.task { + val rs = resolversTask.value + val scalaOrg = scalaOrganization.value + val scalaVer = scalaVersion.value + val interProjectDependencies = csrInterProjectDependencies.value + val excludeDeps = Inputs.exclusions( + allExcludeDependencies.value, + scalaVer, + scalaBinaryVersion.value, + streams.value.log + ) + val fallbackDeps = csrFallbackDependencies.value + val autoScalaLib = autoScalaLibrary.value && scalaModuleInfo.value.forall( + _.overrideScalaVersion + ) + val profiles = csrMavenProfiles.value + val credentials = CoursierInputsTasks.credentialsTask.value + + val createLogger = csrLogger.value + + val cache = csrCachePath.value + + val internalSbtScalaProvider = appConfiguration.value.provider.scalaProvider + val sbtBootJars = internalSbtScalaProvider.jars() + val sbtScalaVersion = internalSbtScalaProvider.version() + val sbtScalaOrganization = "org.scala-lang" // always assuming sbt uses mainline scala + val classifiers = classifiersTask.value + Classpaths.warnResolversConflict(rs, log) + CoursierConfiguration() + .withResolvers(rs.toVector) + .withInterProjectDependencies(interProjectDependencies.toVector) + .withFallbackDependencies(fallbackDeps.toVector) + .withExcludeDependencies( + excludeDeps.toVector.map { + case (o, n) => + (o.value, n.value) + }.sorted + ) + .withAutoScalaLibrary(autoScalaLib) + .withSbtScalaJars(sbtBootJars.toVector) + .withSbtScalaVersion(sbtScalaVersion) + .withSbtScalaOrganization(sbtScalaOrganization) + .withClassifiers(classifiers.toVector.flatten.map(_.value)) + .withHasClassifiers(classifiers.nonEmpty) + .withMavenProfiles(profiles.toVector.sorted) + .withScalaOrganization(scalaOrg) + .withScalaVersion(scalaVer) + .withCredentials(credentials) + .withLogger(createLogger) + .withCache(cache) + .withLog(log) + } + } + + private val pluginIvySnapshotsBase = Resolver.SbtRepositoryRoot.stripSuffix("/") + "/ivy-snapshots" + + def coursierSbtResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] = Def.task { + val resolvers = + sbt.Classpaths + .bootRepositories(appConfiguration.value) + .toSeq + .flatten ++ // required because of the hack above it seems + externalResolvers.in(updateSbtClassifiers).value + + val pluginIvySnapshotsFound = resolvers.exists { + case repo: URLRepository => + repo.patterns.artifactPatterns.headOption + .exists(_.startsWith(pluginIvySnapshotsBase)) + case _ => false + } + + val resolvers0 = + if (pluginIvySnapshotsFound && !resolvers.contains(Classpaths.sbtPluginReleases)) + resolvers :+ Classpaths.sbtPluginReleases + else + resolvers + val keepPreloaded = true // coursierKeepPreloaded.value + if (keepPreloaded) + resolvers0 + else + resolvers0.filter { r => + !r.name.startsWith("local-preloaded") + } + } + + def publicationsSetting(packageConfigs: Seq[(Configuration, CConfiguration)]): Def.Setting[_] = { + csrPublications := CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs: _*).value + } +} diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala index fc45b83c0..a6f12b680 100644 --- a/main/src/main/scala/sbt/internal/LibraryManagement.scala +++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala @@ -5,12 +5,15 @@ * Licensed under Apache License 2.0 (see LICENSE) */ -package sbt.internal +package sbt +package internal +import lmcoursier.CoursierDependencyResolution import java.io.File - import sbt.internal.librarymanagement._ +import sbt.internal.util.{ ConsoleAppender, LogOption } import sbt.librarymanagement._ +import sbt.librarymanagement.ivy.IvyDependencyResolution import sbt.librarymanagement.syntax._ import sbt.util.{ CacheStore, CacheStoreFactory, Logger, Tracked } import sbt.io.IO @@ -19,6 +22,43 @@ private[sbt] object LibraryManagement { private type UpdateInputs = (Long, ModuleSettings, UpdateConfiguration) + def defaultUseCoursier: Boolean = { + val coursierOpt = sys.props + .get("sbt.coursier") + .flatMap( + str => + ConsoleAppender.parseLogOption(str) match { + case LogOption.Always => Some(true) + case LogOption.Never => Some(false) + case _ => None + } + ) + val ivyOpt = sys.props + .get("sbt.ivy") + .flatMap( + str => + ConsoleAppender.parseLogOption(str) match { + case LogOption.Always => Some(true) + case LogOption.Never => Some(false) + case _ => None + } + ) + val notIvyOpt = ivyOpt map { !_ } + coursierOpt.orElse(notIvyOpt).getOrElse(true) + } + + def dependencyResolutionTask: Def.Initialize[Task[DependencyResolution]] = Def.taskDyn { + if (Keys.useCoursier.value) { + Def.task { CoursierDependencyResolution(Keys.csrConfiguration.value) } + } else + Def.task { + IvyDependencyResolution( + Keys.ivyConfiguration.value, + CustomHttp.okhttpClient.value + ) + } + } + def cachedUpdate( lm: DependencyResolution, module: ModuleDescriptor, @@ -33,6 +73,8 @@ private[sbt] object LibraryManagement { ewo: EvictionWarningOptions, mavenStyle: Boolean, compatWarning: CompatibilityWarningOptions, + includeCallers: Boolean, + includeDetails: Boolean, log: Logger ): UpdateReport = { @@ -50,15 +92,15 @@ private[sbt] object LibraryManagement { throw unresolvedWarning.resolveException } log.debug(s"Done updating $label") - val finalReport = transform(report) + val report1 = transform(report) // Warn of any eviction and compatibility warnings - val ew = EvictionWarning(module, ewo, finalReport) + val ew = EvictionWarning(module, ewo, report1) ew.lines.foreach(log.warn(_)) ew.infoAllTheThings.foreach(log.info(_)) CompatibilityWarning.run(compatWarning, module, mavenStyle, log) - - finalReport + val report2 = transformDetails(report1, includeCallers, includeDetails) + report2 } /* Check if a update report is still up to date or we must resolve again. */ @@ -90,7 +132,9 @@ private[sbt] object LibraryManagement { import sbt.librarymanagement.LibraryManagementCodec._ val cachedResolve = Tracked.lastOutput[UpdateInputs, UpdateReport](cache) { case (_, Some(out)) if upToDate(inChanged, out) => markAsCached(out) - case _ => resolve + case pair => + log.debug(s""""not up to date. inChanged = $inChanged, force = $force""") + resolve } import scala.util.control.Exception.catching catching(classOf[NullPointerException], classOf[OutOfMemoryError]) @@ -150,4 +194,24 @@ private[sbt] object LibraryManagement { .withExtraAttributes(m.extraAttributes) .withConfigurations(if (confs) m.configurations else None) .branch(m.branchName) + + private[this] def transformDetails( + ur: UpdateReport, + includeCallers: Boolean, + includeDetails: Boolean + ): UpdateReport = { + val crs0 = ur.configurations + val crs1 = + if (includeDetails) crs0 + else crs0 map { _.withDetails(Vector()) } + val crs2 = + if (includeCallers) crs1 + else + crs1 map { cr => + val mrs0 = cr.modules + val mrs1 = mrs0 map { _.withCallers(Vector()) } + cr.withModules(mrs1) + } + ur.withConfigurations(crs2) + } } diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala new file mode 100644 index 000000000..23e64aae2 --- /dev/null +++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierArtifactsTasks.scala @@ -0,0 +1,157 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package librarymanagement + +import lmcoursier.definitions.{ + Classifier, + Configuration => CConfiguration, + Extension => CExtension, + Publication => CPublication, + Type => CType +} +import sbt.librarymanagement._ +import sbt.Keys._ + +object CoursierArtifactsTasks { + def coursierPublicationsTask( + configsMap: (sbt.librarymanagement.Configuration, CConfiguration)* + ): Def.Initialize[sbt.Task[Seq[(CConfiguration, CPublication)]]] = + Def.task { + val s = sbt.Keys.state.value + val projectRef = sbt.Keys.thisProjectRef.value + val projId = sbt.Keys.projectID.value + val sv = sbt.Keys.scalaVersion.value + val sbv = sbt.Keys.scalaBinaryVersion.value + val ivyConfs = sbt.Keys.ivyConfigurations.value + val extracted = Project.extract(s) + import extracted._ + + val sourcesConfigOpt = + if (ivyConfigurations.value.exists(_.name == "sources")) + Some(CConfiguration("sources")) + else + None + + val docsConfigOpt = + if (ivyConfigurations.value.exists(_.name == "docs")) + Some(CConfiguration("docs")) + else + None + + val sbtBinArtifacts = + for ((config, targetConfig) <- configsMap) yield { + + val publish = getOpt( + publishArtifact + .in(projectRef) + .in(packageBin) + .in(config) + ).getOrElse(false) + + if (publish) + getOpt( + artifact + .in(projectRef) + .in(packageBin) + .in(config) + ).map(targetConfig -> _) + else + None + } + + val sbtSourceArtifacts = + for ((config, targetConfig) <- configsMap) yield { + + val publish = getOpt( + publishArtifact + .in(projectRef) + .in(packageSrc) + .in(config) + ).getOrElse(false) + + if (publish) + getOpt( + artifact + .in(projectRef) + .in(packageSrc) + .in(config) + ).map(sourcesConfigOpt.getOrElse(targetConfig) -> _) + else + None + } + + val sbtDocArtifacts = + for ((config, targetConfig) <- configsMap) yield { + + val publish = + getOpt( + publishArtifact + .in(projectRef) + .in(packageDoc) + .in(config) + ).getOrElse(false) + + if (publish) + getOpt( + artifact + .in(projectRef) + .in(packageDoc) + .in(config) + ).map(docsConfigOpt.getOrElse(targetConfig) -> _) + else + None + } + + val sbtArtifacts = sbtBinArtifacts ++ sbtSourceArtifacts ++ sbtDocArtifacts + + def artifactPublication(artifact: Artifact) = { + + val name = CrossVersion(projId.crossVersion, sv, sbv) + .fold(artifact.name)(_(artifact.name)) + + CPublication( + name, + CType(artifact.`type`), + CExtension(artifact.extension), + artifact.classifier.fold(Classifier(""))(Classifier(_)) + ) + } + + val sbtArtifactsPublication = sbtArtifacts.collect { + case Some((config, artifact)) => + config -> artifactPublication(artifact) + } + + val stdArtifactsSet = sbtArtifacts.flatMap(_.map { case (_, a) => a }.toSeq).toSet + + // Second-way of getting artifacts from SBT + // No obvious way of getting the corresponding publishArtifact value for the ones + // only here, it seems. + val extraSbtArtifacts = getOpt( + sbt.Keys.artifacts + .in(projectRef) + ).getOrElse(Nil) + .filterNot(stdArtifactsSet) + + // Seems that SBT does that - if an artifact has no configs, + // it puts it in all of them. See for example what happens to + // the standalone JAR artifact of the coursier cli module. + def allConfigsIfEmpty(configs: Iterable[ConfigRef]): Iterable[ConfigRef] = + if (configs.isEmpty) ivyConfs.filter(_.isPublic).map(c => ConfigRef(c.name)) else configs + + val extraSbtArtifactsPublication = for { + artifact <- extraSbtArtifacts + config <- allConfigsIfEmpty(artifact.configurations.map(x => ConfigRef(x.name))) + // FIXME If some configurations from artifact.configurations are not public, they may leak here :\ + } yield CConfiguration(config.name) -> artifactPublication(artifact) + + sbtArtifactsPublication ++ extraSbtArtifactsPublication + } +} diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala new file mode 100644 index 000000000..e50b1a874 --- /dev/null +++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierInputsTasks.scala @@ -0,0 +1,235 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package librarymanagement + +import sbt.librarymanagement._ +import sbt.util.Logger +import sbt.Keys._ +import lmcoursier.definitions.{ + Attributes => CAttributes, + Classifier, + Configuration => CConfiguration, + Dependency => CDependency, + // Extension => CExtension, + Info => CInfo, + Module, + ModuleName, + Organization => COrganization, + Project => CProject, + // Publication => CPublication, + Type => CType +} +import lmcoursier.credentials.DirectCredentials +import lmcoursier.{ FallbackDependency, FromSbt, Inputs } +import sbt.librarymanagement.ivy.{ + FileCredentials, + Credentials, + DirectCredentials => IvyDirectCredentials +} +import sbt.ScopeFilter.Make._ +import scala.collection.JavaConverters._ + +private[sbt] object CoursierInputsTasks { + private def coursierProject0( + projId: ModuleID, + dependencies: Seq[ModuleID], + excludeDeps: Seq[InclExclRule], + configurations: Seq[sbt.librarymanagement.Configuration], + sv: String, + sbv: String, + log: Logger + ): CProject = { + + val exclusions0 = Inputs.exclusions(excludeDeps, sv, sbv, log) + + val configMap = Inputs.configExtends(configurations) + + val proj = FromSbt.project( + projId, + dependencies, + configMap, + sv, + sbv + ) + + proj.copy( + dependencies = proj.dependencies.map { + case (config, dep) => + (config, dep.copy(exclusions = dep.exclusions ++ exclusions0)) + } + ) + } + + private[sbt] def coursierProjectTask: Def.Initialize[sbt.Task[CProject]] = + Def.task { + val auOpt = apiURL.value + val proj = coursierProject0( + projectID.value, + allDependencies.value, + allExcludeDependencies.value, + // should projectID.configurations be used instead? + ivyConfigurations.value, + scalaVersion.value, + scalaBinaryVersion.value, + streams.value.log + ) + auOpt match { + case Some(au) => + val props = proj.properties :+ ("info.apiURL" -> au.toString) + proj.copy(properties = props) + case _ => proj + } + } + + private def moduleFromIvy(id: org.apache.ivy.core.module.id.ModuleRevisionId): Module = + Module( + COrganization(id.getOrganisation), + ModuleName(id.getName), + id.getExtraAttributes.asScala.map { + case (k0, v0) => k0.asInstanceOf[String] -> v0.asInstanceOf[String] + }.toMap + ) + + private def dependencyFromIvy( + desc: org.apache.ivy.core.module.descriptor.DependencyDescriptor + ): Seq[(CConfiguration, CDependency)] = { + + val id = desc.getDependencyRevisionId + val module = moduleFromIvy(id) + val exclusions = desc.getAllExcludeRules.map { rule => + // we're ignoring rule.getConfigurations and rule.getMatcher here + val modId = rule.getId.getModuleId + // we're ignoring modId.getAttributes here + (COrganization(modId.getOrganisation), ModuleName(modId.getName)) + }.toSet + + val configurations = desc.getModuleConfigurations.toVector + .flatMap(Inputs.ivyXmlMappings) + + def dependency(conf: CConfiguration, attr: CAttributes) = CDependency( + module, + id.getRevision, + conf, + exclusions, + attr, + optional = false, + desc.isTransitive + ) + + val attributes: CConfiguration => CAttributes = { + + val artifacts = desc.getAllDependencyArtifacts + + val m = artifacts.toVector.flatMap { art => + val attr = CAttributes(CType(art.getType), Classifier("")) + art.getConfigurations.map(CConfiguration(_)).toVector.map { conf => + conf -> attr + } + }.toMap + + c => m.getOrElse(c, CAttributes(CType(""), Classifier(""))) + } + + configurations.map { + case (from, to) => + from -> dependency(to, attributes(to)) + } + } + + private[sbt] def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[CProject]]] = + Def.taskDyn { + + val state = sbt.Keys.state.value + val projectRef = sbt.Keys.thisProjectRef.value + + val projectRefs = Project.transitiveInterDependencies(state, projectRef) + + Def.task { + val projects = csrProject.all(ScopeFilter(inProjects(projectRefs: _*))).value + val projectModules = projects.map(_.module).toSet + + // this includes org.scala-sbt:global-plugins referenced from meta-builds in particular + val extraProjects = sbt.Keys.projectDescriptors.value + .map { + case (k, v) => + moduleFromIvy(k) -> v + } + .filter { + case (module, _) => + !projectModules(module) + } + .toVector + .map { + case (module, v) => + val configurations = v.getConfigurations.map { c => + CConfiguration(c.getName) -> c.getExtends.map(CConfiguration(_)).toSeq + }.toMap + val deps = v.getDependencies.flatMap(dependencyFromIvy) + CProject( + module, + v.getModuleRevisionId.getRevision, + deps, + configurations, + Nil, + None, + Nil, + CInfo("", "", Nil, Nil, None) + ) + } + + projects ++ extraProjects + } + } + + private[sbt] def coursierFallbackDependenciesTask + : Def.Initialize[sbt.Task[Seq[FallbackDependency]]] = + Def.taskDyn { + val state = sbt.Keys.state.value + val projectRef = sbt.Keys.thisProjectRef.value + + val projects = Project.transitiveInterDependencies(state, projectRef) + + Def.task { + val allDeps = + allDependencies.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten + + FromSbt.fallbackDependencies( + allDeps, + scalaVersion.value, + scalaBinaryVersion.value + ) + } + } + + val credentialsTask = Def.task { + val log = streams.value.log + val creds = sbt.Keys.credentials.value + .flatMap { + case dc: IvyDirectCredentials => List(dc) + case fc: FileCredentials => + Credentials.loadCredentials(fc.path) match { + case Left(err) => + log.warn(s"$err, ignoring it") + Nil + case Right(dc) => List(dc) + } + } + .map { c => + DirectCredentials() + .withHost(c.host) + .withUsername(c.userName) + .withPassword(c.passwd) + .withRealm(Some(c.realm).filter(_.nonEmpty)) + .withHttpsOnly(false) + .withMatchHost(true) + } + creds ++ csrExtraCredentials.value + } +} diff --git a/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala b/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala new file mode 100644 index 000000000..4e6f535d7 --- /dev/null +++ b/main/src/main/scala/sbt/internal/librarymanagement/CoursierRepositoriesTasks.scala @@ -0,0 +1,130 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package librarymanagement + +import sbt.librarymanagement._ +import sbt.Keys._ +import sbt.ScopeFilter.Make._ +import sbt.io.IO + +private[sbt] object CoursierRepositoriesTasks { + private object CResolvers { + private val slowReposBase = Seq( + "https://repo.typesafe.com/", + "https://repo.scala-sbt.org/", + "http://repo.typesafe.com/", + "http://repo.scala-sbt.org/" + ) + + private val fastReposBase = Seq( + "http://repo1.maven.org/", + "https://repo1.maven.org/" + ) + + private def url(res: Resolver): Option[String] = + res match { + case m: sbt.librarymanagement.MavenRepository => + Some(m.root) + case u: URLRepository => + u.patterns.artifactPatterns.headOption + .orElse(u.patterns.ivyPatterns.headOption) + case _ => + None + } + + private def fastRepo(res: Resolver): Boolean = + url(res).exists(u => fastReposBase.exists(u.startsWith)) + + private def slowRepo(res: Resolver): Boolean = + url(res).exists(u => slowReposBase.exists(u.startsWith)) + + def reorderResolvers(resolvers: Seq[Resolver]): Seq[Resolver] = + if (resolvers.exists(fastRepo) && resolvers.exists(slowRepo)) { + val (slow, other) = resolvers.partition(slowRepo) + other ++ slow + } else + resolvers + } + + private def resultTask( + bootResOpt: Option[Seq[Resolver]], + overrideFlag: Boolean + ): Def.Initialize[sbt.Task[Seq[Resolver]]] = + bootResOpt.filter(_ => overrideFlag) match { + case Some(r) => Def.task(r) + case None => + Def.taskDyn { + val extRes = externalResolvers.value + val isSbtPlugin = sbtPlugin.value + if (isSbtPlugin) + Def.task { + Seq( + sbtResolver.value, + Classpaths.sbtPluginReleases + ) ++ extRes + } else + Def.task(extRes) + } + } + + def coursierResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] = + Def.taskDyn { + + val bootResOpt = bootResolvers.value + val overrideFlag = overrideBuildResolvers.value + + Def.task { + val result0 = resultTask(bootResOpt, overrideFlag).value + val reorderResolvers = true // coursierReorderResolvers.value + val keepPreloaded = true // coursierKeepPreloaded.value + + val paths = ivyPaths.value + val result1 = + if (reorderResolvers) CResolvers.reorderResolvers(result0) + else result0 + val result2 = + paths.ivyHome match { + case Some(ivyHome) => + val ivyHomeUri = IO.toURI(ivyHome).getSchemeSpecificPart + result1 map { + case r: FileRepository => + val ivyPatterns = r.patterns.ivyPatterns map { + _.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri) + } + val artifactPatterns = r.patterns.artifactPatterns map { + _.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri) + } + val p = + r.patterns.withIvyPatterns(ivyPatterns).withArtifactPatterns(artifactPatterns) + r.withPatterns(p) + case r => r + } + case _ => result1 + } + + if (keepPreloaded) + result2 + else + result2.filter { r => + !r.name.startsWith("local-preloaded") + } + } + } + + def coursierRecursiveResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] = + Def.taskDyn { + val state = sbt.Keys.state.value + val projectRef = sbt.Keys.thisProjectRef.value + val projects = Project.transitiveInterDependencies(state, projectRef) + Def.task { + csrResolvers.all(ScopeFilter(inProjects(projectRef +: projects: _*))).value.flatten + } + } +} diff --git a/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala b/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala new file mode 100644 index 000000000..966d0fb6e --- /dev/null +++ b/main/src/main/scala/sbt/internal/librarymanagement/IvyXml.scala @@ -0,0 +1,225 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package librarymanagement + +import java.nio.charset.StandardCharsets.UTF_8 +import java.nio.file.Files + +import lmcoursier.definitions.{ Configuration, Project } +import org.apache.ivy.core.module.id.ModuleRevisionId +import Def.Setting +import sbt.Keys.{ + csrProject, + csrPublications, + publishLocalConfiguration, + publishConfiguration, + useCoursier +} +import sbt.librarymanagement.PublishConfiguration +import scala.collection.JavaConverters._ +import scala.xml.{ Node, PrefixedAttribute } + +object IvyXml { + import sbt.Project._ + + private def rawContent( + currentProject: Project, + shadedConfigOpt: Option[Configuration] + ): String = { + + // Important: width = Int.MaxValue, so that no tag gets truncated. + // In particular, that prevents things like to be split to + // + // + // by the pretty-printer. + // See https://github.com/sbt/sbt/issues/3412. + val printer = new scala.xml.PrettyPrinter(Int.MaxValue, 2) + + """""" + '\n' + + printer.format(content(currentProject, shadedConfigOpt)) + } + + // These are required for publish to be fine, later on. + private def writeFiles( + currentProject: Project, + shadedConfigOpt: Option[Configuration], + ivySbt: IvySbt, + log: sbt.util.Logger + ): Unit = { + + val ivyCacheManager = ivySbt.withIvy(log)(ivy => ivy.getResolutionCacheManager) + + val ivyModule = ModuleRevisionId.newInstance( + currentProject.module.organization.value, + currentProject.module.name.value, + currentProject.version, + currentProject.module.attributes.asJava + ) + + val cacheIvyFile = ivyCacheManager.getResolvedIvyFileInCache(ivyModule) + val cacheIvyPropertiesFile = ivyCacheManager.getResolvedIvyPropertiesInCache(ivyModule) + + val content0 = rawContent(currentProject, shadedConfigOpt) + cacheIvyFile.getParentFile.mkdirs() + log.info(s"Writing Ivy file $cacheIvyFile") + Files.write(cacheIvyFile.toPath, content0.getBytes(UTF_8)) + + // Just writing an empty file here... Are these only used? + cacheIvyPropertiesFile.getParentFile.mkdirs() + Files.write(cacheIvyPropertiesFile.toPath, Array.emptyByteArray) + () + } + + private def content(project0: Project, shadedConfigOpt: Option[Configuration]): Node = { + + val filterOutDependencies = + shadedConfigOpt.toSet[Configuration].flatMap { shadedConfig => + project0.dependencies + .collect { case (conf, dep) if conf.value == shadedConfig.value => dep } + } + + val project: Project = project0.copy( + dependencies = project0.dependencies.collect { + case p @ (_, dep) if !filterOutDependencies(dep) => p + } + ) + + val infoAttrs = + (project.module.attributes.toSeq ++ project.properties).foldLeft[xml.MetaData](xml.Null) { + case (acc, (k, v)) => + new PrefixedAttribute("e", k, v, acc) + } + + val licenseElems = project.info.licenses.map { + case (name, urlOpt) => + val n = + + urlOpt.fold(n) { url => + n % .attributes + } + } + + val infoElem = { + + {licenseElems} + {project.info.description} + + } % infoAttrs + + val confElems = project.configurations.toVector.collect { + case (name, extends0) if !shadedConfigOpt.exists(_.value == name.value) => + val extends1 = shadedConfigOpt.fold(extends0)(c => extends0.filter(_.value != c.value)) + val n = + if (extends1.nonEmpty) + n % .attributes + else + n + } + + val publications = project.publications + .groupBy { case (_, p) => p } + .mapValues { _.map { case (cfg, _) => cfg } } + + val publicationElems = publications.map { + case (pub, configs) => + val n = + + + if (pub.classifier.value.nonEmpty) + n % .attributes + else + n + } + + val dependencyElems = project.dependencies.toVector.map { + case (conf, dep) => + val excludes = dep.exclusions.toSeq.map { + case (org, name) => + + } + + val n = + ${dep.configuration.value}"}> + {excludes} + + + val moduleAttrs = dep.module.attributes.foldLeft[xml.MetaData](xml.Null) { + case (acc, (k, v)) => + new PrefixedAttribute("e", k, v, acc) + } + + n % moduleAttrs + } + + + {infoElem} + {confElems} + {publicationElems} + {dependencyElems} + + } + + private def makeIvyXmlBefore[T]( + task: TaskKey[T], + shadedConfigOpt: Option[Configuration] + ): Setting[Task[T]] = + task := task.dependsOn { + Def.taskDyn { + val doGen = useCoursier.value + if (doGen) + Def.task { + val currentProject = { + val proj = csrProject.value + val publications = csrPublications.value + proj.copy(publications = publications) + } + IvyXml.writeFiles( + currentProject, + shadedConfigOpt, + sbt.Keys.ivySbt.value, + sbt.Keys.streams.value.log + ) + } else + Def.task(()) + } + }.value + + private lazy val needsIvyXmlLocal = Seq(publishLocalConfiguration) ++ getPubConf( + "makeIvyXmlLocalConfiguration" + ) + private lazy val needsIvyXml = Seq(publishConfiguration) ++ getPubConf( + "makeIvyXmlConfiguration" + ) + + private[this] def getPubConf(method: String): List[TaskKey[PublishConfiguration]] = + try { + val cls = sbt.Keys.getClass + val m = cls.getMethod(method) + val task = m.invoke(sbt.Keys).asInstanceOf[TaskKey[PublishConfiguration]] + List(task) + } catch { + case _: Throwable => // FIXME Too wide + Nil + } + + def generateIvyXmlSettings( + shadedConfigOpt: Option[Configuration] = None + ): Seq[Setting[_]] = + (needsIvyXml ++ needsIvyXmlLocal).map(makeIvyXmlBefore(_, shadedConfigOpt)) + +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 942d1183c..716b4005d 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -29,23 +29,7 @@ object Dependencies { private val utilScripted = "org.scala-sbt" %% "util-scripted" % utilVersion private val libraryManagementCore = "org.scala-sbt" %% "librarymanagement-core" % lmVersion - private val libraryManagementIvy = "org.scala-sbt" %% "librarymanagement-ivy" % lmVersion - - private val libraryManagementImpl = { - val lmOrganization = - sys.props.get("sbt.build.lm.organization") match { - case Some(impl) => impl - case _ => "org.scala-sbt" - } - - val lmModuleName = - sys.props.get("sbt.build.lm.moduleName") match { - case Some(impl) => impl - case _ => "librarymanagement-ivy" - } - - lmOrganization %% lmModuleName % lmVersion - } + private val libraryManagementImpl = "org.scala-sbt" %% "librarymanagement-ivy" % lmVersion val launcherVersion = "1.0.4" val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion @@ -126,6 +110,9 @@ object Dependencies { def addSbtZincCompileCore(p: Project): Project = addSbtModule(p, sbtZincPath, "zincCompileCore", zincCompileCore) + val lmCoursierVersion = "1.1.0-M14-1" + val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % lmCoursierVersion + val sjsonNewScalaJson = Def.setting { "com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value } diff --git a/sbt/src/repo-override-test/dependency-management/default-resolvers/test b/sbt/src/repo-override-test/dependency-management/default-resolvers/pending similarity index 100% rename from sbt/src/repo-override-test/dependency-management/default-resolvers/test rename to sbt/src/repo-override-test/dependency-management/default-resolvers/pending diff --git a/sbt/src/sbt-test/actions/external-doc/build.sbt b/sbt/src/sbt-test/actions/external-doc/build.sbt index 80ead271f..834ad7004 100644 --- a/sbt/src/sbt-test/actions/external-doc/build.sbt +++ b/sbt/src/sbt-test/actions/external-doc/build.sbt @@ -1,3 +1,6 @@ +// https://github.com/coursier/coursier/issues/1123 +ThisBuild / useCoursier := false + Seq( autoAPIMappings in ThisBuild := true, publishArtifact in (ThisBuild, packageDoc) := false, diff --git a/sbt/src/sbt-test/actions/previous-in-input-task/build.sbt b/sbt/src/sbt-test/actions/previous-in-input-task/build.sbt new file mode 100644 index 000000000..a7e169d7e --- /dev/null +++ b/sbt/src/sbt-test/actions/previous-in-input-task/build.sbt @@ -0,0 +1,10 @@ +import sjsonnew.BasicJsonProtocol._ + +val cacheTask = taskKey[Int]("task") +cacheTask := 1 + +val checkTask = inputKey[Unit]("validate that the correct value is set by cacheTask") +checkTask := { + val expected = Def.spaceDelimited("").parsed.head.toInt + assert(cacheTask.previous.getOrElse(0) == expected) +} \ No newline at end of file diff --git a/sbt/src/sbt-test/actions/previous-in-input-task/test b/sbt/src/sbt-test/actions/previous-in-input-task/test new file mode 100644 index 000000000..1b7969eea --- /dev/null +++ b/sbt/src/sbt-test/actions/previous-in-input-task/test @@ -0,0 +1,5 @@ +> checkTask 0 + +> cacheTask + +> checkTask 1 \ No newline at end of file diff --git a/sbt/src/sbt-test/classloader-cache/snapshot/build.sbt b/sbt/src/sbt-test/classloader-cache/snapshot/build.sbt index 73ebc2aa9..a54646805 100644 --- a/sbt/src/sbt-test/classloader-cache/snapshot/build.sbt +++ b/sbt/src/sbt-test/classloader-cache/snapshot/build.sbt @@ -1,9 +1,10 @@ import java.nio.file.Files import java.nio.file.attribute.FileTime - import scala.collection.JavaConverters._ val rewriteIvy = inputKey[Unit]("Rewrite ivy directory") +ThisBuild / useCoursier := false + val snapshot = (project in file(".")).settings( name := "akka-test", scalaVersion := "2.12.8", diff --git a/sbt/src/sbt-test/dependency-management/aar-packaging/build.sbt b/sbt/src/sbt-test/dependency-management/aar-packaging/build.sbt new file mode 100644 index 000000000..67a22204e --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/aar-packaging/build.sbt @@ -0,0 +1,6 @@ +ThisBuild / scalaVersion := "2.11.12" + +libraryDependencies += ("com.rengwuxian.materialedittext" % "library" % "2.1.4") + .exclude("com.android.support", "support-v4") + .exclude("com.android.support", "support-annotations") + .exclude("com.android.support", "appcompat-v7") diff --git a/sbt/src/sbt-test/dependency-management/aar-packaging/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/aar-packaging/src/main/scala/Main.scala new file mode 100644 index 000000000..61295349d --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/aar-packaging/src/main/scala/Main.scala @@ -0,0 +1,6 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/aar-packaging/test b/sbt/src/sbt-test/dependency-management/aar-packaging/test new file mode 100644 index 000000000..2182f57b0 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/aar-packaging/test @@ -0,0 +1,3 @@ +$ delete output +> run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/artifact/build.sbt b/sbt/src/sbt-test/dependency-management/artifact/build.sbt index 7a737bbec..6e51258c1 100644 --- a/sbt/src/sbt-test/dependency-management/artifact/build.sbt +++ b/sbt/src/sbt-test/dependency-management/artifact/build.sbt @@ -3,8 +3,10 @@ import sbt.internal.inc.classpath.ClasspathUtilities lazy val checkFull = taskKey[Unit]("") lazy val check = taskKey[Unit]("") -lazy val root = (project in file(".")). - settings( +ThisBuild / useCoursier := false + +lazy val root = (project in file(".")) + .settings( ivyPaths := IvyPaths(baseDirectory.value, Some(target.value / "ivy-cache")), publishTo := Some(Resolver.file("Test Publish Repo", file("test-repo"))), resolvers += (baseDirectory { base => "Test Repo" at (base / "test-repo").toURI.toString }).value, @@ -34,8 +36,10 @@ def publishedID = org % artifactID % vers artifacts(mainArtifact) def retrieveID = org % "test-retrieve" % "2.0" // check that the test class is on the compile classpath, either because it was compiled or because it was properly retrieved -def checkTask(classpath: TaskKey[Classpath]) = Def task { - val loader = ClasspathUtilities.toLoader((classpath in Compile).value.files, scalaInstance.value.loader) +def checkTask(classpath: TaskKey[Classpath]) = Def.task { + val deps = libraryDependencies.value + val cp = (classpath in Compile).value.files + val loader = ClasspathUtilities.toLoader(cp, scalaInstance.value.loader) try { Class.forName("test.Test", false, loader); () } - catch { case _: ClassNotFoundException | _: NoClassDefFoundError => sys.error("Dependency not retrieved properly") } + catch { case _: ClassNotFoundException | _: NoClassDefFoundError => sys.error(s"Dependency not retrieved properly: $deps, $cp") } } diff --git a/sbt/src/sbt-test/dependency-management/auto-scala-library/build.sbt b/sbt/src/sbt-test/dependency-management/auto-scala-library/build.sbt new file mode 100644 index 000000000..20969e7e5 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/auto-scala-library/build.sbt @@ -0,0 +1,20 @@ +autoScalaLibrary := false +libraryDependencies += "com.chuusai" % "shapeless_2.12" % "2.3.2" + +val checkScalaLibrary = TaskKey[Unit]("checkScalaLibrary") + +checkScalaLibrary := { + val scalaLibsJars = managedClasspath + .in(Compile) + .value + .map(_.data.getName) + .filter(_.startsWith("scala-library")) + .sorted + val expectedScalaLibsJars = Seq( + "scala-library-2.12.0.jar" + ) + assert( + scalaLibsJars == expectedScalaLibsJars, + s"$scalaLibsJars != $expectedScalaLibsJars" + ) +} diff --git a/sbt/src/sbt-test/dependency-management/auto-scala-library/test b/sbt/src/sbt-test/dependency-management/auto-scala-library/test new file mode 100644 index 000000000..f56f5a75e --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/auto-scala-library/test @@ -0,0 +1 @@ +> checkScalaLibrary diff --git a/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt b/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt index 75e55de1d..5c155cb2e 100644 --- a/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt +++ b/sbt/src/sbt-test/dependency-management/cache-classifiers/multi.sbt @@ -1,5 +1,8 @@ ThisBuild / scalaVersion := "2.12.8" +// TTL of Coursier is 24h +ThisBuild / useCoursier := false + def localCache = ivyPaths := IvyPaths(baseDirectory.value, Some((baseDirectory in ThisBuild).value / "ivy" / "cache")) diff --git a/sbt/src/sbt-test/dependency-management/cache-update/build.sbt b/sbt/src/sbt-test/dependency-management/cache-update/build.sbt index db7eead25..b12fb7e29 100644 --- a/sbt/src/sbt-test/dependency-management/cache-update/build.sbt +++ b/sbt/src/sbt-test/dependency-management/cache-update/build.sbt @@ -31,7 +31,9 @@ lazy val root = (project in file(".")) // sbt resolves dependencies every compile when using %% with dependencyOverrides TaskKey[Unit]("check") := { val s = (streams in update).value - val cacheStoreFactory = s.cacheStoreFactory sub updateCacheName.value + + val cacheDirectory = crossTarget.value / "update" / updateCacheName.value + val cacheStoreFactory = sbt.util.CacheStoreFactory.directory(cacheDirectory) val module = ivyModule.value val updateConfig = updateConfiguration.value val extraInputHash0 = module.extraInputHash diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt index 237f70774..e3057754e 100644 --- a/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt +++ b/sbt/src/sbt-test/dependency-management/cached-resolution-classifier/multi.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val check = taskKey[Unit]("Runs the check") def commonSettings: Seq[Def.Setting[_]] = diff --git a/sbt/src/sbt-test/dependency-management/cached-resolution-exclude/multi.sbt b/sbt/src/sbt-test/dependency-management/cached-resolution-exclude/multi.sbt index 7bca9158b..05659cdf1 100644 --- a/sbt/src/sbt-test/dependency-management/cached-resolution-exclude/multi.sbt +++ b/sbt/src/sbt-test/dependency-management/cached-resolution-exclude/multi.sbt @@ -1,6 +1,8 @@ // https://github.com/sbt/sbt/issues/1649 lazy val check = taskKey[Unit]("Runs the check") +ThisBuild / useCoursier := false + def commonSettings: Seq[Def.Setting[_]] = Seq( ivyPaths := IvyPaths( (baseDirectory in ThisBuild).value, Some((baseDirectory in LocalRootProject).value / "ivy-cache")), diff --git a/sbt/src/sbt-test/dependency-management/chainresolver/build.sbt b/sbt/src/sbt-test/dependency-management/chainresolver/build.sbt index e63b0921e..8906939b2 100644 --- a/sbt/src/sbt-test/dependency-management/chainresolver/build.sbt +++ b/sbt/src/sbt-test/dependency-management/chainresolver/build.sbt @@ -3,7 +3,7 @@ lazy val check = taskKey[Unit]("Runs the check") def commonSettings: Seq[Def.Setting[_]] = Seq( ivyPaths := IvyPaths( (baseDirectory in ThisBuild).value, Some((target in LocalRootProject).value / "ivy-cache")), - scalaVersion in ThisBuild := "2.11.7", + scalaVersion in ThisBuild := "2.11.12", organization in ThisBuild := "com.example", version in ThisBuild := "0.1.0-SNAPSHOT", autoScalaLibrary := false, diff --git a/sbt/src/sbt-test/dependency-management/circular-dependency/changes/multi.sbt b/sbt/src/sbt-test/dependency-management/circular-dependency/changes/multi.sbt index c86962b24..ce0d2665f 100644 --- a/sbt/src/sbt-test/dependency-management/circular-dependency/changes/multi.sbt +++ b/sbt/src/sbt-test/dependency-management/circular-dependency/changes/multi.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val check = taskKey[Unit]("Runs the check") def commonSettings: Seq[Def.Setting[_]] = diff --git a/sbt/src/sbt-test/dependency-management/classifier2/build.sbt b/sbt/src/sbt-test/dependency-management/classifier2/build.sbt new file mode 100644 index 000000000..133599913 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/classifier2/build.sbt @@ -0,0 +1,2 @@ +ThisBuild / scalaVersion := "2.11.12" +libraryDependencies += "org.jclouds.api" % "nova" % "1.5.9" classifier "tests" diff --git a/sbt/src/sbt-test/dependency-management/classifier2/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/classifier2/src/main/scala/Main.scala new file mode 100644 index 000000000..b1a40797d --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/classifier2/src/main/scala/Main.scala @@ -0,0 +1,18 @@ +import java.io.File +import java.nio.file.Files + +import scala.util.Try + +object Main extends App { + + def classFound(clsName: String) = Try( + Thread.currentThread() + .getContextClassLoader() + .loadClass(clsName) + ).toOption.nonEmpty + + val name = "org.jclouds.openstack.nova.functions.ParseServerFromJsonResponseTest" + val classifierTest = classFound(name) + + assert(classifierTest, s"Couldn't find $name") +} diff --git a/sbt/src/sbt-test/dependency-management/classifier2/test b/sbt/src/sbt-test/dependency-management/classifier2/test new file mode 100644 index 000000000..62ea636c1 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/classifier2/test @@ -0,0 +1 @@ +> run diff --git a/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/build.sbt b/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/build.sbt index a3b3bf1f4..391353a8e 100644 --- a/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/build.sbt +++ b/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/build.sbt @@ -1,7 +1,9 @@ -scalaVersion := "2.12.6" +ThisBuild / scalaVersion := "2.12.8" + +lazy val check = taskKey[Unit]("") // We can't use "%%" here without breaking the "== bridgeModule" check below -val bridgeModule = "org.scala-sbt" % s"compiler-bridge_2.12" % "1.2.1" +val bridgeModule = "org.scala-sbt" % s"compiler-bridge_2.12" % "1.3.0-M3" libraryDependencies += bridgeModule % Configurations.ScalaTool @@ -10,7 +12,14 @@ scalaCompilerBridgeSource := "shouldnotbeused" % "dummy" % "dummy" scalaCompilerBridgeBinaryJar := { for { toolReport <- update.value.configuration(Configurations.ScalaTool) - m <- toolReport.modules.find(m => m.module == bridgeModule) + m <- toolReport.modules.find(m => m.module.name == bridgeModule.name) (_, file) <- m.artifacts.find(art => art._1.`type` == Artifact.DefaultType) } yield file } + +check := { + val toolReport = update.value.configuration(Configurations.ScalaTool).get + val m = toolReport.modules.find(m => m.module.name == bridgeModule.name) + val bridge = scalaCompilerBridgeBinaryJar.value + bridge.getOrElse(sys.error(s"bridge JAR is missing: $toolReport")) +} diff --git a/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/test b/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/test index 5df2af1f3..5f1fbe2c5 100644 --- a/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/test +++ b/sbt/src/sbt-test/dependency-management/compiler-bridge-binary/test @@ -1 +1,2 @@ +> check > compile diff --git a/sbt/src/sbt-test/dependency-management/configurations-to-retrieve/build.sbt b/sbt/src/sbt-test/dependency-management/configurations-to-retrieve/build.sbt index e8a4aeabd..d03c0f295 100644 --- a/sbt/src/sbt-test/dependency-management/configurations-to-retrieve/build.sbt +++ b/sbt/src/sbt-test/dependency-management/configurations-to-retrieve/build.sbt @@ -1,11 +1,11 @@ -configurationsToRetrieve := Some(Vector(Compile)) +ThisBuild / useCoursier := false -retrieveManaged := true - -libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile" - -autoScalaLibrary := false - -managedDirectory := file("dependencies") - -retrievePattern := "[conf]/[artifact]-[revision](-[classifier]).[ext]" +lazy val root = (project in file(".")) + .settings( + configurationsToRetrieve := Some(Vector(Compile)), + retrieveManaged := true, + libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile", + autoScalaLibrary := false, + managedDirectory := file("dependencies"), + retrievePattern := "[conf]/[artifact]-[revision](-[classifier]).[ext]", + ) diff --git a/sbt/src/sbt-test/dependency-management/conflict-manager/build.sbt b/sbt/src/sbt-test/dependency-management/conflict-manager/build.sbt index b5cfdf07b..0dc7a72fc 100644 --- a/sbt/src/sbt-test/dependency-management/conflict-manager/build.sbt +++ b/sbt/src/sbt-test/dependency-management/conflict-manager/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + libraryDependencies ++= Seq( "org.spark-project" %% "spark-core" % "0.5.1", "log4j" % "log4j" % "1.2.17" diff --git a/sbt/src/sbt-test/dependency-management/default-artifact/build.sbt b/sbt/src/sbt-test/dependency-management/default-artifact/build.sbt index 829951e2e..c7fe3b549 100644 --- a/sbt/src/sbt-test/dependency-management/default-artifact/build.sbt +++ b/sbt/src/sbt-test/dependency-management/default-artifact/build.sbt @@ -1,11 +1,13 @@ +ThisBuild / useCoursier := false + resolvers += Resolver.file("buggy", file("repo"))( - Patterns( - ivyPatterns = Vector("[organization]/[module]/[revision]/ivy.xml"), - artifactPatterns = Vector("[organization]/[module]/[revision]/[artifact].[ext]"), - isMavenCompatible = false, - descriptorOptional = true, - skipConsistencyCheck = true - ) + Patterns( + ivyPatterns = Vector("[organization]/[module]/[revision]/ivy.xml"), + artifactPatterns = Vector("[organization]/[module]/[revision]/[artifact].[ext]"), + isMavenCompatible = false, + descriptorOptional = true, + skipConsistencyCheck = true + ) ) libraryDependencies += "a" % "b" % "1.0.0" % "compile->runtime" artifacts(Artifact("b1", "jar", "jar")) diff --git a/sbt/src/sbt-test/dependency-management/default-artifact/repo/a/b/1.0.0/ivy.xml b/sbt/src/sbt-test/dependency-management/default-artifact/repo/a/b/1.0.0/ivy.xml index 53fe74fc9..165b4c192 100644 --- a/sbt/src/sbt-test/dependency-management/default-artifact/repo/a/b/1.0.0/ivy.xml +++ b/sbt/src/sbt-test/dependency-management/default-artifact/repo/a/b/1.0.0/ivy.xml @@ -1,13 +1,13 @@ - a + a - + - - + + diff --git a/sbt/src/sbt-test/dependency-management/dynamic-revision/test b/sbt/src/sbt-test/dependency-management/dynamic-revision/pending similarity index 100% rename from sbt/src/sbt-test/dependency-management/dynamic-revision/test rename to sbt/src/sbt-test/dependency-management/dynamic-revision/pending diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt b/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt index b7f1ef752..15e4df170 100644 --- a/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt +++ b/sbt/src/sbt-test/dependency-management/exclude-dependencies/build.sbt @@ -9,14 +9,14 @@ val repatchTwitter = "com.eed3si9n" %% "repatch-twitter-core" % "dispatch0.11.1_ lazy val a = (project in file("a")). settings( - scalaVersion := "2.11.4", + scalaVersion := "2.11.12", libraryDependencies += dispatch, excludeDependencies += "org.slf4j" ) lazy val b = (project in file("b")). settings( - scalaVersion := "2.11.4", + scalaVersion := "2.11.12", libraryDependencies += repatchTwitter, excludeDependencies += "net.databinder.dispatch" %% "dispatch-core" ) diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies2/build.sbt b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/build.sbt new file mode 100644 index 000000000..7b75a187f --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/build.sbt @@ -0,0 +1,11 @@ + +ThisBuild / scalaVersion := "2.11.12" + +organization := "io.get-coursier.test" +name := "sbt-coursier-exclude-dependencies" +version := "0.1.0-SNAPSHOT" + +libraryDependencies += "com.github.alexarchambault" %% "argonaut-shapeless_6.1" % "1.0.0-RC1" + +excludeDependencies += sbt.ExclusionRule("com.chuusai", "shapeless_2.11") +excludeDependencies += "io.argonaut" %% "argonaut" diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies2/coursier b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/coursier new file mode 100755 index 000000000..6cada6f8b Binary files /dev/null and b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/coursier differ diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies2/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/src/main/scala/Main.scala new file mode 100644 index 000000000..1bc056610 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/src/main/scala/Main.scala @@ -0,0 +1,32 @@ +import java.io.File +import java.nio.file.Files + +import scala.util.Try + +object Main extends App { + + def classFound(clsName: String) = Try( + Thread.currentThread() + .getContextClassLoader() + .loadClass(clsName) + ).toOption.nonEmpty + + val shapelessFound = classFound("shapeless.HList") + val argonautFound = classFound("argonaut.Json") + val argonautShapelessFound = classFound("argonaut.derive.MkEncodeJson") + + assert( + argonautShapelessFound, + "Expected to find class from argonaut-shapeless" + ) + assert( + !shapelessFound, + "Expected not to find classes from shapeless" + ) + assert( + !argonautFound, + "Expected not to find classes from argonaut" + ) + + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/exclude-dependencies2/test b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/test new file mode 100644 index 000000000..ad685c023 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/exclude-dependencies2/test @@ -0,0 +1,5 @@ +$ delete output +> run +$ exists output +> publishLocal +$ exec java -jar coursier launch io.get-coursier.test:sbt-coursier-exclude-dependencies_2.11:0.1.0-SNAPSHOT diff --git a/sbt/src/sbt-test/dependency-management/ext-pom-classifier/build.sbt b/sbt/src/sbt-test/dependency-management/ext-pom-classifier/build.sbt index cfbfbdb21..d3253a483 100644 --- a/sbt/src/sbt-test/dependency-management/ext-pom-classifier/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ext-pom-classifier/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val root = (project in file(".")) .settings( scalaVersion := "2.12.6", diff --git a/sbt/src/sbt-test/dependency-management/extra/changes/UseColor.sbt b/sbt/src/sbt-test/dependency-management/extra/changes/UseColor.sbt index fdb138835..2fc37decd 100644 --- a/sbt/src/sbt-test/dependency-management/extra/changes/UseColor.sbt +++ b/sbt/src/sbt-test/dependency-management/extra/changes/UseColor.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val root = (project in file(".")) .settings( organization := "org.example", diff --git a/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/a/src/main/scala/A.scala b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/a/src/main/scala/A.scala new file mode 100644 index 000000000..954405774 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/a/src/main/scala/A.scala @@ -0,0 +1,6 @@ + +case class A(msg: String) + +object A { + def default = A("OK") +} diff --git a/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/b/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/b/src/main/scala/Main.scala new file mode 100644 index 000000000..59bb6d372 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/b/src/main/scala/Main.scala @@ -0,0 +1,9 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + + val msg = shapeless.Generic[A].to(A.default).head + + Files.write(new File("output").toPath, msg.getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/build.sbt b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/build.sbt new file mode 100644 index 000000000..98731216b --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/build.sbt @@ -0,0 +1,13 @@ +ThisBuild / scalaVersion := "2.11.12" + +lazy val a = project + .settings( + libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.234" from "https://oss.sonatype.org/content/repositories/releases/com/chuusai/shapeless_2.11/2.3.1/shapeless_2.11-2.3.1.jar" + ) + +lazy val b = project + .dependsOn(a) + +lazy val root = project + .in(file(".")) + .aggregate(a, b) diff --git a/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/test b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/test new file mode 100644 index 000000000..ea53e1abb --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/fallback-dependencies-inter-project/test @@ -0,0 +1,3 @@ +$ delete output +> b/run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt b/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt index 1912a7fbb..11bcdf94e 100644 --- a/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt +++ b/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile" autoScalaLibrary := false diff --git a/sbt/src/sbt-test/dependency-management/global-plugins/build.sbt b/sbt/src/sbt-test/dependency-management/global-plugins/build.sbt new file mode 100644 index 000000000..5642f168f --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/global-plugins/build.sbt @@ -0,0 +1 @@ +scalaVersion := "2.12.8" diff --git a/sbt/src/sbt-test/dependency-management/global-plugins/global/plugins/metals.sbt b/sbt/src/sbt-test/dependency-management/global-plugins/global/plugins/metals.sbt new file mode 100644 index 000000000..8aae08736 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/global-plugins/global/plugins/metals.sbt @@ -0,0 +1,2 @@ +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.2.5") +addSbtPlugin("org.scalameta" % "sbt-metals" % "0.4.4") diff --git a/sbt/src/sbt-test/dependency-management/global-plugins/test b/sbt/src/sbt-test/dependency-management/global-plugins/test new file mode 100644 index 000000000..67a8b1ff1 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/global-plugins/test @@ -0,0 +1,2 @@ +> metalsEnable +> bloopInstall diff --git a/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/build.sbt b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/build.sbt new file mode 100644 index 000000000..8e7c4a097 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/build.sbt @@ -0,0 +1,3 @@ +ThisBuild / scalaVersion := "2.11.12" + +libraryDependencies += "org.apache.hadoop" % "hadoop-yarn-server-resourcemanager" % "2.7.1" diff --git a/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/src/main/scala/Main.scala new file mode 100644 index 000000000..032874759 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/src/main/scala/Main.scala @@ -0,0 +1,8 @@ +import java.io.File +import java.nio.file.Files + +import org.apache.zookeeper.ZooKeeper + +object Main extends App { + Files.write(new File("output").toPath, classOf[ZooKeeper].getSimpleName.getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/test b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/test new file mode 100644 index 000000000..2182f57b0 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/hadoop-yarn-server-resourcemanager/test @@ -0,0 +1,3 @@ +$ delete output +> run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/info/build.sbt b/sbt/src/sbt-test/dependency-management/info/build.sbt index 02b4f1447..185711816 100644 --- a/sbt/src/sbt-test/dependency-management/info/build.sbt +++ b/sbt/src/sbt-test/dependency-management/info/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + import scala.xml._ lazy val root = (project in file(".")). diff --git a/sbt/src/sbt-test/dependency-management/inter-project-resolvers/a/src/main/scala/A.scala b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/a/src/main/scala/A.scala new file mode 100644 index 000000000..954405774 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/a/src/main/scala/A.scala @@ -0,0 +1,6 @@ + +case class A(msg: String) + +object A { + def default = A("OK") +} diff --git a/sbt/src/sbt-test/dependency-management/inter-project-resolvers/b/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/b/src/main/scala/Main.scala new file mode 100644 index 000000000..f2c112187 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/b/src/main/scala/Main.scala @@ -0,0 +1,14 @@ +import java.io.File +import java.nio.file.Files + +import scalaz.stream._ +import scalaz.concurrent.Task + +object Main extends App { + + val pch = Process.constant((i:Int) => Task.now(())).take(3) + val count = Process.constant(1).toSource.to(pch).runLog.run.size + assert(count == 3) + + Files.write(new File("output").toPath, A.default.msg.getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/inter-project-resolvers/build.sbt b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/build.sbt new file mode 100644 index 000000000..625c7c0d2 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/build.sbt @@ -0,0 +1,17 @@ +ThisBuild / scalaVersion := "2.11.12" + +lazy val a = project + .settings( + resolvers += "Scalaz Bintray Repo" at "https://dl.bintray.com/scalaz/releases" + ) + +lazy val b = project + .dependsOn(a) + .settings( + // resolver added in inter-project dependency only - should still be fine + libraryDependencies += "org.scalaz.stream" %% "scalaz-stream" % "0.7.1a" + ) + +lazy val root = project + .in(file(".")) + .aggregate(a, b) diff --git a/sbt/src/sbt-test/dependency-management/inter-project-resolvers/test b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/test new file mode 100644 index 000000000..ea53e1abb --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project-resolvers/test @@ -0,0 +1,3 @@ +$ delete output +> b/run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/inter-project/a/src/main/scala/A.scala b/sbt/src/sbt-test/dependency-management/inter-project/a/src/main/scala/A.scala new file mode 100644 index 000000000..5308caa95 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project/a/src/main/scala/A.scala @@ -0,0 +1,6 @@ + +object A { + + def msg = "OK" + +} diff --git a/sbt/src/sbt-test/dependency-management/inter-project/b/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/inter-project/b/src/main/scala/Main.scala new file mode 100644 index 000000000..624039aa5 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project/b/src/main/scala/Main.scala @@ -0,0 +1,13 @@ +import java.io.File +import java.nio.file.Files + +import argonaut._, Argonaut._, ArgonautShapeless._ + +object Main extends App { + + case class CC(i: Int, s: String) + + val msg = CC(2, A.msg).asJson.spaces2 + + Files.write(new File("output").toPath, msg.getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/inter-project/build.sbt b/sbt/src/sbt-test/dependency-management/inter-project/build.sbt new file mode 100644 index 000000000..800464482 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project/build.sbt @@ -0,0 +1,26 @@ +ThisBuild / scalaVersion := "2.11.12" + +/** Module with the same Maven coordinates as shapeless 2.3.1 */ +lazy val `shapeless-mock` = project + .settings( + organization := "com.chuusai", + name := "shapeless", + version := "2.3.1" + ) + +lazy val a = project + .settings( + organization := "com.pany", + name := "a", + version := "0.0.1" + ) + +/** Transitively depends on the - real - shapeless 2.3.1 */ +lazy val b = project + .dependsOn(a) + .settings( + organization := "com.pany", + name := "b", + version := "0.0.1", + libraryDependencies += "com.github.alexarchambault" %% "argonaut-shapeless_6.2" % "1.2.0-M1" + ) diff --git a/sbt/src/sbt-test/dependency-management/inter-project/test b/sbt/src/sbt-test/dependency-management/inter-project/test new file mode 100644 index 000000000..ea53e1abb --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/inter-project/test @@ -0,0 +1,3 @@ +$ delete output +> b/run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/ivy-settings-a/build.sbt b/sbt/src/sbt-test/dependency-management/ivy-settings-a/build.sbt index f2e37783d..aabb0862d 100644 --- a/sbt/src/sbt-test/dependency-management/ivy-settings-a/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ivy-settings-a/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + externalIvySettings() externalIvyFile() diff --git a/sbt/src/sbt-test/dependency-management/ivy-settings-b/build.sbt b/sbt/src/sbt-test/dependency-management/ivy-settings-b/build.sbt index eb3bde0f2..95d2dfa06 100644 --- a/sbt/src/sbt-test/dependency-management/ivy-settings-b/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ivy-settings-b/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + externalIvySettings() libraryDependencies += "org.scalacheck" % "scalacheck" % "1.5" diff --git a/sbt/src/sbt-test/dependency-management/ivy-settings-c/build.sbt b/sbt/src/sbt-test/dependency-management/ivy-settings-c/build.sbt index c9beeb2f3..2e7cbd392 100644 --- a/sbt/src/sbt-test/dependency-management/ivy-settings-c/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ivy-settings-c/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val commonSettings = Seq( autoScalaLibrary := false, scalaModuleInfo := None, diff --git a/sbt/src/sbt-test/dependency-management/ivy-settings-multi-a/build.sbt b/sbt/src/sbt-test/dependency-management/ivy-settings-multi-a/build.sbt index d218debd4..12b354173 100644 --- a/sbt/src/sbt-test/dependency-management/ivy-settings-multi-a/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ivy-settings-multi-a/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val commonSettings = Seq( autoScalaLibrary := false, unmanagedJars in Compile ++= (scalaInstance map (_.allJars.toSeq)).value diff --git a/sbt/src/sbt-test/dependency-management/ivy-settings-multi-b/build.sbt b/sbt/src/sbt-test/dependency-management/ivy-settings-multi-b/build.sbt index 0718f9071..94a522095 100644 --- a/sbt/src/sbt-test/dependency-management/ivy-settings-multi-b/build.sbt +++ b/sbt/src/sbt-test/dependency-management/ivy-settings-multi-b/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val a = (project in file(".")). settings(externalIvySettings()) dependsOn(b) diff --git a/sbt/src/sbt-test/dependency-management/latest-local-plugin/changes/use-plugins.sbt b/sbt/src/sbt-test/dependency-management/latest-local-plugin/changes/use-plugins.sbt index 777b3f0ae..175234505 100644 --- a/sbt/src/sbt-test/dependency-management/latest-local-plugin/changes/use-plugins.sbt +++ b/sbt/src/sbt-test/dependency-management/latest-local-plugin/changes/use-plugins.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + addSbtPlugin("org.example" % "def" % "latest.integration") resolvers ++= { diff --git a/sbt/src/sbt-test/dependency-management/metadata-only-resolver/test b/sbt/src/sbt-test/dependency-management/metadata-only-resolver/disable similarity index 100% rename from sbt/src/sbt-test/dependency-management/metadata-only-resolver/test rename to sbt/src/sbt-test/dependency-management/metadata-only-resolver/disable diff --git a/sbt/src/sbt-test/dependency-management/no-pom-artifact/build.sbt b/sbt/src/sbt-test/dependency-management/no-pom-artifact/build.sbt new file mode 100644 index 000000000..7465c34d7 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/no-pom-artifact/build.sbt @@ -0,0 +1,30 @@ + +lazy val noPomCheck = TaskKey[Unit]("noPomCheck") + +noPomCheck := { + + val log = streams.value.log + + val configReport = update.value + .configuration(Compile) + .getOrElse { + throw new Exception( + "compile configuration not found in update report" + ) + } + + val artifacts = configReport + .modules + .flatMap(_.artifacts) + .map(_._1) + + val pomArtifacts = artifacts + .filter { a => + a.`type` == "pom" && a.classifier.isEmpty + } + + for (a <- pomArtifacts) + log.error(s"Found POM artifact $a") + + assert(pomArtifacts.isEmpty) +} diff --git a/sbt/src/sbt-test/dependency-management/no-pom-artifact/test b/sbt/src/sbt-test/dependency-management/no-pom-artifact/test new file mode 100644 index 000000000..67b4dc666 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/no-pom-artifact/test @@ -0,0 +1 @@ +> noPomCheck diff --git a/sbt/src/sbt-test/dependency-management/pom-classpaths/build.sbt b/sbt/src/sbt-test/dependency-management/pom-classpaths/build.sbt index 2cef1bd25..8e57b688a 100644 --- a/sbt/src/sbt-test/dependency-management/pom-classpaths/build.sbt +++ b/sbt/src/sbt-test/dependency-management/pom-classpaths/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + import complete._ import complete.DefaultParsers._ diff --git a/sbt/src/sbt-test/dependency-management/pom-parent-pom/build.sbt b/sbt/src/sbt-test/dependency-management/pom-parent-pom/build.sbt index 458581d12..fa8e4369f 100644 --- a/sbt/src/sbt-test/dependency-management/pom-parent-pom/build.sbt +++ b/sbt/src/sbt-test/dependency-management/pom-parent-pom/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + val checkIvyXml = taskKey[Unit]("Checks the ivy.xml transform was correct") lazy val root = (project in file(".")). diff --git a/sbt/src/sbt-test/dependency-management/profiles/build.sbt b/sbt/src/sbt-test/dependency-management/profiles/build.sbt new file mode 100644 index 000000000..33b6f2f72 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/profiles/build.sbt @@ -0,0 +1,5 @@ +ThisBuild / scalaVersion := "2.11.12" + +Compile / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat +libraryDependencies += "org.apache.spark" %% "spark-sql" % "1.6.2" +csrMavenProfiles += "hadoop-2.6" diff --git a/sbt/src/sbt-test/dependency-management/profiles/output b/sbt/src/sbt-test/dependency-management/profiles/output new file mode 100644 index 000000000..a0aba9318 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/profiles/output @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-management/profiles/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/profiles/src/main/scala/Main.scala new file mode 100644 index 000000000..9ac86fe34 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/profiles/src/main/scala/Main.scala @@ -0,0 +1,19 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + val p = new java.util.Properties + p.load( + Thread.currentThread() + .getContextClassLoader + .getResource("common-version-info.properties") + .openStream() + ) + + val hadoopVersion = p.getProperty("version") + Console.err.println(s"Found hadoop version $hadoopVersion") + + assert(hadoopVersion == "2.6.0") + + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/profiles/test b/sbt/src/sbt-test/dependency-management/profiles/test new file mode 100644 index 000000000..2182f57b0 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/profiles/test @@ -0,0 +1,3 @@ +$ delete output +> run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/retrieve-managed-sync/build.sbt b/sbt/src/sbt-test/dependency-management/retrieve-managed-sync/build.sbt index 4568f6663..980fcc3cd 100644 --- a/sbt/src/sbt-test/dependency-management/retrieve-managed-sync/build.sbt +++ b/sbt/src/sbt-test/dependency-management/retrieve-managed-sync/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + retrieveManaged := true libraryDependencies += "log4j" % "log4j" % "1.2.16" diff --git a/sbt/src/sbt-test/dependency-management/scala-organization-version-check/build.sbt b/sbt/src/sbt-test/dependency-management/scala-organization-version-check/build.sbt index efb198677..c969842f7 100644 --- a/sbt/src/sbt-test/dependency-management/scala-organization-version-check/build.sbt +++ b/sbt/src/sbt-test/dependency-management/scala-organization-version-check/build.sbt @@ -2,7 +2,7 @@ scalaOrganization := "org.other" scalaArtifacts += "thing" -scalaVersion := "2.11.8" +ThisBuild / scalaVersion := "2.11.12" libraryDependencies ++= Seq( "org.other" % "thing" % "1.2.3", diff --git a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt index 82a7dce27..42d335c4d 100644 --- a/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt +++ b/sbt/src/sbt-test/dependency-management/scala-organization/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + organization := "org.dummy" scalaOrganization := "org.other" diff --git a/sbt/src/sbt-test/dependency-management/scala-version-check-exempt/build.sbt b/sbt/src/sbt-test/dependency-management/scala-version-check-exempt/build.sbt index 6f66bc879..540318393 100644 --- a/sbt/src/sbt-test/dependency-management/scala-version-check-exempt/build.sbt +++ b/sbt/src/sbt-test/dependency-management/scala-version-check-exempt/build.sbt @@ -1,6 +1,6 @@ // https://github.com/sbt/sbt/issues/1818 -scalaVersion := "2.11.5" +ThisBuild / scalaVersion := "2.11.12" libraryDependencies += "org.scala-lang" %% "scala-actors-migration" % "1.1.0" libraryDependencies += "org.scala-lang" %% "scala-pickling" % "0.9.1" diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/build.sbt b/sbt/src/sbt-test/dependency-management/snapshot-local/build.sbt new file mode 100644 index 000000000..d87463465 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/build.sbt @@ -0,0 +1,38 @@ +ThisBuild / organization := "com.example" +ThisBuild / scalaVersion := "2.12.8" + +def customIvyPaths: Seq[Def.Setting[_]] = Seq( + ivyPaths := IvyPaths((baseDirectory in ThisBuild).value, Some((baseDirectory in ThisBuild).value / "ivy-cache")) +) + +lazy val sharedResolver: Resolver = { + val r = Resolver.defaultShared + r withConfiguration (r.configuration withIsLocal false) + //MavenRepository("example-shared-repo", "file:///tmp/shared-maven-repo-bad-example") + //Resolver.file("example-shared-repo", repoDir)(Resolver.defaultPatterns) +} + +lazy val common = project + .settings(customIvyPaths) + .settings( + organization := "com.badexample", + name := "badexample", + version := "1.0-SNAPSHOT", + publishTo := Some(sharedResolver), + crossVersion := Disabled(), + publishMavenStyle := (sharedResolver match { + case repo: PatternsBasedRepository => repo.patterns.isMavenCompatible + case _: RawRepository => false // TODO - look deeper + case _: MavenRepository => true + case _ => false // TODO - Handle chain repository? + }) + ) + +lazy val dependent = project + .settings(customIvyPaths) + .settings( + // Ignore the inter-project resolver, so we force to look remotely. + resolvers += sharedResolver, + fullResolvers := fullResolvers.value.filterNot(_==projectResolver.value), + libraryDependencies += "com.badexample" % "badexample" % "1.0-SNAPSHOT" + ) diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/changes/BadCommon.scala b/sbt/src/sbt-test/dependency-management/snapshot-local/changes/BadCommon.scala new file mode 100644 index 000000000..4df4235d5 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/changes/BadCommon.scala @@ -0,0 +1,2 @@ +object Common { +} \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/changes/GoodCommon.scala b/sbt/src/sbt-test/dependency-management/snapshot-local/changes/GoodCommon.scala new file mode 100644 index 000000000..3f9b39258 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/changes/GoodCommon.scala @@ -0,0 +1,3 @@ +object Common { + def name = "common" +} \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/common/src/main/scala/Common.scala b/sbt/src/sbt-test/dependency-management/snapshot-local/common/src/main/scala/Common.scala new file mode 100644 index 000000000..d6175ce12 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/common/src/main/scala/Common.scala @@ -0,0 +1,3 @@ +object Common { + +} \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/dependent/src/main/scala/User.scala b/sbt/src/sbt-test/dependency-management/snapshot-local/dependent/src/main/scala/User.scala new file mode 100644 index 000000000..8bc6103c8 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/dependent/src/main/scala/User.scala @@ -0,0 +1,3 @@ +object User { + println(Common.name) +} \ No newline at end of file diff --git a/sbt/src/sbt-test/dependency-management/snapshot-local/test b/sbt/src/sbt-test/dependency-management/snapshot-local/test new file mode 100644 index 000000000..9fa3d37ba --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/snapshot-local/test @@ -0,0 +1,21 @@ +# Ivy is able to check for SNAPSHOT across different resolvers +# Coursier seems to be sticky about the resolver within the TTL + +> show dependent/fullResolvers + +# Validate that a bad dependency fails the compile +$ copy-file changes/BadCommon.scala common/src/main/scala/Common.scala +> common/publishLocal + +# Force dep resolution to be successful, then compilation to fail +> dependent/update +-> dependent/compile + +# Push new good change to the same repository. +$ copy-file changes/GoodCommon.scala common/src/main/scala/Common.scala +$ sleep 1000 +> common/publishLocal + +# This should compile now because Coursier checks for local update +> show dependent/update +> dependent/compile diff --git a/sbt/src/sbt-test/dependency-management/snapshot-resolution/build.sbt b/sbt/src/sbt-test/dependency-management/snapshot-resolution/build.sbt index b7d912223..be1d08d66 100644 --- a/sbt/src/sbt-test/dependency-management/snapshot-resolution/build.sbt +++ b/sbt/src/sbt-test/dependency-management/snapshot-resolution/build.sbt @@ -1,6 +1,9 @@ ThisBuild / organization := "com.example" ThisBuild / scalaVersion := "2.12.8" +// TTL is 24h so we can't detect the change +ThisBuild / useCoursier := false + def customIvyPaths: Seq[Def.Setting[_]] = Seq( ivyPaths := IvyPaths((baseDirectory in ThisBuild).value, Some((baseDirectory in ThisBuild).value / "ivy-cache")) ) diff --git a/sbt/src/sbt-test/dependency-management/sources/build.sbt b/sbt/src/sbt-test/dependency-management/sources/build.sbt index 7feee83fe..91f35d197 100644 --- a/sbt/src/sbt-test/dependency-management/sources/build.sbt +++ b/sbt/src/sbt-test/dependency-management/sources/build.sbt @@ -1,5 +1,7 @@ -lazy val root = (project in file(".")). - settings( +ThisBuild / useCoursier := false + +lazy val root = (project in file(".")) + .settings( libraryDependencies += "net.liftweb" % "lift-webkit" % "1.0" intransitive(), libraryDependencies += "org.scalacheck" % "scalacheck" % "1.5" intransitive(), autoScalaLibrary := false, @@ -11,15 +13,15 @@ lazy val root = (project in file(".")). def getSources(report: UpdateReport) = report.matching(artifactFilter(`classifier` = "sources") ) def checkSources(report: UpdateReport): Unit = -{ - val srcs = getSources(report) - if(srcs.isEmpty) - sys.error("No sources retrieved") - else if(srcs.size != 2) - sys.error("Incorrect sources retrieved:\n\t" + srcs.mkString("\n\t")) - else - () -} + { + val srcs = getSources(report) + if(srcs.isEmpty) + sys.error(s"No sources retrieved\n\n$report") + else if(srcs.size != 2) + sys.error("Incorrect sources retrieved:\n\t" + srcs.mkString("\n\t")) + else + () + } def checkBinaries(report: UpdateReport): Unit = { diff --git a/sbt/src/sbt-test/dependency-management/test-artifact/cache.sbt b/sbt/src/sbt-test/dependency-management/test-artifact/cache.sbt index 54bded6d5..f6fe7926d 100644 --- a/sbt/src/sbt-test/dependency-management/test-artifact/cache.sbt +++ b/sbt/src/sbt-test/dependency-management/test-artifact/cache.sbt @@ -1,10 +1,10 @@ +ThisBuild / useCoursier := false + ivyPaths := { val base = baseDirectory.value IvyPaths(base, Some(base / "ivy-cache")) } managedScalaInstance := false - autoScalaLibrary := false - crossPaths := false diff --git a/sbt/src/sbt-test/dependency-management/transitive-version-range/build.sbt b/sbt/src/sbt-test/dependency-management/transitive-version-range/build.sbt index 0f8c84c1e..6e3467d19 100644 --- a/sbt/src/sbt-test/dependency-management/transitive-version-range/build.sbt +++ b/sbt/src/sbt-test/dependency-management/transitive-version-range/build.sbt @@ -1,5 +1,6 @@ +ThisBuild / scalaVersion := "2.11.12" + organization := "com.test" name := "maven-version-range-bug" version := "1.0.0-SNAPSHOT" -scalaVersion := "2.11.6" -libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.7.8.1" \ No newline at end of file +libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.7.8.1" diff --git a/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt b/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt index 36f0b199b..cde5ebc0e 100644 --- a/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt +++ b/sbt/src/sbt-test/dependency-management/update-sbt-classifiers/build.sbt @@ -1,4 +1,4 @@ -scalaVersion := "2.11.11" +ThisBuild / scalaVersion := "2.11.12" ivyConfiguration := { throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / ivyConfiguration") diff --git a/sbt/src/sbt-test/dependency-management/url-no-head/build.sbt b/sbt/src/sbt-test/dependency-management/url-no-head/build.sbt new file mode 100644 index 000000000..9fdc2681d --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/url-no-head/build.sbt @@ -0,0 +1,3 @@ +ThisBuild / scalaVersion := "2.11.12" + +libraryDependencies += "ccl.northwestern.edu" % "netlogo" % "5.3.1" % "provided" from s"https://github.com/NetLogo/NetLogo/releases/download/5.3.1/NetLogo.jar" diff --git a/sbt/src/sbt-test/dependency-management/url-no-head/src/main/scala/Main.scala b/sbt/src/sbt-test/dependency-management/url-no-head/src/main/scala/Main.scala new file mode 100644 index 000000000..d75f66eaf --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/url-no-head/src/main/scala/Main.scala @@ -0,0 +1,11 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + // Not using directly the NetLogo 5.x lib, which seems to depend on Scala 2.9 + // Can't find a way to check that NetLogo.jar is in the classpath + // These don't work, even with fork := true: + // assert(Thread.currentThread.getContextClassLoader.getResource("org/nlogo/nvm/Task.class") != null) + // Thread.currentThread.getContextClassLoader.getResource("org/nlogo/nvm/Task.class") + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/dependency-management/url-no-head/test b/sbt/src/sbt-test/dependency-management/url-no-head/test new file mode 100644 index 000000000..2182f57b0 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/url-no-head/test @@ -0,0 +1,3 @@ +$ delete output +> run +$ exists output diff --git a/sbt/src/sbt-test/dependency-management/url/build.sbt b/sbt/src/sbt-test/dependency-management/url/build.sbt index 4e384ca23..f3b8f6fa2 100644 --- a/sbt/src/sbt-test/dependency-management/url/build.sbt +++ b/sbt/src/sbt-test/dependency-management/url/build.sbt @@ -11,14 +11,12 @@ lazy val root = (project in file(".")). def checkClasspath(conf: Configuration) = fullClasspath in conf map { cp => - try - { + try { val loader = ClasspathUtilities.toLoader(cp.files) Class.forName("org.jsoup.Jsoup", false, loader) () } - catch - { - case _: ClassNotFoundException => sys.error("Dependency not downloaded.") + catch { + case _: ClassNotFoundException => sys.error(s"could not instantiate org.jsoup.Jsoup: ${cp.files}") } } diff --git a/sbt/src/sbt-test/dependency-management/url/test b/sbt/src/sbt-test/dependency-management/url/pending similarity index 100% rename from sbt/src/sbt-test/dependency-management/url/test rename to sbt/src/sbt-test/dependency-management/url/pending diff --git a/sbt/src/sbt-test/dependency-management/version-interval/build.sbt b/sbt/src/sbt-test/dependency-management/version-interval/build.sbt new file mode 100644 index 000000000..efeaf236e --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/version-interval/build.sbt @@ -0,0 +1,35 @@ + +libraryDependencies += "org.json4s" %% "json4s-native" % "[3.3.0,3.5.0)" + + +lazy val actualVersionCheck = taskKey[Unit]("") + +actualVersionCheck := { + + val log = streams.value.log + + val configReport = update.value + .configuration(Compile) + .getOrElse { + sys.error("compile configuration not found in update report") + } + + val modules = configReport + .modules + .map(_.module) + + assert(modules.nonEmpty) + assert(modules.exists(_.name.startsWith("json4s-native"))) + + val wrongModules = modules.filter { m => + val v = m.revision + v.contains("[") || v.contains("]") || v.contains("(") || v.contains(")") + } + + if (wrongModules.nonEmpty) { + log.error("Found unexpected intervals in revisions") + for (m <- wrongModules) + log.error(s" ${m.organization}:${m.name}:${m.revision}") + sys.error("Found intervals in revisions") + } +} diff --git a/sbt/src/sbt-test/dependency-management/version-interval/test b/sbt/src/sbt-test/dependency-management/version-interval/test new file mode 100644 index 000000000..99803d595 --- /dev/null +++ b/sbt/src/sbt-test/dependency-management/version-interval/test @@ -0,0 +1 @@ +> actualVersionCheck diff --git a/sbt/src/sbt-test/plugins/dotty/LICENSE b/sbt/src/sbt-test/plugins/dotty/LICENSE new file mode 100644 index 000000000..728844ee3 --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2015 The dotty-example-project contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/sbt/src/sbt-test/plugins/dotty/README.md b/sbt/src/sbt-test/plugins/dotty/README.md new file mode 100644 index 000000000..e476c5c1d --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/README.md @@ -0,0 +1 @@ +Cut-n-pasted from https://github.com/lampepfl/dotty-example-project/tree/a753b14e281bbaa6c69f26298913ad6feba969c7 diff --git a/sbt/src/sbt-test/plugins/dotty/build.sbt b/sbt/src/sbt-test/plugins/dotty/build.sbt new file mode 100644 index 000000000..e38070b5e --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/build.sbt @@ -0,0 +1 @@ +scalaVersion := "0.13.0-RC1" diff --git a/sbt/src/sbt-test/plugins/dotty/project/build.properties b/sbt/src/sbt-test/plugins/dotty/project/build.properties new file mode 100644 index 000000000..16dc090c5 --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/project/build.properties @@ -0,0 +1,3 @@ +# sbt-coursier scripted tests: required, as we default to sbt 1.0.3, +# but sbt-dotty requires sbt >= 1.2.7 +sbt.version=1.2.7 diff --git a/sbt/src/sbt-test/plugins/dotty/project/plugins.sbt b/sbt/src/sbt-test/plugins/dotty/project/plugins.sbt new file mode 100644 index 000000000..b5de60fc6 --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.3.0") diff --git a/sbt/src/sbt-test/plugins/dotty/src/main/scala/Main.scala b/sbt/src/sbt-test/plugins/dotty/src/main/scala/Main.scala new file mode 100644 index 000000000..8a44ae4ef --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/src/main/scala/Main.scala @@ -0,0 +1,16 @@ + +object Main { + + def main(args: Array[String]): Unit = { + + runExample("Trait Params")(TraitParams.test) + + } + + private def runExample(name: String)(f: => Unit) = { + println(Console.MAGENTA + s"$name example:" + Console.RESET) + f + println() + } + +} diff --git a/sbt/src/sbt-test/plugins/dotty/src/main/scala/TraitParams.scala b/sbt/src/sbt-test/plugins/dotty/src/main/scala/TraitParams.scala new file mode 100644 index 000000000..5d4409971 --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/src/main/scala/TraitParams.scala @@ -0,0 +1,21 @@ +/** + * Trait Parameters: https://dotty.epfl.ch/docs/reference/other-new-features/trait-parameters.html + */ +object TraitParams { + + trait Base(val msg: String) + class A extends Base("Hello") + class B extends Base("Dotty!") + + // Union types only exist in Dotty, so there's no chance that this will accidentally be compiled with Scala 2 + private def printMessages(msgs: (A | B)*) = println(msgs.map(_.msg).mkString(" ")) + + def test: Unit = { + + printMessages(new A, new B) + + // Sanity check the classpath: this won't run if the dotty jar is not present. + val x: Int => Int = z => z + x(1) + } +} diff --git a/sbt/src/sbt-test/plugins/dotty/test b/sbt/src/sbt-test/plugins/dotty/test new file mode 100644 index 000000000..62ea636c1 --- /dev/null +++ b/sbt/src/sbt-test/plugins/dotty/test @@ -0,0 +1 @@ +> run diff --git a/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/build.sbt b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/build.sbt new file mode 100644 index 000000000..6dcc058c2 --- /dev/null +++ b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/build.sbt @@ -0,0 +1,2 @@ +scalaVersion := "2.12.2" +enablePlugins(ScalafmtPlugin) diff --git a/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/project/extra.sbt b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/project/extra.sbt new file mode 100644 index 000000000..4aa3881f4 --- /dev/null +++ b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/project/extra.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.15") diff --git a/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/src/main/scala/Main.scala b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/src/main/scala/Main.scala new file mode 100644 index 000000000..61295349d --- /dev/null +++ b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/src/main/scala/Main.scala @@ -0,0 +1,6 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/test b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/test new file mode 100644 index 000000000..97b42a4f4 --- /dev/null +++ b/sbt/src/sbt-test/plugins/neo-sbt-scalafmt/test @@ -0,0 +1 @@ +> scalafmt diff --git a/sbt/src/sbt-test/plugins/sbt-native-packager/build.sbt b/sbt/src/sbt-test/plugins/sbt-native-packager/build.sbt new file mode 100644 index 000000000..4c3343012 --- /dev/null +++ b/sbt/src/sbt-test/plugins/sbt-native-packager/build.sbt @@ -0,0 +1,20 @@ +ThisBuild / scalaVersion := "2.12.8" + +name := "hello" +enablePlugins(JavaAppPackaging) + +lazy val check = taskKey[Unit]("") + +check := { + val cmd = "target/universal/stage/bin/hello" + val cmd0 = + if (sys.props("os.name").toLowerCase(java.util.Locale.ROOT).contains("windows")) + cmd + ".bat" + else + cmd + val b = new ProcessBuilder(cmd0) + b.inheritIO() + val p = b.start() + val retCode = p.waitFor() + assert(retCode == 0, s"Command $cmd returned code $retCode") +} diff --git a/sbt/src/sbt-test/plugins/sbt-native-packager/project/plugins.sbt b/sbt/src/sbt-test/plugins/sbt-native-packager/project/plugins.sbt new file mode 100644 index 000000000..414d83d34 --- /dev/null +++ b/sbt/src/sbt-test/plugins/sbt-native-packager/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.20") diff --git a/sbt/src/sbt-test/plugins/sbt-native-packager/src/main/scala/Main.scala b/sbt/src/sbt-test/plugins/sbt-native-packager/src/main/scala/Main.scala new file mode 100644 index 000000000..61295349d --- /dev/null +++ b/sbt/src/sbt-test/plugins/sbt-native-packager/src/main/scala/Main.scala @@ -0,0 +1,6 @@ +import java.io.File +import java.nio.file.Files + +object Main extends App { + Files.write(new File("output").toPath, "OK".getBytes("UTF-8")) +} diff --git a/sbt/src/sbt-test/plugins/sbt-native-packager/test b/sbt/src/sbt-test/plugins/sbt-native-packager/test new file mode 100644 index 000000000..bb563a74f --- /dev/null +++ b/sbt/src/sbt-test/plugins/sbt-native-packager/test @@ -0,0 +1,5 @@ +$ delete output +> stage +> check +$ exists output +$ delete output diff --git a/sbt/src/sbt-test/plugins/scala-js/build.sbt b/sbt/src/sbt-test/plugins/scala-js/build.sbt new file mode 100644 index 000000000..2c43a4b30 --- /dev/null +++ b/sbt/src/sbt-test/plugins/scala-js/build.sbt @@ -0,0 +1,3 @@ +scalaVersion := "2.12.3" +enablePlugins(ScalaJSPlugin) +libraryDependencies += "org.scala-js" %%% "scalajs-java-time" % "0.2.2" diff --git a/sbt/src/sbt-test/plugins/scala-js/project/extra.sbt b/sbt/src/sbt-test/plugins/scala-js/project/extra.sbt new file mode 100644 index 000000000..4f6de4f49 --- /dev/null +++ b/sbt/src/sbt-test/plugins/scala-js/project/extra.sbt @@ -0,0 +1 @@ +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.19") diff --git a/sbt/src/sbt-test/plugins/scala-js/test b/sbt/src/sbt-test/plugins/scala-js/test new file mode 100644 index 000000000..103bd8d2f --- /dev/null +++ b/sbt/src/sbt-test/plugins/scala-js/test @@ -0,0 +1 @@ +> update diff --git a/sbt/src/sbt-test/plugins/unidoc/build.sbt b/sbt/src/sbt-test/plugins/unidoc/build.sbt new file mode 100644 index 000000000..3aa46422f --- /dev/null +++ b/sbt/src/sbt-test/plugins/unidoc/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := "2.12.1" +scalacOptions += "-Xfatal-warnings" // required for the test + +enablePlugins(ScalaUnidocPlugin) +autoAPIMappings := true diff --git a/sbt/src/sbt-test/plugins/unidoc/project/extra.sbt b/sbt/src/sbt-test/plugins/unidoc/project/extra.sbt new file mode 100644 index 000000000..ade7d89a5 --- /dev/null +++ b/sbt/src/sbt-test/plugins/unidoc/project/extra.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.2") diff --git a/sbt/src/sbt-test/plugins/unidoc/src/main/scala/Foo.scala b/sbt/src/sbt-test/plugins/unidoc/src/main/scala/Foo.scala new file mode 100644 index 000000000..b5ba8323e --- /dev/null +++ b/sbt/src/sbt-test/plugins/unidoc/src/main/scala/Foo.scala @@ -0,0 +1,3 @@ + +/** Default instances for Scala's [[scala.concurrent.Future Future]]. */ +class Foo diff --git a/sbt/src/sbt-test/plugins/unidoc/test b/sbt/src/sbt-test/plugins/unidoc/test new file mode 100644 index 000000000..7439923b4 --- /dev/null +++ b/sbt/src/sbt-test/plugins/unidoc/test @@ -0,0 +1 @@ +> unidoc diff --git a/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt b/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt index 55b3bac97..493c6dcac 100644 --- a/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt +++ b/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt @@ -11,12 +11,15 @@ lazy val root = (project in file(".")) sbtPlugin := true, TaskKey[Unit]("check") := mkCheck("2.12", "1.0", "1.").value, - TaskKey[Unit]("check2") := mkCheck("2.10", "0.13", "0.13").value + TaskKey[Unit]("check2") := mkCheck("2.10", "0.13", "0.13").value, + + // Coursier requires extra resolver for sbt 0.13 + resolvers += Resolver.typesafeIvyRepo("releases"), ) lazy val app = (project in file("app")) -def mkCheck(scalaBinV: String, sbtBinVer: String, sbtVerPrefix: String) = Def task { +def mkCheck(scalaBinV: String, sbtBinVer: String, sbtVerPrefix: String) = Def.task { val crossV = (sbtVersion in pluginCrossBuild).value val crossBinV = (sbtBinaryVersion in pluginCrossBuild).value val sv = projectID.value.extraAttributes("e:scalaVersion") diff --git a/sbt/src/sbt-test/project/extra/build.sbt b/sbt/src/sbt-test/project/extra/build.sbt index 113584958..556d3e61b 100644 --- a/sbt/src/sbt-test/project/extra/build.sbt +++ b/sbt/src/sbt-test/project/extra/build.sbt @@ -1,3 +1,5 @@ +ThisBuild / useCoursier := false + lazy val root = (project in file(".")). settings( autoScalaLibrary := false, diff --git a/sbt/src/test/scala/sbt/RunFromSourceMain.scala b/sbt/src/test/scala/sbt/RunFromSourceMain.scala index b91e610ee..1753f6cf5 100644 --- a/sbt/src/test/scala/sbt/RunFromSourceMain.scala +++ b/sbt/src/test/scala/sbt/RunFromSourceMain.scala @@ -14,7 +14,7 @@ import xsbti._ import scala.sys.process.Process object RunFromSourceMain { - private val sbtVersion = "1.1.4" // TestBuildInfo.version + private val sbtVersion = TestBuildInfo.version private val scalaVersion = "2.12.6" def fork(workingDirectory: File): Process = { diff --git a/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala b/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala index db1727a2a..a3fb7cf27 100644 --- a/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala +++ b/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala @@ -167,93 +167,59 @@ final class ScriptedTests( import RemoteSbtCreatorKind._ val (group, name) = testName s"$group/$name" match { - case "actions/add-alias" => LauncherBased // sbt/Package$ - case "actions/cross-multiproject" => LauncherBased // tbd - case "actions/external-doc" => LauncherBased // sbt/Package$ - case "actions/input-task" => LauncherBased // sbt/Package$ - case "actions/input-task-dyn" => LauncherBased // sbt/Package$ - case "classloader-cache/akka-actor-system" => LauncherBased // sbt/Package$ - case "classloader-cache/jni" => LauncherBased // sbt/Package$ - case "classloader-cache/library-mismatch" => LauncherBased // sbt/Package$ - case "classloader-cache/runtime-layers" => LauncherBased // sbt/Package$ - case "classloader-cache/package-private" => LauncherBased // sbt/Package$ - case "compiler-project/dotty-compiler-plugin" => LauncherBased // sbt/Package$ - case "compiler-project/run-test" => LauncherBased // sbt/Package$ - case "compiler-project/src-dep-plugin" => LauncherBased // sbt/Package$ - case "dependency-management/artifact" => LauncherBased // tbd - case "dependency-management/cache-classifiers" => LauncherBased // tbd - case "dependency-management/cache-local" => LauncherBased // tbd - case "dependency-management/cache-resolver" => LauncherBased // sbt/Package$ - case "dependency-management/cache-update" => LauncherBased // tbd - case "dependency-management/cached-resolution-circular" => LauncherBased // tbd - case "dependency-management/cached-resolution-classifier" => LauncherBased // tbd - case "dependency-management/cached-resolution-configurations" => LauncherBased // tbd - case "dependency-management/cached-resolution-conflicts" => LauncherBased // tbd - case "dependency-management/cached-resolution-exclude" => LauncherBased // tbd - case "dependency-management/cached-resolution-force" => LauncherBased // tbd - case "dependency-management/cached-resolution-interproj" => LauncherBased // tbd - case "dependency-management/cached-resolution-overrides" => LauncherBased // tbd - case "dependency-management/chainresolver" => LauncherBased // tbd - case "dependency-management/circular-dependency" => LauncherBased // tbd - case "dependency-management/classifier" => LauncherBased // tbd - case "dependency-management/default-resolvers" => LauncherBased // tbd - case "dependency-management/deliver-artifacts" => LauncherBased // tbd - case "dependency-management/exclude-transitive" => LauncherBased // tbd - case "dependency-management/extra" => LauncherBased // tbd - case "dependency-management/force" => LauncherBased // tbd - case "dependency-management/info" => LauncherBased // tbd - case "dependency-management/inline-dependencies-a" => LauncherBased // tbd - case "dependency-management/ivy-settings-c" => LauncherBased // sbt/Package$ - case "dependency-management/latest-local-plugin" => LauncherBased // sbt/Package$ - case "dependency-management/metadata-only-resolver" => LauncherBased // tbd - case "dependency-management/no-file-fails-publish" => LauncherBased // tbd - case "dependency-management/override" => LauncherBased // tbd - case "dependency-management/parent-publish" => LauncherBased // sbt/Package$ - case "dependency-management/pom-parent-pom" => LauncherBased // tbd - case "dependency-management/publish-to-maven-local-file" => LauncherBased // sbt/Package$ - case "dependency-management/snapshot-resolution" => LauncherBased // tbd - case "dependency-management/test-artifact" => LauncherBased // sbt/Package$ - case "dependency-management/transitive-version-range" => LauncherBased // tbd - case "dependency-management/update-sbt-classifiers" => LauncherBased // tbd - case "dependency-management/url" => LauncherBased // tbd - case "java/argfile" => LauncherBased // sbt/Package$ - case "java/cross" => LauncherBased // sbt/Package$ - case "java/basic" => LauncherBased // sbt/Package$ - case "java/varargs-main" => LauncherBased // sbt/Package$ - case "package/lazy-name" => LauncherBased // sbt/Package$ - case "package/manifest" => LauncherBased // sbt/Package$ - case "package/resources" => LauncherBased // sbt/Package$ - case "project/Class.forName" => LauncherBased // sbt/Package$ - case "project/binary-plugin" => LauncherBased // sbt/Package$ - case "project/default-settings" => LauncherBased // sbt/Package$ - case "project/extra" => LauncherBased // tbd - case "project/flatten" => LauncherBased // sbt/Package$ - case "project/generated-root-no-publish" => LauncherBased // tbd - case "project/giter8-plugin" => LauncherBased // tbd - case "project/lib" => LauncherBased // sbt/Package$ - case "project/scripted-plugin" => LauncherBased // tbd - case "project/scripted-skip-incompatible" => LauncherBased // sbt/Package$ - case "project/session-update-from-cmd" => LauncherBased // tbd - case "project/transitive-plugins" => LauncherBased // tbd - case "run/awt" => LauncherBased // sbt/Package$ - case "run/classpath" => LauncherBased // sbt/Package$ - case "run/daemon" => LauncherBased // sbt/Package$ - case "run/daemon-exit" => LauncherBased // sbt/Package$ - case "run/error" => LauncherBased // sbt/Package$ - case "run/fork" => LauncherBased // sbt/Package$ - case "run/fork-loader" => LauncherBased // sbt/Package$ - case "run/non-local-main" => LauncherBased // sbt/Package$ - case "run/spawn" => LauncherBased // sbt/Package$ - case "run/spawn-exit" => LauncherBased // sbt/Package$ - case "source-dependencies/binary" => LauncherBased // sbt/Package$ - case "source-dependencies/export-jars" => LauncherBased // sbt/Package$ - case "source-dependencies/implicit-search" => LauncherBased // sbt/Package$ - case "source-dependencies/java-basic" => LauncherBased // sbt/Package$ - case "source-dependencies/less-inter-inv" => LauncherBased // sbt/Package$ - case "source-dependencies/less-inter-inv-java" => LauncherBased // sbt/Package$ - case "source-dependencies/linearization" => LauncherBased // sbt/Package$ - case "source-dependencies/named" => LauncherBased // sbt/Package$ - case "source-dependencies/specialized" => LauncherBased // sbt/Package$ + case "actions/add-alias" => LauncherBased // sbt/Package$ + case "actions/cross-multiproject" => LauncherBased // tbd + case "actions/external-doc" => LauncherBased // sbt/Package$ + case "actions/input-task" => LauncherBased // sbt/Package$ + case "actions/input-task-dyn" => LauncherBased // sbt/Package$ + case "classloader-cache/akka-actor-system" => LauncherBased // sbt/Package$ + case "classloader-cache/jni" => LauncherBased // sbt/Package$ + case "classloader-cache/library-mismatch" => LauncherBased // sbt/Package$ + case "classloader-cache/runtime-layers" => LauncherBased // sbt/Package$ + case "classloader-cache/package-private" => LauncherBased // sbt/Package$ + case "compiler-project/dotty-compiler-plugin" => LauncherBased // sbt/Package$ + case "compiler-project/run-test" => LauncherBased // sbt/Package$ + case "compiler-project/src-dep-plugin" => LauncherBased // sbt/Package$ + case gn if gn.startsWith("dependency-management/") => LauncherBased // sbt/Package$ + case gn if gn.startsWith("plugins/") => LauncherBased // sbt/Package$ + case "java/argfile" => LauncherBased // sbt/Package$ + case "java/cross" => LauncherBased // sbt/Package$ + case "java/basic" => LauncherBased // sbt/Package$ + case "java/varargs-main" => LauncherBased // sbt/Package$ + case "package/lazy-name" => LauncherBased // sbt/Package$ + case "package/manifest" => LauncherBased // sbt/Package$ + case "package/resources" => LauncherBased // sbt/Package$ + case "project/Class.forName" => LauncherBased // sbt/Package$ + case "project/binary-plugin" => LauncherBased // sbt/Package$ + case "project/default-settings" => LauncherBased // sbt/Package$ + case "project/extra" => LauncherBased // tbd + case "project/flatten" => LauncherBased // sbt/Package$ + case "project/generated-root-no-publish" => LauncherBased // tbd + case "project/giter8-plugin" => LauncherBased // tbd + case "project/lib" => LauncherBased // sbt/Package$ + case "project/scripted-plugin" => LauncherBased // tbd + case "project/scripted-skip-incompatible" => LauncherBased // sbt/Package$ + case "project/session-update-from-cmd" => LauncherBased // tbd + case "project/transitive-plugins" => LauncherBased // tbd + case "run/awt" => LauncherBased // sbt/Package$ + case "run/classpath" => LauncherBased // sbt/Package$ + case "run/daemon" => LauncherBased // sbt/Package$ + case "run/daemon-exit" => LauncherBased // sbt/Package$ + case "run/error" => LauncherBased // sbt/Package$ + case "run/fork" => LauncherBased // sbt/Package$ + case "run/fork-loader" => LauncherBased // sbt/Package$ + case "run/non-local-main" => LauncherBased // sbt/Package$ + case "run/spawn" => LauncherBased // sbt/Package$ + case "run/spawn-exit" => LauncherBased // sbt/Package$ + case "source-dependencies/binary" => LauncherBased // sbt/Package$ + case "source-dependencies/export-jars" => LauncherBased // sbt/Package$ + case "source-dependencies/implicit-search" => LauncherBased // sbt/Package$ + case "source-dependencies/java-basic" => LauncherBased // sbt/Package$ + case "source-dependencies/less-inter-inv" => LauncherBased // sbt/Package$ + case "source-dependencies/less-inter-inv-java" => LauncherBased // sbt/Package$ + case "source-dependencies/linearization" => LauncherBased // sbt/Package$ + case "source-dependencies/named" => LauncherBased // sbt/Package$ + case "source-dependencies/specialized" => LauncherBased // sbt/Package$ case "tests/test-cross" => LauncherBased // the sbt metabuild classpath leaks into the test interface classloader in older versions of sbt case _ => RunFromSourceBased