Skip to content

Commit 8e13c5d

Browse files
authored
Merge pull request #1571 from eed3si9n/wip/directory-support
[2.x] fix: Directory support
2 parents 04d05ca + 886c716 commit 8e13c5d

File tree

2 files changed

+65
-5
lines changed

2 files changed

+65
-5
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ ThisBuild / version := {
4646
nightlyVersion match {
4747
case Some(v) => v
4848
case _ =>
49-
if ((ThisBuild / isSnapshot).value) "2.0.0-M3-SNAPSHOT"
49+
if ((ThisBuild / isSnapshot).value) "2.0.0-M6-SNAPSHOT"
5050
else old
5151
}
5252
}

internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ package sbt
1313
package internal
1414
package inc
1515

16-
import java.io.InputStream
16+
import java.io.{ ByteArrayInputStream, InputStream }
17+
import java.nio.ByteBuffer
1718
import java.nio.file.{ Files, Path, Paths }
1819
import xsbti.{ BasicVirtualFileRef, FileConverter, PathBasedFile, VirtualFile, VirtualFileRef }
20+
import sbt.nio.file.{ FileTreeView, Glob, IsNotHidden, IsRegularFile, RecursiveGlob }
1921

2022
class MappedVirtualFile(encodedPath: String, rootPathsMap: Map[String, Path])
2123
extends BasicVirtualFileRef(encodedPath)
@@ -40,8 +42,47 @@ object MappedVirtualFile {
4042
}
4143
}
4244

45+
class MappedDirectory(
46+
encodedPath: String,
47+
rootPathsMap: Map[String, Path],
48+
items: List[VirtualFile]
49+
) extends BasicVirtualFileRef(encodedPath)
50+
with PathBasedFile {
51+
private def path: Path = MappedVirtualFile.toPath(encodedPath, rootPathsMap)
52+
override lazy val contentHash: Long = {
53+
val buffer = ByteBuffer.allocate(java.lang.Long.BYTES * items.size)
54+
val hashes = items.foreach { item =>
55+
buffer.putLong(item.contentHash)
56+
}
57+
HashUtil.farmHash(buffer.array())
58+
}
59+
override lazy val sizeBytes: Long = items.map(_.sizeBytes).sum
60+
override lazy val contentHashStr: String = {
61+
val sb = new StringBuilder
62+
val hashes = items.foreach { item =>
63+
sb.append(item.contentHashStr)
64+
}
65+
val stream = new ByteArrayInputStream(hashes.toString.getBytes("UTF-8"))
66+
HashUtil.sha256HashStr(stream)
67+
}
68+
override def input(): InputStream = ???
69+
override def toPath: Path = path
70+
}
71+
72+
object MappedDirectory {
73+
def apply(
74+
encodedPath: String,
75+
rootPaths: Map[String, Path],
76+
items: List[VirtualFile]
77+
): MappedDirectory =
78+
new MappedDirectory(encodedPath, rootPaths, items)
79+
}
80+
4381
class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolean)
4482
extends FileConverter {
83+
84+
import MappedFileConverter.view
85+
4586
val rootPaths2: Seq[(String, Path)] = rootPaths.toSeq.flatMap {
4687
case (key, rootPath) =>
4788
if (rootPath.startsWith("/var/") || rootPath.startsWith("/tmp/")) {
@@ -56,9 +97,15 @@ class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolea
5697
}
5798

5899
def toVirtualFile(path: Path): VirtualFile = {
100+
def isDirectory: Boolean =
101+
Files.isDirectory(path) || (!Files.exists(path) && path.getFileName.toString().endsWith(
102+
"classes"
103+
))
59104
rootPaths2.find { case (_, rootPath) => path.startsWith(rootPath) } match {
60105
case Some((key, rootPath)) =>
61-
MappedVirtualFile(s"$${$key}/${rootPath.relativize(path)}".replace('\\', '/'), rootPaths)
106+
val encodedPath = s"$${$key}/${rootPath.relativize(path)}".replace('\\', '/')
107+
if (isDirectory) toDirectory(path, encodedPath)
108+
else MappedVirtualFile(encodedPath, rootPaths)
62109
case _ =>
63110
def isCtSym =
64111
path.getFileSystem
@@ -67,13 +114,26 @@ class MappedFileConverter(rootPaths: Map[String, Path], allowMachinePath: Boolea
67114
def isJrt = path.getFileSystem.provider().getScheme == "jrt"
68115
if (isJrt || path.getFileName.toString == "rt.jar" || isCtSym)
69116
DummyVirtualFile("rt.jar", path)
70-
else if (allowMachinePath) MappedVirtualFile(s"$path".replace('\\', '/'), rootPaths)
71-
else sys.error(s"$path cannot be mapped using the root paths $rootPaths")
117+
else if (allowMachinePath) {
118+
val encodedPath = s"$path".replace('\\', '/')
119+
if (isDirectory) toDirectory(path, encodedPath)
120+
else MappedVirtualFile(encodedPath, rootPaths)
121+
} else sys.error(s"$path cannot be mapped using the root paths $rootPaths")
72122
}
73123
}
124+
125+
def toDirectory(path: Path, encodedPath: String) = {
126+
val list = view.list(Glob(path, RecursiveGlob), IsRegularFile && IsNotHidden)
127+
.map(_._1)
128+
.sortBy(x => x.toUri().toString())
129+
val items = list.map(toVirtualFile)
130+
MappedDirectory(encodedPath, rootPaths, items.toList)
131+
}
74132
}
75133

76134
object MappedFileConverter {
135+
private[sbt] lazy val view = FileTreeView.Ops(FileTreeView.default)
136+
77137
def empty: MappedFileConverter = new MappedFileConverter(Map(), true)
78138
def apply(rootPaths: Map[String, Path], allowMachinePath: Boolean): MappedFileConverter =
79139
new MappedFileConverter(rootPaths, allowMachinePath)

0 commit comments

Comments
 (0)