Skip to content

Commit 3a6d0c2

Browse files
Merge pull request #8094 from som-snytt/issue/6450
Handle -d /tmp on macos
2 parents c8371e4 + beed79f commit 3a6d0c2

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

compiler/src/dotty/tools/io/AbstractFile.scala

+15-11
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import java.io.{
1010
ByteArrayOutputStream
1111
}
1212
import java.net.URL
13-
import java.nio.file.{Files, Paths}
13+
import java.nio.file.{FileAlreadyExistsException, Files, Paths}
1414

1515
/**
1616
* An abstraction over files for use in the reflection/compiler libraries.
@@ -235,17 +235,21 @@ abstract class AbstractFile extends Iterable[AbstractFile] {
235235
file
236236
}
237237

238-
private def fileOrSubdirectoryNamed(name: String, isDir: Boolean): AbstractFile = {
239-
val lookup = lookupName(name, isDir)
240-
if (lookup != null) lookup
241-
else {
242-
Files.createDirectories(jpath)
243-
val path = jpath.resolve(name)
244-
if (isDir) Files.createDirectory(path)
245-
else Files.createFile(path)
246-
new PlainFile(new File(path))
238+
private def fileOrSubdirectoryNamed(name: String, isDir: Boolean): AbstractFile =
239+
lookupName(name, isDir) match {
240+
case null =>
241+
// the optional exception may be thrown for symlinks, notably /tmp on MacOS.
242+
// isDirectory tests for existing directory. The default behavior is hypothetical isDirectory(jpath, FOLLOW_LINKS).
243+
try Files.createDirectories(jpath)
244+
catch { case _: FileAlreadyExistsException if Files.isDirectory(jpath) => }
245+
246+
// a race condition in creating the entry after the failed lookup may throw
247+
val path = jpath.resolve(name)
248+
if (isDir) Files.createDirectory(path)
249+
else Files.createFile(path)
250+
new PlainFile(new File(path))
251+
case lookup => lookup
247252
}
248-
}
249253

250254
/**
251255
* Get the file in this directory with the given name,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package dotty.tools.io
2+
3+
import org.junit.Test
4+
5+
import dotty.tools.io.AbstractFile
6+
import java.nio.file.Files._
7+
8+
class AbstractFileTest {
9+
//
10+
// Cope with symbolic links. Exercised by -d output.
11+
//
12+
// BytecodeWriters#getFile ensures d.isDirectory for elements in path,
13+
// but d.fileNamed and d.subdirectoryNamed also Files.createDirectories
14+
// for prefixes, which may optionally fail on an existing symbolic link.
15+
//
16+
private def exerciseSymbolicLinks(temp: Directory): Unit = {
17+
val base = {
18+
val target = createTempDirectory(temp.jpath, "real")
19+
val link = temp.jpath.resolve("link")
20+
createSymbolicLink(link, target) // may bail early if unsupported
21+
AbstractFile.getDirectory(link)
22+
}
23+
24+
val file = base.fileNamed("foo")
25+
assert(file.exists && !file.isDirectory)
26+
27+
val dir = base.subdirectoryNamed("bar")
28+
assert(dir.isDirectory)
29+
val leaf = dir.fileNamed("basement")
30+
assert(leaf.exists && !leaf.isDirectory)
31+
32+
val nested = AbstractFile.getDirectory(createSymbolicLink(dir.jpath.resolve("link"), dir.subdirectoryNamed("nested").jpath))
33+
val doubly = nested.fileNamed("doubly")
34+
assert(nested.exists && nested.isDirectory) // /tmp/link/bar/link
35+
assert(doubly.exists && !doubly.isDirectory) // /tmp/link/bar/link/doubly
36+
assert(dir.subdirectoryNamed("link").exists)
37+
}
38+
@Test def t6450(): Unit =
39+
try Directory.inTempDirectory(exerciseSymbolicLinks)
40+
catch { case _: UnsupportedOperationException => () }
41+
}
42+
43+
/* Was:
44+
[error] Test dotty.tools.io.AbstractFileTest.t6450 failed: java.nio.file.FileAlreadyExistsException: /var/folders/2_/xb149z895wb5f1y632xp2bw40000gq/T/temp9110019868196066936/link, took 0.124 sec
45+
[error] at sun.nio.fs.UnixException.translateToIOException(UnixException.java:88)
46+
[error] at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
47+
[error] at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
48+
[error] at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384)
49+
[error] at java.nio.file.Files.createDirectory(Files.java:674)
50+
[error] at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781)
51+
[error] at java.nio.file.Files.createDirectories(Files.java:727)
52+
[error] at dotty.tools.io.AbstractFile.fileOrSubdirectoryNamed(AbstractFile.scala:242)
53+
[error] at dotty.tools.io.AbstractFile.fileNamed(AbstractFile.scala:262)
54+
[error] at dotty.tools.io.AbstractFileTest.exerciseSymbolicLinks(AbstractFileTest.scala:25)
55+
*/

0 commit comments

Comments
 (0)