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

IllegalArgumentException when running "cljsbuild once" #240

Closed
viesti opened this issue Oct 9, 2013 · 10 comments
Closed

IllegalArgumentException when running "cljsbuild once" #240

viesti opened this issue Oct 9, 2013 · 10 comments
Milestone

Comments

@viesti
Copy link
Contributor

viesti commented Oct 9, 2013

We ran into a problem in our build environment:

     [exec] Compiling ClojureScript.
     [exec] java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for
     [exec]  class: nil
     [exec]     at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:541)
     [exec]     at clojure.java.io$fn__8551$G__8546__8558.invoke(io.clj:73)
     [exec]     at clojure.java.io$reader.doInvoke(io.clj:106)
     [exec]     at clojure.lang.RestFn.invoke(RestFn.java:410)
     [exec]     at clojure.lang.AFn.applyToHelper(AFn.java:161)
     [exec]     at clojure.lang.RestFn.applyTo(RestFn.java:132)
     [exec]     at clojure.core$apply.invoke(core.clj:619)
     [exec]     at clojure.core$slurp.doInvoke(core.clj:6278)
     [exec]     at clojure.lang.RestFn.invoke(RestFn.java:410)
     [exec]     at cljsbuild.compiler$reload_clojure.invoke(compiler.clj:108)
     [exec]     at cljsbuild.compiler$run_compiler.invoke(compiler.clj:154)
     [exec]     at user$eval2805$iter__2808__2812$fn__2813.invoke(form-init4410045073015253494.clj:1)
     [exec]     at clojure.lang.LazySeq.sval(LazySeq.java:42)
     [exec]     at clojure.lang.LazySeq.seq(LazySeq.java:60)
     [exec]     at clojure.lang.RT.seq(RT.java:484)
     [exec]     at clojure.core$seq.invoke(core.clj:133)
     [exec]     at clojure.core$dorun.invoke(core.clj:2780)
     [exec]     at clojure.core$doall.invoke(core.clj:2796)
     [exec]     at user$eval2805.invoke(form-init4410045073015253494.clj:1)
     [exec]     at clojure.lang.Compiler.eval(Compiler.java:6619)
     [exec]     at clojure.lang.Compiler.eval(Compiler.java:6609)
     [exec]     at clojure.lang.Compiler.load(Compiler.java:7064)
     [exec]     at clojure.lang.Compiler.loadFile(Compiler.java:7020)
     [exec]     at clojure.main$load_script.invoke(main.clj:294)
     [exec]     at clojure.main$init_opt.invoke(main.clj:299)
     [exec]     at clojure.main$initialize.invoke(main.clj:327)
     [exec]     at clojure.main$null_opt.invoke(main.clj:362)
     [exec]     at clojure.main$main.doInvoke(main.clj:440)
     [exec]     at clojure.lang.RestFn.invoke(RestFn.java:421)
     [exec]     at clojure.lang.Var.invoke(Var.java:419)
     [exec]     at clojure.lang.AFn.applyToHelper(AFn.java:163)
     [exec]     at clojure.lang.Var.applyTo(Var.java:532)
     [exec]     at clojure.main.main(main.java:37)
     [exec] Error encountered performing task 'ring' with profile(s): 'production'
     [exec] Subprocess failed

This is related to the changes in the commit f86627c related to #211. In the form:

:when (-> path (string/replace #"^/" "") io/resource
                    ^String slurp (.contains "defmacro"))]

path seems to be an absolute path (in the above case: "c:\tools\hudson\jobs\xxxxx\workspace\xxxxxx\src\cljs\xxxx\ui\components\tree\macros.clj"), not a resource name on the classpath. io/resource then returns nil and slurp throws an IllegalArgumentException.

Funny thing is that I can't reproduce this on my machine (OSX), the build machine we have is running Windows.

I guess pathshould be a resource name on the classpath, but it would be neat if this would work for absolute file paths as well (being more tolerant would be even neater).

I don't have a patch ready now, but can submit what I had in mind probably tomorrow.

@viesti
Copy link
Contributor Author

viesti commented Oct 9, 2013

