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

require_relative fails for relative paths within jars on Windows #3197

Closed
trejkaz opened this Issue Jul 30, 2015 · 9 comments

Comments

Projects
None yet
5 participants
@trejkaz
Copy link

trejkaz commented Jul 30, 2015

We use gems in a jar to simplify distribution of the gems used for test runs.

When requiring rspec, rspec internally uses require_relative, which then fails. I notice there is a weird mix of the two different slash directions, which probably explains why I'm not seeing the same problem on OSX:

Errno::ENOENT: No such file or directory - C:\hudson\workspace\trunk-functional-tests\os\windows\dependencies\jruby\jruby-testing-gems.jar!\gems\rspec-support-3.3.0\lib\rspec\support.rb
                        realpath at org/jruby/RubyFile.java:805
                require_relative at uri:classloader:/jruby/kernel/kernel.rb:21
                block in Support at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-support-3.3.0/lib/rspec/support.rb:28
                            call at org/jruby/RubyProc.java:308
  block in require_rspec_support at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-support-3.3.0/lib/rspec/support.rb:19
                <module:Support> at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-support-3.3.0/lib/rspec/support.rb:29
                  <module:RSpec> at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-support-3.3.0/lib/rspec/support.rb:2
                           <top> at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-support-3.3.0/lib/rspec/support.rb:1
                         require at org/jruby/RubyKernel.java:940
                          (root) at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1
                           <top> at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:54
                         require at org/jruby/RubyKernel.java:940
                          (root) at c:/hudson/workspace/trunk-functional-tests/os/windows/dependencies/jruby/jruby-testing-gems.jar!/gems/rspec-core-3.3.2/lib/rspec/core.rb:5
                           <top> at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1
                         require at org/jruby/RubyKernel.java:940
                         require at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:54
                           <top> at c:\hudson\workspace\trunk-functional-tests\os\windows/functional-tests/run-rspec.rb:8
@trejkaz

This comment has been minimized.

Copy link
Author

trejkaz commented Aug 4, 2015

Quick workaround for our particular situation is to avoid using paths inside jars, but put the jar on the classpath and then use "uri:classloader:" file paths.

e.g., we had this, which fails:

ENV['GEM_PATH'] = "jar:file:#{File.expand_path('../dependencies/jruby/jruby-testing-gems.jar', File.dirname(__FILE__))}!/"

This was replaced by the following, which works fine:

require File.expand_path('../dependencies/jruby/jruby-testing-gems.jar', File.dirname(__FILE__))
ENV['GEM_PATH'] = "uri:classloader:/"

Or I guess you can just avoid putting gems in jars, but I rather like the ability to do this, because it makes it easier to keep everything together.

@mkristian

This comment has been minimized.

Copy link
Member

mkristian commented Aug 4, 2015

packing gems inside a jar is used quite a lot. and it should even work
without setting ENV['PATH'], i.e. it is implicitly added to the
Gem::Specification.dirs to lookout for gemspecs.

@cyberfox

This comment has been minimized.

Copy link

cyberfox commented Nov 2, 2015

This just bit me, really hard. I'm trying to load active_support inside a gems.jar file, and I'm getting a similar dump. It's like org.jruby.Rubyfile.realpath messes up the path separators, and suddenly it can't read the jar file anymore. 😞

Sadly it just brought my release process to a hard halt for now.

@enebo enebo added this to the JRuby 9.0.4.0 milestone Nov 2, 2015

@mkristian

This comment has been minimized.

Copy link
Member

mkristian commented Nov 3, 2015

this could be already fixed with #3401 which has a fix on jruby-1_7 branch - did not merge to master yet.

@enebo

This comment has been minimized.

Copy link
Member

enebo commented Nov 12, 2015

I did the test where I put actionpack (and a lot of other gems into a jar file). I picked actionpack since the version.rb file uses a relative_require. With a very recent fix from @mkristian (a5dd1b7) in addition to #3401 fixed I think all issues mentioned here.

@griest024

This comment has been minimized.

Copy link

griest024 commented Aug 21, 2016

I think this needs to be reopened.

I have a hello world program that I pack into a jar with warbler.

$ warble
rm -f jruby-require.jar
Creating jruby-require.jar

Running it throws an exception:

$ java -jar jruby-require.jar
LoadError: no such file to load -- uri:classloader:/jruby-require/hello
           require at org/jruby/RubyKernel.java:944
           require at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:55
  require_relative at uri:classloader:/jruby/kernel/kernel.rb:13
             <top> at uri:classloader:/jruby-require/main.rb:2
              load at org/jruby/RubyKernel.java:962
             <top> at uri:classloader:/META-INF/main.rb:1
           require at org/jruby/RubyKernel.java:944
            (root) at uri:classloader:/META-INF/main.rb:1
             <top> at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1
ERROR: org.jruby.embed.EvalFailedException: (LoadError) no such file to load -- uri:classloader:/jruby-require/hello

File structure of jar:

$ jar tf jruby-require.jar
JarMain.class
META-INF/
META-INF/MANIFEST.MF
META-INF/init.rb
META-INF/lib/
META-INF/lib/jruby-core-9.1.2.0-complete.jar
META-INF/lib/jruby-stdlib-9.1.2.0.jar
META-INF/main.rb
jruby-require/
jruby-require/lib/
jruby-require/lib/lib.rb
jruby-require/main.rb

Using require works fine.

@mkristian

This comment has been minimized.

Copy link
Member

mkristian commented Aug 21, 2016

@griest024 but I do not see a hello.rb file in your jar. also require_relative 'hello' from jruby-require/main.rb I expect ruby to look for jruby-require/hello.rb which jruby does with uri:classloader:/jruby-require/hello

and I do not know how warbler executes main.rb as it seems to twice inside the jar. if warbler executes META-INF/main.rb then this is not finding any hello.rb as well.

if you jruby-require/lib/lib.rb is the hello.rb and jruby-require/lib is on the $LOAD_PATH then require works.

@griest024

This comment has been minimized.

Copy link

griest024 commented Aug 21, 2016

@mkristian sorry I refactored some stuff to make it clearer. Here are the correct contents of the jar

$ jar tf jruby-require.jar
JarMain.class
META-INF/
META-INF/MANIFEST.MF
META-INF/init.rb
META-INF/lib/
META-INF/lib/jruby-core-9.1.2.0-complete.jar
META-INF/lib/jruby-stdlib-9.1.2.0.jar
META-INF/main.rb
jruby-require/
jruby-require/Rakefile
jruby-require/lib/
jruby-require/lib/hello.rb
jruby-require/main.rb

Also File.expand_path __FILE__ in main.rb returns uri:classloader:/jruby-require/main.rb.

require does work, as warbler will add specified directories to the load path. My problem is that a bunch of code already relies on require_relative calls.

@mkristian

This comment has been minimized.

Copy link
Member

mkristian commented Aug 21, 2016

@griest024 the thing here is that main.rb can not see hello.rb even if you would unpack the jar and add jruby-require/lib/ to your LOAD_PATH. not that I am saying File.expand_path is working correctly everywhere but in you example it does the right thing as well the require_relative'. especially on windowsFile.expand_path` with all those uri-like paths is not part of the test-suite: https://github.com/jruby/jruby/blob/master/test/jruby/test_file.rb#L273 as they produced too many errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.