mirror of https://github.com/sbt/sbt.git
fix: Fix root project detection
**Problem** Whether a subproject is root or not is currently detected by comparing getCanonicalFile against the build base directory. Problem is that often the root project uses "." as the directory, and getting the canonical file works ok for the current build, but it breaks when loading `ProjectRef`. There might be other bugs related to the root project detection. **Solution** This factors out `isRootPath` function that's aware of the build base. This PR adds the repro test prepared by xuwei-k.
This commit is contained in:
parent
bc69030e58
commit
ac4ba55e9e
|
|
@ -596,7 +596,7 @@ private[sbt] object Load {
|
|||
|
||||
// since base directories are resolved at this point (after 'projects'),
|
||||
// we can compare Files instead of converting to URIs
|
||||
def isRoot(p: Project) = p.base.getCanonicalFile() == unit.localBase.getCanonicalFile()
|
||||
def isRoot(p: Project) = isRootPath(p.base, unit.localBase)
|
||||
|
||||
val externals = referenced(defined).toList
|
||||
val explicitRoots = unit.definitions.builds.flatMap(_.rootProject)
|
||||
|
|
@ -688,6 +688,13 @@ private[sbt] object Load {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when value is the subproject base for root project.
|
||||
* Note that it's often specified as file(".").
|
||||
*/
|
||||
def isRootPath(value: File, projectBase: File): Boolean =
|
||||
projectBase.getCanonicalFile() == IO.resolve(projectBase, value).getCanonicalFile()
|
||||
|
||||
def resolveBase(against: File): Project => Project = {
|
||||
def resolve(f: File) = {
|
||||
val fResolved = new File(IO.directoryURI(IO.resolve(against, f)))
|
||||
|
|
@ -821,11 +828,10 @@ private[sbt] object Load {
|
|||
// TODO - As of sbt 0.13.6 we should always have a default root project from
|
||||
// here on, so the autogenerated build aggregated can be removed from this code. ( I think)
|
||||
// We may actually want to move it back here and have different flags in loadTransitive...
|
||||
val hasRoot = loadedProjectsRaw.projects.exists(
|
||||
_.base.getCanonicalFile() == normBase.getCanonicalFile()
|
||||
) || defsScala.exists(
|
||||
_.rootProject.isDefined
|
||||
)
|
||||
val hasRoot =
|
||||
loadedProjectsRaw.projects.exists(p => isRootPath(p.base, normBase)) || defsScala.exists(
|
||||
_.rootProject.isDefined
|
||||
)
|
||||
val (loadedProjects, defaultBuildIfNone, keepClassFiles) =
|
||||
if (hasRoot)
|
||||
(
|
||||
|
|
@ -992,12 +998,11 @@ private[sbt] object Load {
|
|||
// load all relevant configuration files (.sbt, as .scala already exists at this point)
|
||||
def discover(base: File): DiscoveredProjects = {
|
||||
val auto =
|
||||
if (base.getCanonicalFile() == buildBase.getCanonicalFile()) AddSettings.allDefaults
|
||||
if isRootPath(base, buildBase) then AddSettings.allDefaults
|
||||
else AddSettings.defaultSbtFiles
|
||||
|
||||
val extraFiles =
|
||||
if base.getCanonicalFile() == buildBase.getCanonicalFile() && isMetaBuildContext(context)
|
||||
then extraSbtFiles
|
||||
if isRootPath(base, buildBase) && isMetaBuildContext(context) then extraSbtFiles
|
||||
else Nil
|
||||
discoverProjects(auto, base, extraFiles, plugins, eval, memoSettings, converter)
|
||||
}
|
||||
|
|
@ -1311,8 +1316,7 @@ private[sbt] object Load {
|
|||
val rawFiles = associatedFiles(auto)
|
||||
val loadedFiles = loadFiles(rawFiles)
|
||||
val rawProjects = loadedFiles.projects
|
||||
val (root, nonRoot) =
|
||||
rawProjects.partition(_.base.getCanonicalFile() == projectBase.getCanonicalFile())
|
||||
val (root, nonRoot) = rawProjects.partition(p => isRootPath(p.base, projectBase))
|
||||
// TODO - good error message if more than one root project
|
||||
DiscoveredProjects(
|
||||
root.headOption,
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
val a1 = (project in file("."))
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// https://github.com/sbt/sbt/issues/7738
|
||||
val root = (project in file("."))
|
||||
.dependsOn(ProjectRef(file("a1"), "a1"))
|
||||
|
|
@ -0,0 +1 @@
|
|||
> projects
|
||||
Loading…
Reference in New Issue