Realised that adding stacktrace and some more contex might be neat, so updated the description accordingly.

@viesti
Copy link
Contributor Author

viesti commented Oct 9, 2013

Hmm, passing forward a path defined with absolute pathname (like c:\tools...) seems to cause problems later on:

[exec] Compiling ClojureScript.
[exec] Reloading Clojure file "c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\xxx\ui\components\tree\macros.clj" failed.
[exec] java.io.FileNotFoundException: Could not locate c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\xxx\ui\components\tree\macros__init.class or c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\xxx\ui\components\tree\macros.clj on classpath:
[exec]                  RT.java:443 clojure.lang.RT.load
[exec]                  RT.java:411 clojure.lang.RT.load
[exec]                core.clj:5530 clojure.core/load[fn]
[exec]                core.clj:5529 clojure.core/load
[exec]              RestFn.java:408 clojure.lang.RestFn.invoke
[exec]             compiler.clj:114 cljsbuild.compiler/reload-clojure[fn]
[exec]             compiler.clj:113 cljsbuild.compiler/reload-clojure
[exec]             compiler.clj:157 cljsbuild.compiler/run-compiler
[exec] form-init3163256090223370828.clj:1 user/eval2805[fn]
[exec]              LazySeq.java:42 clojure.lang.LazySeq.sval
[exec]              LazySeq.java:60 clojure.lang.LazySeq.seq
[exec]                  RT.java:484 clojure.lang.RT.seq
[exec]                 core.clj:133 clojure.core/seq
[exec]                core.clj:2780 clojure.core/dorun
[exec]                core.clj:2796 clojure.core/doall
[exec] form-init3163256090223370828.clj:1 user/eval2805
[exec]           Compiler.java:6619 clojure.lang.Compiler.eval
[exec]           Compiler.java:6609 clojure.lang.Compiler.eval
[exec]           Compiler.java:7064 clojure.lang.Compiler.load
[exec]           Compiler.java:7020 clojure.lang.Compiler.loadFile
[exec]                 main.clj:294 clojure.main/load-script
[exec]                 main.clj:299 clojure.main/init-opt
[exec]                 main.clj:327 clojure.main/initialize
[exec]                 main.clj:362 clojure.main/null-opt
[exec]                 main.clj:440 clojure.main/main
[exec]              RestFn.java:421 clojure.lang.RestFn.invoke
[exec]                 Var.java:419 clojure.lang.Var.invoke
[exec]                 AFn.java:163 clojure.lang.AFn.applyToHelper
[exec]                 Var.java:532 clojure.lang.Var.applyTo
[exec]                 main.java:37 clojure.main.main
[exec] Compiling ClojureScript.

So I guess the input should be on classpath, and the above file is actually on classpath, just that the pathname is absolute instead of relative, hmm...

@cemerick
Copy link
Collaborator

cemerick commented Oct 9, 2013

I think the io/resource call is wrong, along with the regex dropping the leading slash. Looking at it right now, (-> path ^String slurp (.contains "defmacro")) seems more right (not tested). Would love a patch, if you're up for making one.

@viesti
Copy link
Contributor Author

viesti commented Oct 9, 2013

True, io/resource seems unnecessary (is ^String unnecessary?, isn't slurp defined to return a string already? might be that I'm not understanding the use of ^String in this context).

Anyway, we still end up into another problem even if we nuke io/resource since something later on assumes the thing to be on the classpath.

@viesti
Copy link
Contributor Author

viesti commented Oct 10, 2013

I'm investigating more, but I'm thinking that since reload-clojure ends up calling load (which "Loads Clojure code from resources in classpath"), we need a path on the classpath. So maybe relativize isn't working in our build environment.

@viesti
Copy link
Contributor Author

viesti commented Oct 10, 2013

Ok so I managed to trace this down case-sensitivity problem:

[exec] relativize parent: 'src/cljs'
[exec] relativize path: 'c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\vision\ui\components\tree\macros.clj'
[exec] absolute parent: 'C:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs'
[exec] absolute path: 'c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\vision\ui\components\tree\macros.clj'
[exec] result: 'c:\tools\hudson\jobs\xxxxx\workspace\xxx-xxx\src\cljs\vision\ui\components\tree\macros.clj'

