mirror of https://github.com/sbt/sbt.git
Better auto project ID handling. Ref #776.
* Consolidate project ID validation and normalization into Project methods * Provide an earlier and more detailed error message when the directory name can't be used for the project ID
This commit is contained in:
parent
6f0028e50d
commit
ce1c8b0ebc
|
|
@ -5,6 +5,7 @@ package sbt
|
|||
|
||||
object StringUtilities
|
||||
{
|
||||
@deprecated("Different use cases require different normalization. Use Project.normalizeModuleID or normalizeProjectID instead.", "0.13.0")
|
||||
def normalize(s: String) = s.toLowerCase.replaceAll("""\W+""", "-")
|
||||
def nonEmpty(s: String, label: String)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -923,7 +923,7 @@ object Classpaths
|
|||
conflictWarning in GlobalScope :== ConflictWarning.default("global"),
|
||||
conflictWarning := conflictWarning.value.copy(label = Reference.display(thisProjectRef.value)),
|
||||
unmanagedBase := baseDirectory.value / "lib",
|
||||
normalizedName := StringUtilities.normalize(name.value),
|
||||
normalizedName := Project.normalizeModuleID(name.value),
|
||||
isSnapshot <<= isSnapshot or version(_ endsWith "-SNAPSHOT"),
|
||||
description <<= description or name,
|
||||
homepage in GlobalScope :== None,
|
||||
|
|
|
|||
|
|
@ -435,17 +435,26 @@ object Load
|
|||
val loadedDefs = new sbt.LoadedDefinitions(defDir, Nil, plugs.loader, defs, loadedProjects, defNames)
|
||||
new sbt.BuildUnit(uri, normBase, loadedDefs, plugs)
|
||||
}
|
||||
|
||||
private[this] def autoID(localBase: File, context: PluginManagement.Context, existingIDs: Seq[String]): String =
|
||||
{
|
||||
import StringUtilities.{normalize => norm}
|
||||
def normalizeID(f: File) = Project.normalizeProjectID(f.getName) match {
|
||||
case Right(id) => id
|
||||
case Left(msg) => error(autoIDError(f, msg))
|
||||
}
|
||||
def nthParentName(f: File, i: Int): String =
|
||||
if(f eq null) Build.defaultID(localBase) else if(i <= 0) norm(f.getName) else nthParentName(f.getParentFile, i - 1)
|
||||
if(f eq null) Build.defaultID(localBase) else if(i <= 0) normalizeID(f) else nthParentName(f.getParentFile, i - 1)
|
||||
val pluginDepth = context.pluginProjectDepth
|
||||
val postfix = "-build" * pluginDepth
|
||||
val idBase = if(context.globalPluginProject) "global-plugins" else nthParentName(localBase, pluginDepth)
|
||||
val tryID = idBase + postfix
|
||||
if(existingIDs.contains(tryID)) Build.defaultID(localBase) else tryID
|
||||
}
|
||||
|
||||
private[this] def autoIDError(base: File, reason: String): String =
|
||||
"Could not derive root project ID from directory " + base.getAbsolutePath + ":\n" +
|
||||
reason + "\nRename the directory or explicitly define a root project."
|
||||
|
||||
private[this] def projectsFromBuild(b: Build, base: File): Seq[Project] =
|
||||
b.projectDefinitions(base).map(resolveBase(base))
|
||||
|
||||
|
|
|
|||
|
|
@ -157,10 +157,26 @@ object Project extends ProjectExtra
|
|||
delegates: => Seq[ProjectReference] = Nil, settings: => Seq[Def.Setting[_]] = defaultSettings, configurations: Seq[Configuration] = Configurations.default,
|
||||
auto: AddSettings = AddSettings.allDefaults): Project =
|
||||
{
|
||||
DefaultParsers.parse(id, DefaultParsers.ID).left.foreach(errMsg => sys.error("Invalid project ID: " + errMsg))
|
||||
validProjectID(id).foreach(errMsg => sys.error("Invalid project ID: " + errMsg))
|
||||
new ProjectDef[ProjectReference](id, base, aggregate, dependencies, delegates, settings, configurations, auto) with Project
|
||||
}
|
||||
|
||||
/** Returns None if `id` is a valid Project ID or Some containing the parser error message if it is not.*/
|
||||
def validProjectID(id: String): Option[String] = DefaultParsers.parse(id, DefaultParsers.ID).left.toOption
|
||||
|
||||
|
||||
/** Constructs a valid Project ID based on `id` and returns it in Right or returns the error message in Left if one cannot be constructed.*/
|
||||
def normalizeProjectID(id: String): Either[String, String] =
|
||||
{
|
||||
// TODO: better attempt
|
||||
val attempt = id.toLowerCase.replaceAll("""\W+""", "-")
|
||||
validProjectID(attempt).toLeft(attempt)
|
||||
}
|
||||
|
||||
/** Normalize a String so that it is suitable for use as a dependency management module identifier.
|
||||
* This is a best effort implementation, since valid characters are not documented or consistent.*/
|
||||
def normalizeModuleID(id: String): String = id.toLowerCase.replaceAll("""\W+""", "-")
|
||||
|
||||
def resolved(id: String, base: File, aggregate: => Seq[ProjectRef], dependencies: => Seq[ResolvedClasspathDependency], delegates: => Seq[ProjectRef],
|
||||
settings: Seq[Def.Setting[_]], configurations: Seq[Configuration], auto: AddSettings): ResolvedProject =
|
||||
new ProjectDef[ProjectRef](id, base, aggregate, dependencies, delegates, settings, configurations, auto) with ResolvedProject
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ project/ directory.
|
|||
val pom = pomFile(info)
|
||||
val model = readPom(pom)
|
||||
|
||||
val n = StringUtilities.normalize(model.getName)
|
||||
val n = Project.normalizeProjectID(model.getName)
|
||||
val base = Option(model.getProjectDirectory) getOrElse info.base
|
||||
val root = Project(n, base) settings( pomSettings(model) : _*)
|
||||
val build = new Build { override def projects = Seq(root) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue