Skip to content

Commit 5dc0aa5

Browse files
authored
Make os.pwd modifiable via the os.pwd0 dynamic variable (#298)
Basically the same thing we did in #295 and #283, except rather than being `os.SubProcess`-specific this applies to all usage of `os.pwd`. And with similar limitations: this works for code paths that go through OS-Lib, but not for code that uses `java.io` or `java.nio` directly. AFAIK this is the last of the "global" things we need to redirect in Mill tasks, after env variables and default subprocess streams. I'd like it to go into Mill 0.12.0 together with the other sandboxing-related changes Added unit tests and updated the documentation Pull Request: #298
1 parent 29266d7 commit 5dc0aa5

File tree

5 files changed

+37
-4
lines changed

5 files changed

+37
-4
lines changed

Readme.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,8 +1828,8 @@ wd / os.up
18281828
wd / os.up / os.up
18291829
----
18301830

1831-
Note that there are no in-built operations to change the `os.pwd`. In general,
1832-
you should not need to: simply defining a new path, e.g.
1831+
`os.pwd` can be modified in certain scopes via the `os.dynamicPwd` dynamic variable, but
1832+
best practice is not to change it. Instead simply define a new path, e.g.
18331833

18341834
[source,scala]
18351835
----

os/src-jvm/package.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import scala.language.implicitConversions
22
import java.nio.file.FileSystem
33
import java.nio.file.FileSystems
44
import java.nio.file.Paths
5+
import scala.util.DynamicVariable
56

67
package object os {
78
type Generator[+T] = geny.Generator[T]
@@ -38,7 +39,9 @@ package object os {
3839
/**
3940
* The current working directory for this process.
4041
*/
41-
val pwd: Path = os.Path(java.nio.file.Paths.get(".").toAbsolutePath)
42+
def pwd: Path = dynamicPwd.value
43+
val dynamicPwd: DynamicVariable[Path] =
44+
new DynamicVariable(os.Path(java.nio.file.Paths.get(".").toAbsolutePath))
4245

4346
val up: RelPath = RelPath.up
4447

os/src-native/package.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import java.nio.file.FileSystem
22
import java.nio.file.FileSystems
3+
import scala.util.DynamicVariable
34
package object os {
45
type Generator[+T] = geny.Generator[T]
56
val Generator = geny.Generator
@@ -31,7 +32,9 @@ package object os {
3132
/**
3233
* The current working directory for this process.
3334
*/
34-
val pwd: Path = os.Path(java.nio.file.Paths.get(".").toAbsolutePath)
35+
def pwd: Path = dynamicPwd.value
36+
val dynamicPwd: DynamicVariable[Path] =
37+
new DynamicVariable(os.Path(java.nio.file.Paths.get(".").toAbsolutePath))
3538

3639
val up: RelPath = RelPath.up
3740

os/test/src/PathTests.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,14 @@ object PathTests extends TestSuite {
434434
System.err.printf("p[%s]\n", posix(p))
435435
assert(posix(p) contains "/omg")
436436
}
437+
test("dynamicPwd") {
438+
val x = os.pwd
439+
val y = os.dynamicPwd.withValue(os.pwd / "hello") {
440+
os.pwd
441+
}
442+
443+
assert(x / "hello" == y)
444+
}
437445
}
438446
// compare absolute paths
439447
def sameFile(a: java.nio.file.Path, b: java.nio.file.Path): Boolean = {

os/test/src/SubprocessTests.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,5 +225,24 @@ object SubprocessTests extends TestSuite {
225225
assert(output.out.lines() == Seq("HELLO /usr"))
226226
}
227227
}
228+
test("dynamicPwd") {
229+
// Windows doesnt have bash installed so a bit inconvenient
230+
// to run these subprocesses for testing
231+
if (!scala.util.Properties.isWin) {
232+
val outsidePwd = os.pwd
233+
val tmp0 = os.temp.dir()
234+
val tmp = os.followLink(tmp0).getOrElse(tmp0)
235+
val x = proc("bash", "-c", "pwd").call()
236+
val y = os.dynamicPwd.withValue(tmp) {
237+
proc("bash", "-c", "pwd").call()
238+
}
239+
240+
val z = proc("bash", "-c", "pwd").call()
241+
assert(outsidePwd.toString != tmp.toString)
242+
assert(x.out.trim() == outsidePwd.toString)
243+
assert(y.out.trim() == tmp.toString)
244+
assert(z.out.trim() == outsidePwd.toString)
245+
}
246+
}
228247
}
229248
}

0 commit comments

Comments
 (0)