Shadowfiend / sbt-resource-management

Provides tasks to compile coffee script and compass/SASS files, plus tasks to bundle and upload to S3.
http://hacklanta.com/
MIT License
21 stars 7 forks source link

java.lang.Runtime.exec overwrites environment. #12

Closed farmdawgnation closed 11 years ago

farmdawgnation commented 11 years ago

Around line 184 (in my branch, may vary in master for now) in doSassCompile we have the following code:

val process =
  runtime.exec(
    ("compass" :: "compile" :: "-e" :: "production" :: "--force" :: Nil).toArray,
    ("asset_domain=" + bucket :: Nil).toArray)

This is a grand way to set the asset domain for compass, but it wreaks havoc if you're running this code on a system with RVM installed because, according to the [javadoc](http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String[], java.lang.String[], java.io.File%29), it overwrites the environment that RVM set. The net result is that when compass runs it fails with a path error.

matt@FarmStudy:~/Sites/anchor-tab-scala(master)$ sbt resources:compile-sass
...
[warn]    org.scala-lang: 2.9.2, 2.9.1
[info] Compiling SASS files...
[error] env: ruby_noexec_wrapper: No such file or directory
java.lang.RuntimeException: SASS compilation failed with code 127.

I confirmed this was the issue by changing the second parameter in exec to null, and compass started working again (presumably because it had the correct environment).

It looks like System has a getenv call. One possible fix for this is:

val environment = System.getenv().map { case (key, value) => key + "=" + value }
                  ++ ("asset_domain=" + bucket)
val process =
  runtime.exec(
    ("compass" :: "compile" :: "-e" :: "production" :: "--force" :: Nil).toArray,
    environment

Interested in hearing any thoughts along those lines. Might try implementing it myself.

farmdawgnation commented 11 years ago

What's in your hand? Now back TO ME.... the ISSUE IS NOW A PULL REQUEST.

I kind of hate the manual construction of java.lang.String, but I think it's an evil we have to deal with in this case in order to get a list of the correct type instead of Iterable[Any]. (Yay!) Open to an alternate implementation though.

th0br0 commented 11 years ago

As the string constructor is indeed ... a nasty evil:

import scala.collection.JavaConversions._
val environment = (System.getenv() + ("asset_domain" -> bucket)) map { case (key, value) => key + "=" + value }
val process = runtime.exec(
     ("compass" :: "compile" :: "-e" :: "production" :: "--force" :: Nil).toArray,
    environment.toArray)
farmdawgnation commented 11 years ago

Turns out the JavaConversions aren't required, but I do like your representation of environment better. Pushing a change now.

Shadowfiend commented 11 years ago

I preferred the variable name processEnvironment, but no big. This'll do. Does it work?? As in, have you used it? :D

farmdawgnation commented 11 years ago

Yup, I've been using it on Anchor Tab on my local. Just tested it again and it's working fine.