From 009873aec89a4b843b41accf616b42b7a9917ba8 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 6 Jan 2013 16:13:47 -0700 Subject: Introduce ./bin for your app's executables: bin/bundle, bin/rails, bin/rake. Executable scripts are versioned code like the rest of your app. To generate a stub for a bundled gem: 'bundle binstubs unicorn' and 'git add bin/unicorn' --- railties/lib/rails/app_rails_loader.rb | 29 ++++++++++++++++++++++ railties/lib/rails/cli.rb | 7 ++++-- railties/lib/rails/commands.rb | 2 +- railties/lib/rails/commands/runner.rb | 2 +- railties/lib/rails/generators/actions.rb | 2 +- .../rails/generators/rails/app/app_generator.rb | 22 ++++++++-------- .../rails/generators/rails/app/templates/README | 11 +++++--- .../generators/rails/app/templates/bin/bundle | 3 +++ .../rails/generators/rails/app/templates/bin/rails | 3 +++ .../rails/generators/rails/app/templates/bin/rake | 3 +++ .../generators/rails/app/templates/script/rails | 5 ---- .../rails/plugin_new/plugin_new_generator.rb | 14 +++++------ .../rails/plugin_new/templates/bin/rails.tt | 7 ++++++ .../rails/plugin_new/templates/script/rails.tt | 7 ------ railties/lib/rails/script_rails_loader.rb | 29 ---------------------- railties/lib/rails/source_annotation_extractor.rb | 10 ++++---- railties/lib/rails/tasks/framework.rake | 10 ++++---- 17 files changed, 88 insertions(+), 78 deletions(-) create mode 100644 railties/lib/rails/app_rails_loader.rb create mode 100644 railties/lib/rails/generators/rails/app/templates/bin/bundle create mode 100644 railties/lib/rails/generators/rails/app/templates/bin/rails create mode 100644 railties/lib/rails/generators/rails/app/templates/bin/rake delete mode 100644 railties/lib/rails/generators/rails/app/templates/script/rails create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt delete mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt delete mode 100644 railties/lib/rails/script_rails_loader.rb (limited to 'railties/lib') diff --git a/railties/lib/rails/app_rails_loader.rb b/railties/lib/rails/app_rails_loader.rb new file mode 100644 index 0000000000..8937e10db3 --- /dev/null +++ b/railties/lib/rails/app_rails_loader.rb @@ -0,0 +1,29 @@ +require 'pathname' + +module Rails + module AppRailsLoader + RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"] + EXECUTABLE = 'bin/rails' + + def self.exec_app_rails + cwd = Dir.pwd + return unless in_rails_application_or_engine? || in_rails_application_or_engine_subdirectory? + exec RUBY, EXECUTABLE, *ARGV if in_rails_application_or_engine? + Dir.chdir("..") do + # Recurse in a chdir block: if the search fails we want to be sure + # the application is generated in the original working directory. + exec_app_rails unless cwd == Dir.pwd + end + rescue SystemCallError + # could not chdir, no problem just return + end + + def self.in_rails_application_or_engine? + File.exists?(EXECUTABLE) && File.read(EXECUTABLE) =~ /(APP|ENGINE)_PATH/ + end + + def self.in_rails_application_or_engine_subdirectory?(path = Pathname.new(Dir.pwd)) + File.exists?(File.join(path, EXECUTABLE)) || !path.root? && in_rails_application_or_engine_subdirectory?(path.parent) + end + end +end diff --git a/railties/lib/rails/cli.rb b/railties/lib/rails/cli.rb index 443d6f47ad..b717b026de 100644 --- a/railties/lib/rails/cli.rb +++ b/railties/lib/rails/cli.rb @@ -1,9 +1,12 @@ require 'rbconfig' -require 'rails/script_rails_loader' +require 'rails/app_rails_loader' # If we are inside a Rails application this method performs an exec and thus # the rest of this script is not run. -Rails::ScriptRailsLoader.exec_script_rails! +# +# TODO: when we hit this, advise adding ./bin to $PATH instead. Then the +# app's `rails` executable is run immediately. +Rails::AppRailsLoader.exec_app_rails require 'rails/ruby_version_check' Signal.trap("INT") { puts; exit(1) } diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index 5ccec8082c..9cb11f66c6 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -72,7 +72,7 @@ when 'console' when 'server' # Change to the application's path if there is no config.ru file in current dir. - # This allows us to run script/rails server from other directories, but still get + # This allows us to run `rails server` from other directories, but still get # the main config.ru and properly set the tmp directory. Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru")) diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb index 6adbdc6e0b..c4622d6a2d 100644 --- a/railties/lib/rails/commands/runner.rb +++ b/railties/lib/rails/commands/runner.rb @@ -24,7 +24,7 @@ ARGV.clone.options do |opts| if RbConfig::CONFIG['host_os'] !~ /mswin|mingw/ opts.separator "" - opts.separator "You can also use runner as a shebang line for your scripts like this:" + opts.separator "You can also use runner as a shebang line for your executables:" opts.separator "-------------------------------------------------------------" opts.separator "#!/usr/bin/env #{File.expand_path($0)} runner" opts.separator "" diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index b96ee9295e..71cb0b903b 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -186,7 +186,7 @@ module Rails log :generate, what argument = args.map {|arg| arg.to_s }.flatten.join(" ") - in_root { run_ruby_script("script/rails generate #{what} #{argument}", verbose: false) } + in_root { run_ruby_script("bin/rails generate #{what} #{argument}", verbose: false) } end # Runs the supplied rake task diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 372790df59..7d9044a2b4 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -63,6 +63,13 @@ module Rails keep_file 'app/models/concerns' end + def bin + directory "bin" do |content| + "#{shebang}\n" + content + end + chmod "bin", 0755, verbose: false + end + def config empty_directory "config" @@ -103,13 +110,6 @@ module Rails directory "public", "public", recursive: false end - def script - directory "script" do |content| - "#{shebang}\n" + content - end - chmod "script", 0755, verbose: false - end - def test empty_directory_with_keep_file 'test/fixtures' empty_directory_with_keep_file 'test/controllers' @@ -178,6 +178,10 @@ module Rails build(:app) end + def create_bin_files + build(:bin) + end + def create_config_files build(:config) end @@ -211,10 +215,6 @@ module Rails build(:public_directory) end - def create_script_files - build(:script) - end - def create_test_files build(:test) unless options[:skip_test_unit] end diff --git a/railties/lib/rails/generators/rails/app/templates/README b/railties/lib/rails/generators/rails/app/templates/README index 2bd7c27f2a..e566c01c46 100644 --- a/railties/lib/rails/generators/rails/app/templates/README +++ b/railties/lib/rails/generators/rails/app/templates/README @@ -166,6 +166,7 @@ The default directory structure of a generated Ruby on Rails application: | | `-- concerns | `-- views | `-- layouts + |-- bin |-- config | |-- environments | |-- initializers @@ -177,7 +178,6 @@ The default directory structure of a generated Ruby on Rails application: | `-- tasks |-- log |-- public - |-- script |-- test | |-- controllers | |-- fixtures @@ -226,6 +226,12 @@ app/helpers generated for you automatically when using generators for controllers. Helpers can be used to wrap functionality for your views into methods. +bin + Your app's executables -- bundler, rake, rails, and more -- automatically + run using your app's Ruby version and its bundled gems. When you bundle + a new gem and need to run one of its executables, use `bundle binstubs ` + to add it. For example, `bundle binstubs unicorn` adds ./bin/unicorn. + config Configuration files for the Rails environment, the routing map, the database, and other dependencies. @@ -248,9 +254,6 @@ public default HTML files. This should be set as the DOCUMENT_ROOT of your web server. -script - Helper scripts for automation and generation. - test Unit and functional tests along with fixtures. When using the rails generate command, template test files will be generated for you and placed in this diff --git a/railties/lib/rails/generators/rails/app/templates/bin/bundle b/railties/lib/rails/generators/rails/app/templates/bin/bundle new file mode 100644 index 0000000000..e0df7f4440 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/bin/bundle @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +require 'rubygems' +load Gem.bin_path('bundler', 'bundle') diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rails b/railties/lib/rails/generators/rails/app/templates/bin/rails new file mode 100644 index 0000000000..6a128b95e5 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/bin/rails @@ -0,0 +1,3 @@ +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rake b/railties/lib/rails/generators/rails/app/templates/bin/rake new file mode 100644 index 0000000000..d14fc8395b --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/bin/rake @@ -0,0 +1,3 @@ +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/railties/lib/rails/generators/rails/app/templates/script/rails b/railties/lib/rails/generators/rails/app/templates/script/rails deleted file mode 100644 index 11bc1edde9..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/script/rails +++ /dev/null @@ -1,5 +0,0 @@ -# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. - -APP_PATH = File.expand_path('../../config/application', __FILE__) -require File.expand_path('../../config/boot', __FILE__) -require 'rails/commands' diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index cd756a729d..af00748037 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -130,13 +130,13 @@ task default: :test end end - def script(force = false) + def bin(force = false) return unless engine? - directory "script", force: force do |content| + directory "bin", force: force do |content| "#{shebang}\n" + content end - chmod "script", 0755, verbose: false + chmod "bin", 0755, verbose: false end def gemfile_entry @@ -214,8 +214,8 @@ task default: :test build(:images) end - def create_script_files - build(:script) + def create_bin_files + build(:bin) end def create_test_files @@ -264,8 +264,8 @@ task default: :test store_application_definition! build(:test_dummy_config) build(:test_dummy_clean) - # ensure that script/rails has proper dummy_path - build(:script, true) + # ensure that bin/rails has proper dummy_path + build(:bin, true) end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt new file mode 100644 index 0000000000..aa87d1b50c --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt @@ -0,0 +1,7 @@ +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +ENGINE_ROOT = File.expand_path('../..', __FILE__) +ENGINE_PATH = File.expand_path('../../lib/<%= name -%>/engine', __FILE__) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt deleted file mode 100644 index aa87d1b50c..0000000000 --- a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt +++ /dev/null @@ -1,7 +0,0 @@ -# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. - -ENGINE_ROOT = File.expand_path('../..', __FILE__) -ENGINE_PATH = File.expand_path('../../lib/<%= name -%>/engine', __FILE__) - -require 'rails/all' -require 'rails/engine/commands' diff --git a/railties/lib/rails/script_rails_loader.rb b/railties/lib/rails/script_rails_loader.rb deleted file mode 100644 index 7054089614..0000000000 --- a/railties/lib/rails/script_rails_loader.rb +++ /dev/null @@ -1,29 +0,0 @@ -require 'pathname' - -module Rails - module ScriptRailsLoader - RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"] - SCRIPT_RAILS = File.join('script', 'rails') - - def self.exec_script_rails! - cwd = Dir.pwd - return unless in_rails_application? || in_rails_application_subdirectory? - exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application? - Dir.chdir("..") do - # Recurse in a chdir block: if the search fails we want to be sure - # the application is generated in the original working directory. - exec_script_rails! unless cwd == Dir.pwd - end - rescue SystemCallError - # could not chdir, no problem just return - end - - def self.in_rails_application? - File.exists?(SCRIPT_RAILS) - end - - def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd)) - File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent) - end - end -end \ No newline at end of file diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index ac806e8006..971fbf627b 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -15,7 +15,7 @@ class SourceAnnotationExtractor class Annotation < Struct.new(:line, :tag, :text) def self.directories - @@directories ||= %w(app config db lib script test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',') + @@directories ||= %w(app config db lib test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',') end # Returns a representation of the annotation that looks like this: @@ -31,11 +31,11 @@ class SourceAnnotationExtractor end end - # Prints all annotations with tag +tag+ under the root directories +app+, +config+, +lib+, - # +script+, and +test+ (recursively). Filenames with extension + # Prints all annotations with tag +tag+ under the root directories +app+, + # +config+, +lib+, and +test+ (recursively). Filenames with extension # +.builder+, +.rb+, +.erb+, +.haml+, +.slim+, +.css+, +.scss+, +.js+, - # +.coffee+, and +.rake+ are taken into account. The +options+ hash is passed to each - # annotation's +to_s+. + # +.coffee+, and +.rake+ are taken into account. The +options+ hash is + # passed to each annotation's +to_s+. # # This class method is the single entry point for the rake tasks. def self.enumerate(tag, options={}) diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake index 50499304cb..2116330b45 100644 --- a/railties/lib/rails/tasks/framework.rake +++ b/railties/lib/rails/tasks/framework.rake @@ -1,6 +1,6 @@ namespace :rails do - desc "Update configs and some other initially generated files (or use just update:configs, update:scripts, or update:application_controller)" - task update: [ "update:configs", "update:scripts", "update:application_controller" ] + desc "Update configs and some other initially generated files (or use just update:configs, update:bin, or update:application_controller)" + task update: [ "update:configs", "update:bin", "update:application_controller" ] desc "Applies the template supplied by LOCATION=(/path/to/template) or URL" task :template do @@ -58,9 +58,9 @@ namespace :rails do invoke_from_app_generator :create_config_files end - # desc "Adds new scripts to the application script/ directory" - task :scripts do - invoke_from_app_generator :create_script_files + # desc "Adds new executables to the application bin/ directory" + task :bin do + invoke_from_app_generator :create_bin_files end # desc "Rename application.rb to application_controller.rb" -- cgit v1.2.3