Skip to content

Commit

Permalink
Merge pull request #995 from Shopify/dont-load-engines-in-app
Browse files Browse the repository at this point in the history
Filter engines in application directory so they are not loaded
  • Loading branch information
KaanOzkan authored and vinistock committed Jun 27, 2022
1 parent a899608 commit 6ec08fe
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 19 deletions.
20 changes: 2 additions & 18 deletions lib/tapioca/gemfile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def dir

class GemSpec
extend(T::Sig)
include GemHelper

IGNORED_GEMS = T.let(["sorbet", "sorbet-static", "sorbet-runtime", "sorbet-static-and-runtime"].freeze,
T::Array[String])
Expand All @@ -160,7 +161,7 @@ def initialize(spec)

sig { params(gemfile_dir: String).returns(T::Boolean) }
def ignore?(gemfile_dir)
gem_ignored? || gem_in_app_dir?(gemfile_dir)
gem_ignored? || gem_in_app_dir?(gemfile_dir, full_gem_path)
end

sig { returns(String) }
Expand Down Expand Up @@ -284,27 +285,10 @@ def has_parent_gemspec?(path)
false
end

sig { params(path: T.any(String, Pathname)).returns(String) }
def to_realpath(path)
path_string = path.to_s
path_string = File.realpath(path_string) if File.exist?(path_string)
path_string
end

sig { returns(T::Boolean) }
def gem_ignored?
IGNORED_GEMS.include?(name)
end

sig { params(gemfile_dir: String).returns(T::Boolean) }
def gem_in_app_dir?(gemfile_dir)
!gem_in_bundle_path? && full_gem_path.start_with?(gemfile_dir)
end

sig { returns(T::Boolean) }
def gem_in_bundle_path?
full_gem_path.start_with?(Bundler.bundle_path.to_s, Bundler.app_cache.to_s)
end
end
end
end
26 changes: 26 additions & 0 deletions lib/tapioca/helpers/gem_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# typed: true
# frozen_string_literal: true

module Tapioca
module GemHelper
extend T::Sig

sig { params(gemfile_dir: String, full_gem_path: String).returns(T::Boolean) }
def gem_in_app_dir?(gemfile_dir, full_gem_path)
!gem_in_bundle_path?(to_realpath(full_gem_path)) &&
full_gem_path.start_with?(to_realpath(gemfile_dir))
end

sig { params(full_gem_path: String).returns(T::Boolean) }
def gem_in_bundle_path?(full_gem_path)
full_gem_path.start_with?(Bundler.bundle_path.to_s, Bundler.app_cache.to_s)
end

sig { params(path: T.any(String, Pathname)).returns(String) }
def to_realpath(path)
path_string = path.to_s
path_string = File.realpath(path_string) if File.exist?(path_string)
path_string
end
end
end
1 change: 1 addition & 0 deletions lib/tapioca/internal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require "tapioca/runtime/reflection"
require "tapioca/runtime/trackers"
require "tapioca/runtime/dynamic_mixin_compiler"
require "tapioca/helpers/gem_helper"
require "tapioca/runtime/loader"
require "tapioca/helpers/sorbet_helper"
require "tapioca/helpers/type_variable_helper"
Expand Down
6 changes: 5 additions & 1 deletion lib/tapioca/runtime/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Tapioca
module Runtime
class Loader
extend(T::Sig)
include Tapioca::GemHelper

sig do
params(gemfile: Tapioca::Gemfile, initialize_file: T.nilable(String), require_file: T.nilable(String)).void
Expand Down Expand Up @@ -55,7 +56,10 @@ def rails_engines
safe_require("active_support/core_ext/class/subclasses")

# We can use `Class#descendants` here, since we know Rails is loaded
Object.const_get("Rails::Engine").descendants.reject(&:abstract_railtie?)
Object.const_get("Rails::Engine")
.descendants
.reject(&:abstract_railtie?)
.reject { |engine| gem_in_app_dir?(Rails.root.to_path, engine.config.root.to_path) }
end

sig { params(path: String).void }
Expand Down
74 changes: 74 additions & 0 deletions spec/tapioca/cli/gem_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,80 @@ def foo(a, b, c, d, e, f, g, h); end
assert_empty_stderr(result)
assert_success_status(result)
end

it "must not load engines in the application" do
@project.write("config/application.rb", <<~RB)
require "rails"
module ModuleTest
class Application < Rails::Application
attr_reader :config
def initialize
super
root = Pathname.new("#{@project.path}")
@config = Rails::Application::Configuration.new(root)
end
end
def self.application
Application.new
end
end
lib_dir = File.expand_path("../lib/", __dir__)
# Add lib directory to load path
$LOAD_PATH << lib_dir
# Require files from lib directory
Dir.glob("**/*.rb", base: lib_dir).sort.each do |file|
require(file)
end
RB

@project.write("config/environment.rb", <<~RB)
require_relative "application.rb"
RB

@project.write("foo/app/models/foo.rb", <<~RB)
raise NotImplementedError, "This file should not be loaded"
RB

@project.write("foo/lib/foo.rb", <<~RB)
module Foo
class Engine < ::Rails::Engine
isolate_namespace Foo
end
end
RB

@project.write("foo/foo.gemspec", <<~GEMSPEC)
Gem::Specification.new do |spec|
spec.name = "foo"
spec.version = "0.0.1"
spec.authors = ["Maple Ong"]
spec.email = ["[email protected]"]
spec.summary = "Summary of Foo."
spec.description = "Description of Foo."
spec.files = Dir.chdir(File.expand_path(__dir__)) do
Dir["{app,lib}/**/*"]
end
spec.add_dependency "rails", ">= 7.0.3"
end
GEMSPEC

@project.require_real_gem("rails")
@project.gemfile(<<~GEMFILE, append: true)
gem 'foo', path: 'foo'
GEMFILE

@project.bundle_install
res = @project.tapioca("gem activesupport")

refute_includes(res.err, "This file should not be loaded")
assert_success_status(res)
end
end

describe "sync" do
Expand Down

0 comments on commit 6ec08fe

Please sign in to comment.