mirror of https://github.com/sbt/sbt.git
Ensure random file hash for .sbt DSL doesn't conflict across .sbt files.
Fixes #1465
This commit is contained in:
parent
12b6bd148d
commit
0bfb5a4118
|
|
@ -91,12 +91,13 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se
|
|||
def extra(run: Run, unit: CompilationUnit) = atPhase(run.typerPhase.next) { (new TypeExtractor).getType(unit.body) }
|
||||
def read(file: File) = IO.read(file)
|
||||
def write(value: String, f: File) = IO.write(f, value)
|
||||
def extraHash = ""
|
||||
}
|
||||
val i = evalCommon(expression :: Nil, imports, tpeName, ev)
|
||||
val value = (cl: ClassLoader) => getValue[Any](i.enclosingModule, i.loader(cl))
|
||||
new EvalResult(i.extra, value, i.generated, i.enclosingModule)
|
||||
}
|
||||
def evalDefinitions(definitions: Seq[(String, scala.Range)], imports: EvalImports, srcName: String, valTypes: Seq[String]): EvalDefinitions =
|
||||
def evalDefinitions(definitions: Seq[(String, scala.Range)], imports: EvalImports, srcName: String, file: Option[File], valTypes: Seq[String]): EvalDefinitions =
|
||||
{
|
||||
require(definitions.nonEmpty, "Definitions to evaluate cannot be empty.")
|
||||
val ev = new EvalType[Seq[String]] {
|
||||
|
|
@ -113,6 +114,10 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se
|
|||
}
|
||||
def read(file: File) = IO.readLines(file)
|
||||
def write(value: Seq[String], file: File) = IO.writeLines(file, value)
|
||||
def extraHash = file match {
|
||||
case Some(f) => f.getAbsolutePath
|
||||
case None => ""
|
||||
}
|
||||
}
|
||||
val i = evalCommon(definitions.map(_._1), imports, Some(""), ev)
|
||||
new EvalDefinitions(i.loader, i.generated, i.enclosingModule, i.extra)
|
||||
|
|
@ -121,8 +126,12 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se
|
|||
private[this] def evalCommon[T](content: Seq[String], imports: EvalImports, tpeName: Option[String], ev: EvalType[T]): EvalIntermediate[T] =
|
||||
{
|
||||
import Eval._
|
||||
// TODO - We also encode the source of the setting into the hash to avoid conflicts where the exact SAME setting
|
||||
// is defined in multiple evaluated instances with a backing. This leads to issues with finding a previous
|
||||
// value on the classpath when compiling.
|
||||
val hash = Hash.toHex(Hash(bytes(stringSeqBytes(content) :: optBytes(backing)(fileExistsBytes) :: stringSeqBytes(options) ::
|
||||
seqBytes(classpath)(fileModifiedBytes) :: stringSeqBytes(imports.strings.map(_._1)) :: optBytes(tpeName)(bytes) :: Nil)))
|
||||
seqBytes(classpath)(fileModifiedBytes) :: stringSeqBytes(imports.strings.map(_._1)) :: optBytes(tpeName)(bytes) ::
|
||||
bytes(ev.extraHash) :: Nil)))
|
||||
val moduleName = makeModuleName(hash)
|
||||
|
||||
lazy val unit = {
|
||||
|
|
@ -354,6 +363,9 @@ final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Se
|
|||
* The Tree doesn't need to be parsed from the contents of `unit`.
|
||||
*/
|
||||
def unitBody(unit: CompilationUnit, importTrees: Seq[Tree], moduleName: String): Tree
|
||||
|
||||
/** Extra information to include in the hash'd object name to help avoid collisions. */
|
||||
def extraHash: String
|
||||
}
|
||||
|
||||
val DefaultStartLine = 0
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ object EvaluateConfigurations {
|
|||
val parsed = parseConfiguration(lines, imports, offset)
|
||||
val (importDefs, definitions) =
|
||||
if (parsed.definitions.isEmpty) (Nil, DefinedSbtValues.empty) else {
|
||||
val definitions = evaluateDefinitions(eval, name, parsed.imports, parsed.definitions)
|
||||
val definitions = evaluateDefinitions(eval, name, parsed.imports, parsed.definitions, Some(file))
|
||||
val imp = BuildUtil.importAllRoot(definitions.enclosingModule :: Nil)
|
||||
val projs = (loader: ClassLoader) => definitions.values(loader).map(p => resolveBase(file.getParentFile, p.asInstanceOf[Project]))
|
||||
(imp, DefinedSbtValues(definitions))
|
||||
|
|
@ -237,10 +237,10 @@ object EvaluateConfigurations {
|
|||
}
|
||||
private[this] def extractedValTypes: Seq[String] =
|
||||
Seq(classOf[Project], classOf[InputKey[_]], classOf[TaskKey[_]], classOf[SettingKey[_]]).map(_.getName)
|
||||
private[this] def evaluateDefinitions(eval: Eval, name: String, imports: Seq[(String, Int)], definitions: Seq[(String, LineRange)]): compiler.EvalDefinitions =
|
||||
private[this] def evaluateDefinitions(eval: Eval, name: String, imports: Seq[(String, Int)], definitions: Seq[(String, LineRange)], file: Option[File]): compiler.EvalDefinitions =
|
||||
{
|
||||
val convertedRanges = definitions.map { case (s, r) => (s, r.start to r.end) }
|
||||
eval.evalDefinitions(convertedRanges, new EvalImports(imports, name), name, extractedValTypes)
|
||||
eval.evalDefinitions(convertedRanges, new EvalImports(imports, name), name, file, extractedValTypes)
|
||||
}
|
||||
}
|
||||
object Index {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
val commonP = LocalProject("common")
|
||||
|
||||
name := "boink"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
lazy val common = project
|
||||
|
||||
lazy val boink = project
|
||||
|
||||
lazy val woof = project
|
||||
|
|
@ -0,0 +1 @@
|
|||
> compile
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
val commonP = LocalProject("common")
|
||||
|
||||
name := "woof"
|
||||
Loading…
Reference in New Issue