Notice the capital C in "absolute parent" and lowercase c in "absolute path" (now image my sense of frustration... :)). Could using getCanonicalPath be an acceptable fix:

diff --git a/support/src/cljsbuild/compiler.clj b/support/src/cljsbuild/compiler.clj
index 11aa273..134199d 100644
--- a/support/src/cljsbuild/compiler.clj
+++ b/support/src/cljsbuild/compiler.clj
@@ -84,8 +84,8 @@
       path)))

 (defn- relativize [parent path]
-  (let [path (fs/absolute-path path)
-        parent (fs/absolute-path parent)]
+  (let [path (.getCanonicalPath (fs/file path))
+        parent (.getCanonicalPath (fs/file parent))]
     (if (.startsWith path parent)
       (subs path (count parent))
       path)))

@viesti
Copy link
Contributor Author

viesti commented Oct 10, 2013

The above should probably work on Windows and Unixes since "A canonical pathname is both absolute and unique" (quote from javadocs http://docs.oracle.com/javase/7/docs/api/java/io/File.html#getCanonicalPath() )

@viesti
Copy link
Contributor Author

viesti commented Oct 10, 2013

Tested on Linux and OSX.

@cemerick
Copy link
Collaborator

The ^String hint is needed because slurp doesn't hint its return type (though it probably should).

Ouch, case. FWIW, that relativize fn shouldn't really exist at all, at least in its present form. java.net.URI.relativize() is what really should be used here (with whatever string -> file -> URI -> file -> string round trip is necessary).

Would love a PR of whatever solution you'd like to offer up.

viesti pushed a commit to Ekahau/lein-cljsbuild that referenced this issue Oct 10, 2013
The result of fs/absolute-path might differ in case, result of getCanonicalPath
is defined to "be both absolute and unique" [1]. As noted by Chas,
in emezeske#240, this probably is an
incremental solution only.

[1] http://docs.oracle.com/javase/7/docs/api/java/io/File.html#getCanonicalPath()
@viesti
Copy link
Contributor Author

viesti commented Oct 10, 2013

So did a smaller incremental fix now in #241. Didn't know about java.net.URI.relativize() until now, by using it we could remove custom code (removing code is always good :)), but at least this small incremental step would make me happy :).

cemerick added a commit that referenced this issue Oct 10, 2013
rm-hull added a commit to rm-hull/lein-cljsbuild that referenced this issue Oct 21, 2013
Merge branch 'master' of https://github.com/emezeske/lein-cljsbuild

* 'master' of https://github.com/emezeske/lein-cljsbuild: (45 commits)
  0.3.4
  final 0.3.4 release notes
  auto-discover version of lein-cljsbuild being used, fixes emezeskegh-242
  fail test subtask if any :test-command vector contains non-string values, fixes emezeskegh-243
  0.3.4 release notes draft
  Let hard compilation failures (i.e. failures loading Clojure files) fail the broader build (emezeskegh-234)
  Default :output-wrapper to true when :optimizations = :advanced, fixes emezeskegh-201
  bump cljsbuild-version in subproject => 0.3.4-SNAPSHOT (ref emezeskegh-242)
  orphaned release notes?
  Handle case-sensitivity, fixes emezeske#240
  Add new "sample" task
  update release notes
  0.3.4-SNAPSHOT
  0.3.3
  separate deploy script
  add README admonition re: explicit cljs deps, add explicit dep to example projects, fixes emezeskegh-228
  don't include paths in :output-dir or the :output-to path when watching for changes
  Reimplement `find-files` w/o using the "fs" library (too slow), fixes emezeskegh-219
  emit warning when user's project does not contain an explicit ClojureScript dependency, fixes emezeskegh-224
  0.3.3-SNAPSHOT
  ...

Conflicts:
	doc/RELEASE-NOTES.md
	plugin/project.clj
	plugin/src/leiningen/cljsbuild.clj
	support/project.clj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants