diff --git a/CHANGELOG.md b/CHANGELOG.md index e51ecd3e9..ff9f2f81d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,18 +4,27 @@ - Refactor logging for more sane defaults - Remove long-deprecated configuration and API functionality -For most users this should be a minor upgrade; as long as not depending on deprecated functionality or JRuby 9.x. +For most users this should be a minor upgrade; as long as you do not depend on functionality deprecated within +JRuby-Rack 1.2.x, EOL JRuby or EOL Rails versions. Breaking compatibility changes - Drop support for JRuby 9.x (and thus Java < 21) - Drop support for Rails < 7.2 +- Drop JMS support Breaking behavioral changes - Change context listener to throw by default in case of an exception during initialization - Change rails context listener to assume a thread-safe application by default +- Rack is no longer vendored inside the jar, so applications must ensure rack is provided via bundler or GEM_PATH -Breaking Java API changes -- Drop JMS support +Breaking configuration capability changes +- Drop `jruby.rack.jruby.version` and `jruby.rack.rack.release` keys from rack `env` Hash +- Drop deprecated and undocumented jruby-rack 1.0 backwards compat properties `jruby.runtime.timeout.sec`, `jruby.runtime.initializer.threads`, `jruby.init.serial`, `jruby.rack.request.size.threshold.bytes` +- Drop deprecated `jruby.rack.ignore.env` property, replaced long ago by `jruby.runtime.env` and optional `jruby.runtime.env.rubyopt` +- Drop deprecated `jruby.rack.filter.*` properties, replaced long ago by init parameters `addsHtmlToPathInfo` and `verifiesHtmlResource` +- Drop handling of `# rack.version` magic comments inside `config.ru` files, replaced by bundler or user-managed `GEM_PATH` + +Breaking Java API changes (only relevant for users extending the Java API) - Drop unnecessary `jruby.compat.version` and `RackConfig.getCompatVersion()` API - Drop deprecated `org.jruby.rack.RackInput` alias for `org.jruby.rack.ext.Input` class - Drop/rename deprecated `RackConfig` and `ServletRackEnvironment` API methods per their earlier comments @@ -23,18 +32,12 @@ Breaking Java API changes - Custom `RackLogger` implementations must accept `CharSequence` rather than `String` to allow `RubyString` passthrough - Rename deprecated `JRuby::Rack::ServletLog` to `JRuby::Rack::ErrorLog` for clarity, despite usage only in servlet contexts. -Breaking Ruby API changes +Breaking Ruby API changes (only relevant for users extending the Ruby API) - Drop deprecated `JRuby::Rack::RailsFileSystemLayout` alias for `JRuby::Rack::FileSystemLayout` - Drop deprecated `JRuby::Rack::Errors` alias for `JRuby::Rack::ErrorApp` - Drop deprecated `Rack::Handler::Servlet::Env` and `Rack::Handler::Servlet::LazyEnv` types (replaced by `DefaultEnv`) - Drop deprecated setting of global `$servlet_context` variable during embedded usage (replaced by `JRuby::Rack.context`) -Breaking configuration capability changes -- Drop `jruby.rack.jruby.version` and `jruby.rack.rack.release` keys from rack `env` Hash -- Drop deprecated and undocumented jruby-rack 1.0 backwards compat properties `jruby.runtime.timeout.sec`, `jruby.runtime.initializer.threads`, `jruby.init.serial`, `jruby.rack.request.size.threshold.bytes` -- Drop deprecated `jruby.rack.ignore.env` property, replaced long ago by `jruby.runtime.env` and optional `jruby.runtime.env.rubyopt` -- Drop deprecated `jruby.rack.filter.*` properties, replaced long ago by init parameters `addsHtmlToPathInfo` and `verifiesHtmlResource` - ## 1.2.8 - Improve isolation and bundler version/CLI boot issues with more opinionated boot process (#461) diff --git a/Gemfile b/Gemfile index 78d8d7b93..f47ca98ec 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' group :default do - if rack_version = ENV['RACK_VERSION'] + if (rack_version = ENV['RACK_VERSION']) gem 'rack', rack_version else gem 'rack', '~> 2.2.24' diff --git a/README.md b/README.md index b55e70015..c3e77f421 100644 --- a/README.md +++ b/README.md @@ -267,24 +267,10 @@ Ruby environment before booting the application. You can create a file called These files, if found, will be evaluated before booting the Rack environment, allowing you to set environment variables, load scripts, etc. -For plain Rack applications, JRuby-Rack also supports a magic comment to solve -the "rackup" chicken-egg problem (you need Rack's builder loaded before loading -the `config.ru`, yet you may want to setup the gem version from within the rackup - file). As we ship with the Rack gem bundled, otherwise when executing the -provided `config.ru` the bundled (latest) version of Rack will get loaded. - -Use `rack.version` to specify the Rack gem version to be loaded before rackup : - -```ruby -# encoding: UTF-8 -# rack.version: ~>2.2.10 (before code is loaded gem '~>2.2.10' will be called) -``` - -Or the equivalent of doing `bundle exec rackup ...` if you're using Bundler : - -```ruby -# rack.version: bundler (require 'bundler'; Bundler.setup; before loading the script) -``` +JRuby-Rack does not vendor Rack - the application is expected to provide it, just like +with other Ruby web servers. For applications depending on `jruby-rack` via jar (rather than gem), +this means having `rack` in the `Gemfile` (usually implied by the web framework); +or available on the application's gem path. ## Logging diff --git a/Rakefile b/Rakefile index 3014f0de4..b298734ad 100644 --- a/Rakefile +++ b/Rakefile @@ -51,53 +51,18 @@ task(:test_prepare => ['target/classes', 'target/test-classes']) do sh "./mvnw -ntp -Dstyle.color=always -Djruby.compat.artifact=jruby-complete test-compile" end -desc "Unpack the rack gem" -task :unpack_gem => "target" do |t| - target = File.expand_path(t.prerequisites.first) - rack_gemfile = Gem.loaded_specs['rack'].cache_file - unless uptodate?("#{target}/vendor/rack.rb", [__FILE__, rack_gemfile]) - mkdir_p "target/vendor" - require 'rubygems/installer' - rack_dir = File.basename(rack_gemfile).sub(/\.gem$/, '') - Gem::Package.new(rack_gemfile).extract_files("#{target}/#{rack_dir}") - File.open("#{target}/vendor/rack.rb", "w") do |f| - f << "dir = File.dirname(__FILE__)\n" - f << "if dir =~ /.jar!/ && dir !~ /^file:/\n" - f << " $LOAD_PATH.unshift 'file:' + dir + '/#{rack_dir}'\n" - f << "else\n" - f << " $LOAD_PATH.unshift dir + '/#{rack_dir}'\n" - f << "end\n" - f << "require 'rack'" - end - end -end -GENERATED << 'target/vendor/rack.rb' - -desc "Generate (ruby) resources" -task :resources => ['target/classes', :unpack_gem] do |t| - rack_dir = File.basename(FileList["target/rack-*"].first) - classes_dir = t.prerequisites.first - { 'target/vendor' => "#{classes_dir}/vendor", - "target/#{rack_dir}/lib" => "#{classes_dir}/vendor/#{rack_dir}"}.each do |src,dest| - mkdir_p dest - FileList["#{src}/*"].each do |f| - cp_r f, dest - end - end -end - task :test_resources => ["target/test-classes"] namespace :resources do - desc "Copy (and generate) resources" - task :copy => :resources do + desc "Copy resources" + task :copy do sh './mvnw -ntp process-resources -Dstyle.color=always -Dmdep.skip=true' end desc "Generate test resources" task :test => :test_resources end -task :speconly => [ :resources, :test_resources ] do +task :speconly => [ :test_resources ] do if ENV['SKIP_SPECS'].to_s == 'true' puts "Skipping specs due to SKIP_SPECS=#{ENV['SKIP_SPECS']}" else @@ -143,7 +108,6 @@ GENERATED << target_jruby_rack file (target_jar = "target/jruby-rack-#{JAR_VERSION}.jar") do |file| Rake::Task['compile'].invoke - Rake::Task['resources'].invoke sh "jar cf #{file.name} -C target/classes ." end @@ -179,6 +143,7 @@ task :gem => [:clean, target_jar, target_jruby_rack, target_jruby_rack_version] gem.files = FileList["./**/*"].exclude("*.gem").map{ |f| f.sub(/^\.\//, '') } gem.homepage = %q{http://jruby.org} gem.required_ruby_version = '>= 3.4.0' # JRuby >= 10.0 + gem.add_dependency 'rack', '~> 2.2.0' end require 'rubygems/package' diff --git a/examples/README.md b/examples/README.md index 17acdb929..4d21a5605 100644 --- a/examples/README.md +++ b/examples/README.md @@ -21,7 +21,7 @@ As an executable jar within Jetty: rm -f Gemfile.lock && bundle install && bundle exec warble executable war ``` 2. ```shell - java -Dwarbler.debug=true -Dwarbler.port=8080 -jar *.war + java -Dwarbler.debug=true -Dwarbler.port=8989 -jar *.war ``` ## Demo routes @@ -29,21 +29,21 @@ As an executable jar within Jetty: | Example | Component | Embedded Route | Deployed War Route | |---------|------------------------|-------------------------------------|---------------------------------------------| | Rails 7 | Status Page | http://localhost:8080/up | http://localhost:8080/rails7/up | -| Rails 7 | Snoop Dump | http://localhost:8080/snoop | http://localhost:8080/rails7/snoop | -| Rails 7 | Simple Form submission | http://localhost:8080/simple_form | http://localhost:8080/rails7/simple_form | -| Rails 7 | Body Posts | http://localhost:8080/body | http://localhost:8080/rails7/body | -| Rails 7 | JSP (render) | http://localhost:8080/jsp/ | http://localhost:8080/rails7/jsp/ | -| Rails 7 | JSP (forward to) | http://localhost:8080/jsp-forward/ | http://localhost:8080/rails7/jsp-forward/ | -| Rails 7 | JSP (include) | http://localhost:8080/jsp-include/ | http://localhost:8080/rails7/jsp-include/ | -| Sinatra | Demo Index | http://localhost:8080/ | http://localhost:8080/sinatra | -| Sinatra | Info | http://localhost:8080/info | http://localhost:8080/sinatra/info | -| Sinatra | Snoop Dump | http://localhost:8080/env | http://localhost:8080/sinatra/env | -| Sinatra | JSP (render) | http://localhost:8080/jsp/index.jsp | http://localhost:8080/sinatra/jsp/index.jsp | -| Sinatra | JSP (forward to) | http://localhost:8080/jsp_forward | http://localhost:8080/sinatra/jsp_forward | -| Sinatra | JSP (include) | http://localhost:8080/jsp_include | http://localhost:8080/sinatra/jsp_include | -| Sinatra | Streaming Demo | http://localhost:8080/stream | http://localhost:8080/sinatra/stream | -| Camping | Demo Index | http://localhost:8080/ | http://localhost:8080/camping | -| Camping | Snoop Dump | http://localhost:8080/snoop | http://localhost:8080/camping/snoop | +| Rails 7 | Snoop Dump | http://localhost:8989/snoop | http://localhost:8080/rails7/snoop | +| Rails 7 | Simple Form submission | http://localhost:8989/simple_form | http://localhost:8080/rails7/simple_form | +| Rails 7 | Body Posts | http://localhost:8989/body | http://localhost:8080/rails7/body | +| Rails 7 | JSP (render) | http://localhost:8989/jsp/ | http://localhost:8080/rails7/jsp/ | +| Rails 7 | JSP (forward to) | http://localhost:8989/jsp-forward/ | http://localhost:8080/rails7/jsp-forward/ | +| Rails 7 | JSP (include) | http://localhost:8989/jsp-include/ | http://localhost:8080/rails7/jsp-include/ | +| Sinatra | Demo Index | http://localhost:8989/ | http://localhost:8080/sinatra | +| Sinatra | Info | http://localhost:8989/info | http://localhost:8080/sinatra/info | +| Sinatra | Snoop Dump | http://localhost:8989/env | http://localhost:8080/sinatra/env | +| Sinatra | JSP (render) | http://localhost:8989/jsp/index.jsp | http://localhost:8080/sinatra/jsp/index.jsp | +| Sinatra | JSP (forward to) | http://localhost:8989/jsp_forward | http://localhost:8080/sinatra/jsp_forward | +| Sinatra | JSP (include) | http://localhost:8989/jsp_include | http://localhost:8080/sinatra/jsp_include | +| Sinatra | Streaming Demo | http://localhost:8989/stream | http://localhost:8080/sinatra/stream | +| Camping | Demo Index | http://localhost:8989/ | http://localhost:8080/camping | +| Camping | Snoop Dump | http://localhost:8989/snoop | http://localhost:8080/camping/snoop | ## Development diff --git a/examples/camping/Gemfile b/examples/camping/Gemfile index 4bf2959c8..d196905b7 100644 --- a/examples/camping/Gemfile +++ b/examples/camping/Gemfile @@ -2,8 +2,7 @@ source 'https://rubygems.org' ruby RUBY_VERSION -gem 'camping', '< 3' -gem 'rack', '~> 2.2.0' +gem 'camping', '< 3' # v3 requires Rack 3.x support group :development do gem 'jruby-jars', JRUBY_VERSION diff --git a/examples/rails7/Gemfile b/examples/rails7/Gemfile index c4549f3bf..f6c1746eb 100644 --- a/examples/rails7/Gemfile +++ b/examples/rails7/Gemfile @@ -4,7 +4,6 @@ ruby RUBY_VERSION gem 'rails', '~> 7.2.0' gem 'sprockets-rails' -gem 'rack', '~> 2.2.0' group :development do gem 'jruby-jars', JRUBY_VERSION diff --git a/examples/sinatra/Gemfile b/examples/sinatra/Gemfile index db21fe919..f77c3478d 100644 --- a/examples/sinatra/Gemfile +++ b/examples/sinatra/Gemfile @@ -2,8 +2,12 @@ source 'https://rubygems.org' ruby RUBY_VERSION -gem 'sinatra', '< 4' -gem 'rack', '~> 2.2.0' +gem 'sinatra', '< 4' # v4 requires Rack 3.x support + +if JRUBY_VERSION.start_with?('10.1.') + gem 'ostruct' + gem 'logger' +end group :development do gem 'jruby-jars', JRUBY_VERSION diff --git a/pom.xml b/pom.xml index 2fd3fdaf9..e60dcf063 100644 --- a/pom.xml +++ b/pom.xml @@ -275,16 +275,6 @@ -S rake speconly SKIP_SPECS=${skipTests} - - - rake-resources - prepare-package - - exec - - -S rake resources VERSION=${project.version} - - diff --git a/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java b/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java index 0fe0cedca..05f7619bc 100644 --- a/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java +++ b/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java @@ -165,7 +165,6 @@ public IRubyObject createApplicationObject(final Ruby runtime) { rackContext.log(WARN, "no rackup script found - starting empty Rack application!"); rackupScript = ""; } - checkAndSetRackVersion(runtime); runtime.evalScriptlet("load 'jruby/rack/boot/rack.rb'"); return createRackServletWrapper(runtime, rackupScript, rackupLocation); } @@ -366,40 +365,6 @@ public void initRuntime(final Ruby runtime) { } } - /** - * Checks and sets the required Rack version (if specified as a magic comment). - * - * e.g. # rack.version: =2.2.0 - * - * @apiNote Internal API, only visible due tests. - * - * @param runtime the JRuby runtime - * @return the rack version requirement - */ - public String checkAndSetRackVersion(final Ruby runtime) { - String rackVersion = null; - try { - rackVersion = IOHelpers.rubyMagicCommentValue(rackupScript, "rack.version:"); - } - catch (Exception e) { - rackContext.log(DEBUG, "could not read 'rack.version' magic comment from rackup", e); - } - - if ( rackVersion != null ) { - runtime.evalScriptlet("require 'rubygems'"); - - if ( rackVersion.equalsIgnoreCase("bundler") ) { - runtime.evalScriptlet("require 'bundler'; Bundler.setup"); - } - else { - rackContext.log(DEBUG, "detected 'rack.version' magic comment, " + - "will use `gem 'rack', '"+ rackVersion +"'`"); - runtime.evalScriptlet("gem 'rack', '"+ rackVersion +"' if defined? gem"); - } - } - return rackVersion; - } - private RackApplication createApplication(final ApplicationObjectFactory appFactory) { return new RackApplicationImpl(appFactory); } diff --git a/src/main/java/org/jruby/rack/util/IOHelpers.java b/src/main/java/org/jruby/rack/util/IOHelpers.java index 9091cb67a..4362aba0a 100644 --- a/src/main/java/org/jruby/rack/util/IOHelpers.java +++ b/src/main/java/org/jruby/rack/util/IOHelpers.java @@ -23,12 +23,10 @@ */ package org.jruby.rack.util; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.io.StringReader; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,27 +65,4 @@ public static String inputStreamToString(final InputStream stream) return str.toString(); } - public static String rubyMagicCommentValue(final String script, final String prefix) - throws IOException { - if ( script == null ) return null; - - final BufferedReader reader = new BufferedReader(new StringReader(script), 80); - - String line, comment = null; Pattern pattern = null; - while ( (line = reader.readLine()) != null ) { - // we only support (magic) comments at the beginning : - if (line.isEmpty() || line.charAt(0) != '#' ) break; - - if (pattern == null) { - pattern = Pattern.compile(prefix + "\\s*(\\S+)"); - } - Matcher matcher = pattern.matcher(line); - if (matcher.find()) { - comment = matcher.group(1); break; - } - } - reader.close(); - return comment; - } - } \ No newline at end of file diff --git a/src/main/ruby/jruby/rack.rb b/src/main/ruby/jruby/rack.rb index 445b41f18..d65077cfb 100644 --- a/src/main/ruby/jruby/rack.rb +++ b/src/main/ruby/jruby/rack.rb @@ -60,6 +60,6 @@ def logger=(logger); @@logger = logger end require 'jruby/rack/servlet_ext' require 'jruby/rack/core_ext' -# loading Rack is delayed to allow the application to boot it's desired Rack -# version (if it needs one) e.g. in a Rails application until Bundler setups +# loading Rack is delayed until the booter has run `Bundler.setup` (for a +# bundled application), so that the application's lockfile decides the version JRuby::Rack::Booter.on_boot { require 'jruby/rack/rack_ext' } diff --git a/src/main/ruby/jruby/rack/booter.rb b/src/main/ruby/jruby/rack/booter.rb index 9b2aececa..ebe1bfbc1 100644 --- a/src/main/ruby/jruby/rack/booter.rb +++ b/src/main/ruby/jruby/rack/booter.rb @@ -91,6 +91,7 @@ def boot! export_global_settings load_settings_from_init_rb prepare_bundler_env + prepare_bundler set_relative_url_root run_boot_hooks self @@ -199,6 +200,19 @@ def prepare_bundler_env ENV['BUNDLE_FROZEN'] ||= 'true' if File.exist?("#{ENV['BUNDLE_GEMFILE']}.lock") end + # Boots Bundler (`Bundler.setup`) up-front for a bundled application, so that gems required during the boot - Rack + # in particular - resolve per the application's lockfile, instead of rubygems activating the newest version found + # on the gem path. The application's own `Bundler.setup` (e.g. from *config.ru*) then becomes a no-op. + def prepare_bundler + boot_bundler! if ENV['BUNDLE_GEMFILE'] # not a bundled application + end + + def boot_bundler! + require 'bundler' + # pre-boot bundler with groups respecting BUNDLE_WITHOUT from the environment + Bundler.ui.silence { Bundler.setup } + end + def relative_url_root(init_param = 'rack.relative_url_append') relative_url_root = @rack_context.getContextPath || '' if relative_url_append = @rack_context.getInitParameter(init_param) diff --git a/src/main/ruby/jruby/rack/rack_ext.rb b/src/main/ruby/jruby/rack/rack_ext.rb index 79c531944..4ba177249 100644 --- a/src/main/ruby/jruby/rack/rack_ext.rb +++ b/src/main/ruby/jruby/rack/rack_ext.rb @@ -7,8 +7,9 @@ begin require 'rack' -rescue LoadError - require 'vendor/rack' +rescue LoadError => e + raise LoadError, "#{e.message}\nJRuby-Rack no longer vendors Rack - make sure the rack gem is " \ + "available to the application (e.g. add it to the Gemfile or install it into the gem path)" end unless defined?(::Rack::RELEASE) # Servlet API friendly extensions to Rack diff --git a/src/main/ruby/jruby/rack/rails_booter.rb b/src/main/ruby/jruby/rack/rails_booter.rb index b04e7e042..32ab26c47 100644 --- a/src/main/ruby/jruby/rack/rails_booter.rb +++ b/src/main/ruby/jruby/rack/rails_booter.rb @@ -38,9 +38,7 @@ def to_app # Loads the Rails environment (*config/environment.rb*). def load_environment - user_boot = expand_path('config/boot.rb') - prepare_bundler(user_boot) - require user_boot + require rails_boot_path require 'jruby/rack/rails/railtie' require expand_path('config/environment.rb') require 'jruby/rack/rails/extensions' @@ -48,45 +46,46 @@ def load_environment protected + # For a Rails booter bundler setup is delayed to be run during the (Rails) environment load so we can + # determine whether Rails requires opinionated bundler pre-boot. + # @see JRuby::Rack::RailsBooter#load_environment + # @see #rails_boot_path + def prepare_bundler + # no-op, deferred + end + def set_relative_url_root if rails_relative_url_root = relative_url_root('rails.relative_url_append') ENV['RAILS_RELATIVE_URL_ROOT'] = rails_relative_url_root end end - # no rack etc extensions required here (called during boot!) - # require 'jruby/rack/rails/extensions' on #load_environment + def rails_boot_path + user_boot = expand_path('config/boot.rb') + # pre-boot bundler if the user boot.rb appears to be using CLI/default bundler setup + boot_bundler! if default_rails_bundler_boot?(user_boot) + user_boot + end - # For a Rails booter the boot hooks are delayed to be run after the - # (Rails) environment gets loaded. - # @see JRuby::Rack::Railtie + # For a Rails booter the boot hooks are delayed to be run after the (Rails) environment gets loaded, before + # extensions. + # @see JRuby::Rack::RailsBooter#load_environment / jruby/rack/rails/extensions # @see JRuby::Rack::Booter#run_boot_hooks + # @see JRuby::Rack::Railtie# def run_boot_hooks - # no-op hooks run when 'jruby/rack/rails/extensions' gets loaded + # no-op, deferred end private - # For a default (unmodified) Rails *config/boot.rb*, runs `Bundler.setup` up-front. `bundler/setup` can swallow setup - # errors and end up calling `exit` when it believes stdout is a tty (which is frequently mis-detected under a servlet - # container); pre-booting makes failures raise instead, so the container logs the actual error. - def prepare_bundler(boot_rb_path) + def default_rails_bundler_boot?(boot_rb_path) return unless ENV['BUNDLE_GEMFILE'] # not a bundled application - - if rails_has_default_bundler_boot?(boot_rb_path) - # pre-boot bundler with groups respecting BUNDLE_WITHOUT from the environment - require 'bundler' - Bundler.ui.silence { Bundler.setup } - end - end - - def rails_has_default_bundler_boot?(boot_rb_path) boot_rb_content = File.read(boot_rb_path) if File.readable?(boot_rb_path) - return false unless boot_rb_content # Assume default if there is a `require 'bundler/setup'` and no custom Bundler management e.g # explicit `Bundler.setup(...)` call or `BUNDLE_WITHOUT` hardcoded. - %r{^\s*require\s+["']bundler/setup["']} =~ boot_rb_content && + boot_rb_content && + %r{^\s*require\s+["']bundler/setup["']} =~ boot_rb_content && %r{Bundler\.setup} !~ boot_rb_content && %r{BUNDLE_WITHOUT} !~ boot_rb_content end @@ -105,7 +104,7 @@ def to_app; rails_booter.to_app end # @private def rails_booter - raise "no booter set" unless booter = JRuby::Rack.booter + raise "no booter set" unless (booter = JRuby::Rack.booter) raise "not a rails booter" unless booter.is_a?(JRuby::Rack::RailsBooter) booter end diff --git a/src/spec/ruby/jruby/rack/booter_spec.rb b/src/spec/ruby/jruby/rack/booter_spec.rb index 9cebdb910..86afe2e74 100644 --- a/src/spec/ruby/jruby/rack/booter_spec.rb +++ b/src/spec/ruby/jruby/rack/booter_spec.rb @@ -423,4 +423,41 @@ def boot_app(gemfile = "source 'https://rubygems.org'\n", lockfile = "GEM\n") end + describe "#prepare_bundler" do + require 'tmpdir'; require 'fileutils' + + before :each do + @original_pwd = Dir.pwd + @original_bundle_env = {} + %w(BUNDLE_GEMFILE BUNDLE_VERSION BUNDLE_FROZEN).each { |k| @original_bundle_env[k] = ENV.delete(k) } + require 'bundler' + end + + after :each do + Dir.chdir(@original_pwd) + @original_bundle_env.each { |k, v| v.nil? ? ENV.delete(k) : ENV[k] = v } + FileUtils.rm_rf @app_dir if @app_dir + end + + def boot_app(gemfile = "source 'https://rubygems.org'\n") + @app_dir = File.realpath(Dir.mktmpdir('rack-app')) # macOS: /var -> /private/var + File.write(File.join(@app_dir, 'Gemfile'), gemfile) if gemfile + booter.layout_class = JRuby::Rack::FileSystemLayout + booter.app_path = @app_dir + booter.boot! + end + + it "boots Bundler up-front for a bundled application (so Rack resolves per the lockfile)" do + allow(Bundler.ui).to receive(:silence).and_yield + expect(Bundler).to receive(:setup) + boot_app + end + + it "does not boot Bundler for a non-bundled application (no Gemfile)" do + expect(Bundler).to_not receive(:setup) + boot_app nil + end + + end + end diff --git a/src/spec/ruby/jruby/rack/rails_booter_spec.rb b/src/spec/ruby/jruby/rack/rails_booter_spec.rb index 171074d9d..2b03b3613 100644 --- a/src/spec/ruby/jruby/rack/rails_booter_spec.rb +++ b/src/spec/ruby/jruby/rack/rails_booter_spec.rb @@ -132,39 +132,35 @@ def booted_with_boot_rb(boot_rb, gemfile = "source 'https://rubygems.org'\n") booter end - def prepare_bundler!(booted) - booted.send :prepare_bundler, File.join(@app_dir, 'config', 'boot.rb') - end - it "pre-boots bundler for a default rails boot.rb" do booted = booted_with_boot_rb DEFAULT_RAILS_BOOT_RB allow(Bundler.ui).to receive(:silence).and_yield expect(Bundler).to receive(:setup) - prepare_bundler! booted + booted.send :rails_boot_path end it "does not pre-boot when boot.rb manages BUNDLE_WITHOUT itself" do booted = booted_with_boot_rb %Q{ENV['BUNDLE_WITHOUT'] = 'test'\nrequire "bundler/setup"\n} expect(Bundler).to_not receive(:setup) - prepare_bundler! booted + booted.send :rails_boot_path end it "does not pre-boot when boot.rb ever calls Bundler.setup itself" do booted = booted_with_boot_rb %Q{if ENV['BOOT_ALL']\n require "bundler/setup"\nelse\n require "bundler"\n Bundler.setup(:default)\nend\n} expect(Bundler).to_not receive(:setup) - prepare_bundler! booted + booted.send :rails_boot_path end it "does not pre-boot when the require is commented out" do booted = booted_with_boot_rb %Q{# require "bundler/setup"\n} expect(Bundler).to_not receive(:setup) - prepare_bundler! booted + booted.send :rails_boot_path end it "does not pre-boot a non-bundled application (no Gemfile)" do booted = booted_with_boot_rb DEFAULT_RAILS_BOOT_RB, nil expect(Bundler).to_not receive(:setup) - prepare_bundler! booted + booted.send :rails_boot_path end end diff --git a/src/spec/ruby/rack/application_spec.rb b/src/spec/ruby/rack/application_spec.rb index b8b031f07..183651092 100644 --- a/src/spec/ruby/rack/application_spec.rb +++ b/src/spec/ruby/rack/application_spec.rb @@ -2,8 +2,6 @@ describe org.jruby.rack.DefaultRackApplication, "call" do - before(:all) { require 'tempfile' } - before :each do @rack_env = org.jruby.rack.RackEnvironment.impl do |name, *args| case name.to_s @@ -310,31 +308,6 @@ def newRuntime() should_eval_as_nil "defined?(::Rack::RELEASE)" end - it "loads specified version of rack via bundler", :lib => :stub do - gem_install_unless_installed 'rack', '2.2.0' - set_config 'jruby.runtime.env', 'false' - - script = "# encoding: UTF-8\n" + - "# rack.version: bundler \n" + - "Proc.new { 'proc-rack-app' }" - app_factory.setRackupScript script - @runtime = app_factory.newRuntime - - file = Tempfile.new('Gemfile') - file << "source 'https://rubygems.org'\n gem 'rack', '2.2.0'" - file.flush - @runtime.evalScriptlet "ENV['BUNDLE_GEMFILE'] = #{file.path.inspect}" - @runtime.evalScriptlet "ENV['GEM_HOME'] = #{ENV['GEM_HOME'].inspect}" - @runtime.evalScriptlet "ENV['GEM_PATH'] = #{ENV['GEM_PATH'].inspect}" - - app_factory.checkAndSetRackVersion(@runtime) - @runtime.evalScriptlet "require 'rack'" - - should_eval_as_not_nil "defined?(Bundler)" - should_eval_as_eql_to "Rack.release", '2.2.0' - should_eval_as_eql_to "Gem.loaded_specs['rack'].version.to_s", '2.2.0' - end - it "initializes the $servlet_context global variable" do @runtime = app_factory.new_runtime expect(@runtime.evalScriptlet("defined?($servlet_context)")).to be_truthy diff --git a/src/spec/ruby/rack/util_spec.rb b/src/spec/ruby/rack/util_spec.rb index b239cfaa8..e93f2ecab 100644 --- a/src/spec/ruby/rack/util_spec.rb +++ b/src/spec/ruby/rack/util_spec.rb @@ -20,27 +20,4 @@ expect(string).to eql "# comment\nputs 'vůl or kôň';\nexit(0)\n" end - it "reads magic comment 1" do - code = "# hello: world \n" + - "# comment\n" + - "exit(0);" - string = IOHelpers.rubyMagicCommentValue(code, "hello:") - expect(string).to eql "world" - end - - it "reads magic comment 2" do - code = "# encoding: UTF-8 \n" + - "# comment\n" + - "# rack.version: 2.2.0 \n" + - "exit(0)\n'42'" - string = IOHelpers.rubyMagicCommentValue(code, "rack.version:") - expect(string).to eql "2.2.0" - end - - it "works when reading an empty/null string" do - expect(IOHelpers.rubyMagicCommentValue(nil, 'ruby.version:')).to be nil - expect(IOHelpers.rubyMagicCommentValue('', 'ruby.version:')).to be nil - expect(IOHelpers.rubyMagicCommentValue("\n", 'ruby.version:')).to be nil - end - end \ No newline at end of file diff --git a/src/spec/ruby/spec_helper.rb b/src/spec/ruby/spec_helper.rb index c3aa7fe38..6a72e618e 100644 --- a/src/spec/ruby/spec_helper.rb +++ b/src/spec/ruby/spec_helper.rb @@ -59,12 +59,6 @@ def raise_logger(level = 'WARN') org.jruby.rack.logging.RaiseLogger.new(level, JRuby.runtime.out) end - def gem_install_unless_installed(name, version) - require 'rubygems/dependency_installer' - installer = Gem::DependencyInstaller.new - installer.install name, version - end - ExpectationNotMetError = RSpec::Expectations::ExpectationNotMetError def expect_eql_java_bytes(actual, expected)