Skip to content
5 changes: 3 additions & 2 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ 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)
ProblemFilter.exclude[ReversedMissingMethodProblem]("os.ProcessLike.joinPumperThreadsHook")
ProblemFilter.exclude[ReversedMissingMethodProblem]("os.ProcessLike.joinPumperThreadsHook"),
ProblemFilter.exclude[MissingTypesProblem]("os.proc$")
Comment thread
lolgab marked this conversation as resolved.
Outdated
)
}

Expand Down
33 changes: 25 additions & 8 deletions os/src/ProcessOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,19 @@ case class proc(command: Shellable*) {
def pipeTo(next: proc): ProcGroup = ProcGroup(Seq(this, next))
}

object proc {

/**
* The env passed by default to child processes
*/
val env = new scala.util.DynamicVariable[Map[String, String]](sys.env)

// TODO: Delete when in binary compatibity breaking window
def andThen[T](f: proc => T): Seq[Shellable] => T = s => f(apply(s))
// TODO: Delete when in binary compatibity breaking window
def compose[T](f: T => Seq[Shellable]): T => proc = t => apply(f(t))
Comment thread
lolgab marked this conversation as resolved.
Outdated
}

/**
* A group of processes that are piped together, corresponding to e.g. `ls -l | grep .scala`.
* You can create a `ProcGroup` by calling `.pipeTo` on a [[proc]] multiple times.
Expand Down Expand Up @@ -485,18 +498,22 @@ private[os] object ProcessOps {
val builder = new java.lang.ProcessBuilder()

val environment = builder.environment()
environment.clear()

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) builder.environment().put(k, v)
else builder.environment().remove(k)
}
}

if (propagateEnv) {
addToProcessEnv(os.proc.env.value)
}

addToProcessEnv(env)

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

builder
Expand Down
16 changes: 16 additions & 0 deletions os/test/src/SubprocessTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ object SubprocessTests extends TestSuite {
}
}
}
test("envWithValue") {
if (Unix()) {
def envValue() = os.proc("bash", "-c", "echo \"$TEST_ENV_FOO\"").call().out.lines().head

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

os.proc.env.withValue(Map("TEST_ENV_FOO" -> "bar")) {
val res = envValue()
assert(res == "bar")
}

val after = envValue()
assert(after == "")
}
}
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