Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce os.SubProcess.env DynamicVariable to override default env #295

Merged
merged 10 commits into from
Aug 30, 2024
3 changes: 2 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ trait SafeDeps extends ScalaModule {
}

trait MiMaChecks extends Mima {
def mimaPreviousVersions = Seq("0.9.0", "0.9.1", "0.9.2", "0.9.3", "0.10.0")
def mimaPreviousVersions =
Seq("0.9.0", "0.9.1", "0.9.2", "0.9.3", "0.10.0", "0.10.1", "0.10.2", "0.10.3", "0.10.4")
override def mimaBinaryIssueFilters: T[Seq[ProblemFilter]] = Seq(
ProblemFilter.exclude[ReversedMissingMethodProblem]("os.PathConvertible.isCustomFs"),
// this is fine, because ProcessLike is sealed (and its subclasses should be final)
Expand Down
27 changes: 19 additions & 8 deletions os/src/ProcessOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -486,17 +486,28 @@ private[os] object ProcessOps {

val environment = builder.environment()

if (!propagateEnv) {
environment.clear()
}

if (env != null) {
for ((k, v) <- env) {
if (v != null) builder.environment().put(k, v)
else builder.environment().remove(k)
def addToProcessEnv(env: Map[String, String]) =
if (env != null) {
for ((k, v) <- env) {
if (v != null) environment.put(k, v)
else environment.remove(k)
}
}

os.SubProcess.env.value match {
case null =>
if (!propagateEnv) {
environment.clear()
}
case subProcessEnvValue =>
environment.clear()
if (propagateEnv) {
addToProcessEnv(subProcessEnvValue)
}
}

addToProcessEnv(env)

builder.directory(Option(cwd).getOrElse(os.pwd).toIO)

builder
Expand Down
6 changes: 6 additions & 0 deletions os/src/SubProcess.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ class SubProcess(

object SubProcess {

/**
* The env passed by default to child processes.
* When `null`, the system environment is used.
*/
val env = new scala.util.DynamicVariable[Map[String, String]](null)

/**
* A [[BufferedWriter]] with the underlying [[java.io.OutputStream]] exposed
*
Expand Down
22 changes: 22 additions & 0 deletions os/test/src/SubprocessTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,28 @@ object SubprocessTests extends TestSuite {
}
}
}
test("envWithValue") {
if (Unix()) {
val variableName = "TEST_ENV_FOO"
val variableValue = "bar"
def envValue() = os.proc(
"bash",
"-c",
s"""if [ -z $${$variableName+x} ]; then echo "unset"; else echo "$$$variableName"; fi"""
).call().out.lines().head

val before = envValue()
assert(before == "unset")

os.SubProcess.env.withValue(Map(variableName -> variableValue)) {
val res = envValue()
assert(res == variableValue)
}

val after = envValue()
assert(after == "unset")
}
}
test("multiChunk") {
// Make sure that in the case where multiple chunks are being read from
// the subprocess in quick succession, we ensure that the output handler
Expand Down