railties 3.0.0.beta4 → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/CHANGELOG +24 -6
  2. data/README.rdoc +25 -0
  3. data/guides/assets/javascripts/code_highlighter.js +0 -0
  4. data/guides/assets/javascripts/guides.js +0 -0
  5. data/guides/assets/stylesheets/print.css +0 -0
  6. data/guides/assets/stylesheets/reset.css +0 -0
  7. data/guides/assets/stylesheets/style.css +0 -0
  8. data/guides/source/3_0_release_notes.textile +5 -3
  9. data/guides/source/action_controller_overview.textile +19 -0
  10. data/guides/source/active_record_basics.textile +27 -21
  11. data/guides/source/active_record_querying.textile +39 -37
  12. data/guides/source/{activerecord_validations_callbacks.textile → active_record_validations_callbacks.textile} +30 -29
  13. data/guides/source/active_support_core_extensions.textile +232 -107
  14. data/guides/source/api_documentation_guidelines.textile +187 -0
  15. data/guides/source/association_basics.textile +45 -1
  16. data/guides/source/configuring.textile +7 -7
  17. data/guides/source/contributing_to_rails.textile +42 -15
  18. data/guides/source/form_helpers.textile +1 -1
  19. data/guides/source/generators.textile +37 -37
  20. data/guides/source/getting_started.textile +11 -11
  21. data/guides/source/i18n.textile +1 -1
  22. data/guides/source/index.html.erb +14 -6
  23. data/guides/source/initialization.textile +130 -124
  24. data/guides/source/layout.html.erb +5 -2
  25. data/guides/source/layouts_and_rendering.textile +2 -2
  26. data/guides/source/migrations.textile +4 -3
  27. data/guides/source/plugins.textile +15 -15
  28. data/guides/source/rails_application_templates.textile +2 -2
  29. data/guides/source/routing.textile +83 -62
  30. data/guides/source/security.textile +2 -2
  31. data/guides/w3c_validator.rb +30 -6
  32. data/lib/rails.rb +3 -3
  33. data/lib/rails/application.rb +43 -19
  34. data/lib/rails/application/bootstrap.rb +2 -0
  35. data/lib/rails/application/configuration.rb +3 -3
  36. data/lib/rails/application/finisher.rb +6 -6
  37. data/lib/rails/cli.rb +1 -19
  38. data/lib/rails/commands.rb +5 -5
  39. data/lib/rails/commands/application.rb +1 -1
  40. data/lib/rails/commands/console.rb +1 -4
  41. data/lib/rails/commands/generate.rb +0 -0
  42. data/lib/rails/commands/plugin.rb +57 -52
  43. data/lib/rails/commands/runner.rb +2 -1
  44. data/lib/rails/commands/server.rb +6 -2
  45. data/lib/rails/configuration.rb +2 -3
  46. data/lib/rails/console/app.rb +0 -2
  47. data/lib/rails/engine.rb +14 -15
  48. data/lib/rails/engine/configuration.rb +5 -5
  49. data/lib/rails/generators.rb +2 -3
  50. data/lib/rails/generators/actions.rb +4 -4
  51. data/lib/rails/generators/base.rb +1 -1
  52. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +1 -6
  53. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +4 -4
  54. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb +3 -3
  55. data/lib/rails/generators/erb/scaffold/templates/index.html.erb +7 -7
  56. data/lib/rails/generators/erb/scaffold/templates/new.html.erb +2 -2
  57. data/lib/rails/generators/erb/scaffold/templates/show.html.erb +3 -3
  58. data/lib/rails/generators/generated_attribute.rb +2 -1
  59. data/lib/rails/generators/named_base.rb +24 -0
  60. data/lib/rails/generators/rails/app/app_generator.rb +10 -9
  61. data/lib/rails/generators/rails/app/templates/Gemfile +4 -3
  62. data/lib/rails/generators/rails/app/templates/README +6 -31
  63. data/lib/rails/generators/rails/app/templates/Rakefile +1 -1
  64. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +0 -1
  65. data/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory +0 -0
  66. data/lib/rails/generators/rails/app/templates/config/application.rb +11 -11
  67. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml +36 -24
  68. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +1 -1
  69. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
  70. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +3 -0
  71. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +3 -0
  72. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +3 -0
  73. data/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb +1 -1
  74. data/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt +2 -2
  75. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +2 -2
  76. data/lib/rails/generators/rails/app/templates/config/routes.rb +1 -1
  77. data/lib/rails/generators/rails/app/templates/public/index.html +0 -17
  78. data/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js +2027 -900
  79. data/lib/rails/generators/rails/app/templates/public/javascripts/rails.js +114 -57
  80. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +1 -1
  81. data/lib/rails/generators/rails/model/USAGE +1 -1
  82. data/lib/rails/generators/rails/resource/resource_generator.rb +4 -14
  83. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +0 -2
  84. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +28 -30
  85. data/lib/rails/generators/resource_helpers.rb +1 -1
  86. data/lib/rails/generators/test_case.rb +25 -11
  87. data/lib/rails/generators/test_unit/model/model_generator.rb +1 -1
  88. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +0 -1
  89. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +13 -15
  90. data/lib/rails/info.rb +1 -2
  91. data/lib/rails/info_routes.rb +1 -1
  92. data/lib/rails/initializable.rb +3 -16
  93. data/lib/rails/paths.rb +31 -36
  94. data/lib/rails/plugin.rb +10 -6
  95. data/lib/rails/rack/logger.rb +11 -13
  96. data/lib/rails/railtie.rb +14 -42
  97. data/lib/rails/ruby_version_check.rb +19 -5
  98. data/lib/rails/script_rails_loader.rb +29 -0
  99. data/lib/rails/tasks/annotations.rake +2 -2
  100. data/lib/rails/tasks/documentation.rake +47 -16
  101. data/lib/rails/tasks/framework.rake +9 -9
  102. data/lib/rails/tasks/middleware.rake +1 -1
  103. data/lib/rails/tasks/misc.rake +5 -5
  104. data/lib/rails/tasks/routes.rake +1 -1
  105. data/lib/rails/tasks/tmp.rake +5 -5
  106. data/lib/rails/test_unit/testing.rake +38 -14
  107. data/lib/rails/version.rb +1 -1
  108. metadata +29 -17
  109. data/README +0 -281
  110. data/lib/rails/application/routes_reloader.rb +0 -46
  111. data/lib/rails/log_subscriber.rb +0 -115
  112. data/lib/rails/log_subscriber/test_helper.rb +0 -97
  113. data/lib/rails/webrick_server.rb +0 -156
@@ -286,7 +286,7 @@ When filtering user input file names, _(highlight)don't try to remove malicious
286
286
 
287
287
  <ruby>
288
288
  def sanitize_filename(filename)
289
- returning filename.strip do |name|
289
+ filename.strip.tap do |name|
290
290
  # NOTE: File.basename doesn't work right with Windows paths on Unix
291
291
  # get only the filename, not the whole path
292
292
  name.sub! /\A.*(\\|\/)/, ''
@@ -670,7 +670,7 @@ Also, the second query renames some columns with the AS statement so that the we
670
670
 
671
671
  h5(#sql-injection-countermeasures). Countermeasures
672
672
 
673
- Ruby on Rails has a built in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+:conditions => "..."+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>.
673
+ Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+:conditions => "..."+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>.
674
674
 
675
675
  Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:
676
676
 
@@ -35,23 +35,27 @@ module RailsGuides
35
35
 
36
36
  def validate
37
37
  validator = MarkupValidator.new
38
+ STDOUT.sync = true
39
+ errors_on_guides = {}
38
40
 
39
41
  guides_to_validate.each do |f|
40
- puts "Validating #{f}"
41
42
  results = validator.validate_file(f)
42
43
 
43
- if !results.validity
44
- puts "#{f} FAILED W3C validation with #{results.errors.size} error(s):"
45
- results.errors.each do |error|
46
- puts error.to_s
47
- end
44
+ if results.validity
45
+ print "."
46
+ else
47
+ print "E"
48
+ errors_on_guides[f] = results.errors
48
49
  end
49
50
  end
51
+
52
+ show_results(errors_on_guides)
50
53
  end
51
54
 
52
55
  private
53
56
  def guides_to_validate
54
57
  guides = Dir["./guides/output/*.html"]
58
+ guides.delete("./guides/output/layout.html")
55
59
  ENV.key?('ONLY') ? select_only(guides) : guides
56
60
  end
57
61
 
@@ -61,6 +65,26 @@ module RailsGuides
61
65
  prefixes.any? {|p| guide.start_with?("./guides/output/#{p}")}
62
66
  end
63
67
  end
68
+
69
+ def show_results(error_list)
70
+ if error_list.size == 0
71
+ puts "\n\nAll checked guides validate OK!"
72
+ else
73
+ error_summary = error_detail = ""
74
+
75
+ error_list.each_pair do |name, errors|
76
+ error_summary += "\n #{name}"
77
+ error_detail += "\n\n #{name} has #{errors.size} validation error(s):\n"
78
+ errors.each do |error|
79
+ error_detail += "\n "+error.to_s.gsub("\n", "")
80
+ end
81
+ end
82
+
83
+ puts "\n\nThere are #{error_list.size} guides with validation errors:\n" + error_summary
84
+ puts "\nHere are the detailed errors for each guide:" + error_detail
85
+ end
86
+ end
87
+
64
88
  end
65
89
  end
66
90
 
@@ -1,3 +1,5 @@
1
+ require 'rails/ruby_version_check'
2
+
1
3
  require 'pathname'
2
4
 
3
5
  require 'active_support'
@@ -7,8 +9,6 @@ require 'active_support/core_ext/logger'
7
9
  require 'rails/application'
8
10
  require 'rails/version'
9
11
  require 'rails/deprecation'
10
- require 'rails/log_subscriber'
11
- require 'rails/ruby_version_check'
12
12
 
13
13
  require 'active_support/railtie'
14
14
  require 'action_dispatch/railtie'
@@ -66,7 +66,7 @@ module Rails
66
66
 
67
67
  def backtrace_cleaner
68
68
  @@backtrace_cleaner ||= begin
69
- # Relies on ActiveSupport, so we have to lazy load to postpone definition until AS has been loaded
69
+ # Relies on Active Support, so we have to lazy load to postpone definition until AS has been loaded
70
70
  require 'rails/backtrace_cleaner'
71
71
  Rails::BacktraceCleaner.new
72
72
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/hash/reverse_merge'
2
+ require 'active_support/file_update_checker'
2
3
  require 'fileutils'
3
4
  require 'rails/plugin'
4
5
  require 'rails/engine'
@@ -7,14 +8,6 @@ module Rails
7
8
  # In Rails 3.0, a Rails::Application object was introduced which is nothing more than
8
9
  # an Engine but with the responsibility of coordinating the whole boot process.
9
10
  #
10
- # Opposite to Rails::Engine, you can only have one Rails::Application instance
11
- # in your process and both Rails::Application and YourApplication::Application
12
- # points to it.
13
- #
14
- # In other words, Rails::Application is Singleton and whenever you are accessing
15
- # Rails::Application.config or YourApplication::Application.config, you are actually
16
- # accessing YourApplication::Application.instance.config.
17
- #
18
11
  # == Initialization
19
12
  #
20
13
  # Rails::Application is responsible for executing all railties, engines and plugin
@@ -27,7 +20,7 @@ module Rails
27
20
  # Besides providing the same configuration as Rails::Engine and Rails::Railtie,
28
21
  # the application object has several specific configurations, for example
29
22
  # "allow_concurrency", "cache_classes", "consider_all_requests_local", "filter_parameters",
30
- # "logger", "reload_engines", "reload_plugins" and so forth.
23
+ # "logger", "reload_plugins" and so forth.
31
24
  #
32
25
  # Check Rails::Application::Configuration to see them all.
33
26
  #
@@ -46,7 +39,6 @@ module Rails
46
39
  autoload :Configuration, 'rails/application/configuration'
47
40
  autoload :Finisher, 'rails/application/finisher'
48
41
  autoload :Railties, 'rails/application/railties'
49
- autoload :RoutesReloader, 'rails/application/routes_reloader'
50
42
 
51
43
  class << self
52
44
  private :new
@@ -57,6 +49,10 @@ module Rails
57
49
 
58
50
  def instance
59
51
  if self == Rails::Application
52
+ if Rails.application
53
+ ActiveSupport::Deprecation.warn "Calling a method in Rails::Application is deprecated, " <<
54
+ "please call it directly in your application constant #{Rails.application.class.name}.", caller
55
+ end
60
56
  Rails.application
61
57
  else
62
58
  @@instance ||= new
@@ -67,7 +63,7 @@ module Rails
67
63
  raise "You cannot have more than one Rails::Application" if Rails.application
68
64
  super
69
65
  Rails.application = base.instance
70
- Rails.application.add_lib_to_load_paths!
66
+ Rails.application.add_lib_to_load_path!
71
67
  ActiveSupport.run_load_hooks(:before_configuration, base.instance)
72
68
  end
73
69
 
@@ -84,17 +80,30 @@ module Rails
84
80
 
85
81
  delegate :middleware, :to => :config
86
82
 
87
- def add_lib_to_load_paths!
83
+ # This method is called just after an application inherits from Rails::Application,
84
+ # allowing the developer to load classes in lib and use them during application
85
+ # configuration.
86
+ #
87
+ # class MyApplication < Rails::Application
88
+ # require "my_backend" # in lib/my_backend
89
+ # config.i18n.backend = MyBackend
90
+ # end
91
+ #
92
+ # Notice this method takes into consideration the default root path. So if you
93
+ # are changing config.root inside your application definition or having a custom
94
+ # Rails application, you will need to add lib to $LOAD_PATH on your own in case
95
+ # you need to load files in lib/ during the application configuration as well.
96
+ def add_lib_to_load_path! #:nodoc:
88
97
  path = config.root.join('lib').to_s
89
98
  $LOAD_PATH.unshift(path) if File.exists?(path)
90
99
  end
91
100
 
92
- def require_environment!
101
+ def require_environment! #:nodoc:
93
102
  environment = paths.config.environment.to_a.first
94
103
  require environment if environment
95
104
  end
96
105
 
97
- def eager_load!
106
+ def eager_load! #:nodoc:
98
107
  railties.all(&:eager_load!)
99
108
  super
100
109
  end
@@ -108,11 +117,17 @@ module Rails
108
117
  end
109
118
 
110
119
  def routes_reloader
111
- @routes_reloader ||= RoutesReloader.new
120
+ @routes_reloader ||= ActiveSupport::FileUpdateChecker.new([]){ reload_routes! }
112
121
  end
113
122
 
114
123
  def reload_routes!
115
- routes_reloader.reload!
124
+ _routes = self.routes
125
+ _routes.disable_clear_and_finalize = true
126
+ _routes.clear!
127
+ routes_reloader.paths.each { |path| load(path) }
128
+ ActiveSupport.on_load(:action_controller) { _routes.finalize! }
129
+ ensure
130
+ _routes.disable_clear_and_finalize = false
116
131
  end
117
132
 
118
133
  def initialize!
@@ -134,12 +149,20 @@ module Rails
134
149
  self
135
150
  end
136
151
 
152
+ def load_console(sandbox=false)
153
+ initialize_console(sandbox)
154
+ railties.all { |r| r.load_console }
155
+ super()
156
+ self
157
+ end
158
+
137
159
  def app
138
160
  @app ||= begin
139
161
  config.middleware = config.middleware.merge_into(default_middleware_stack)
140
162
  config.middleware.build(routes)
141
163
  end
142
164
  end
165
+ alias :build_middleware_stack :app
143
166
 
144
167
  def call(env)
145
168
  app.call(env.reverse_merge!(env_defaults))
@@ -197,9 +220,10 @@ module Rails
197
220
  require "rails/generators"
198
221
  end
199
222
 
200
- # Application is always reloadable when config.cache_classes is false.
201
- def reloadable?(app)
202
- true
223
+ def initialize_console(sandbox=false)
224
+ require "rails/console/app"
225
+ require "rails/console/sandbox" if sandbox
226
+ require "rails/console/helpers"
203
227
  end
204
228
  end
205
229
  end
@@ -1,4 +1,5 @@
1
1
  require "active_support/notifications"
2
+ require "active_support/descendants_tracker"
2
3
 
3
4
  module Rails
4
5
  class Application
@@ -55,6 +56,7 @@ module Rails
55
56
  initializer :set_clear_dependencies_hook do
56
57
  unless config.cache_classes
57
58
  ActionDispatch::Callbacks.after do
59
+ ActiveSupport::DescendantsTracker.clear
58
60
  ActiveSupport::Dependencies.clear
59
61
  end
60
62
  end
@@ -10,7 +10,7 @@ module Rails
10
10
  attr_accessor :allow_concurrency, :cache_classes, :cache_store,
11
11
  :encoding, :consider_all_requests_local, :dependency_loading,
12
12
  :filter_parameters, :log_level, :logger, :middleware,
13
- :plugins, :preload_frameworks, :reload_engines, :reload_plugins,
13
+ :plugins, :preload_frameworks, :reload_plugins,
14
14
  :secret_token, :serve_static_assets, :session_options,
15
15
  :time_zone, :whiny_nils
16
16
 
@@ -59,7 +59,7 @@ module Rails
59
59
  if File.exists?("#{root}/test/mocks/#{Rails.env}")
60
60
  ActiveSupport::Deprecation.warn "\"Rails.root/test/mocks/#{Rails.env}\" won't be added " <<
61
61
  "automatically to load paths anymore in future releases"
62
- paths.mocks_path "test/mocks", :load_path => true, :glob => Rails.env
62
+ paths.mocks_path "test/mocks", :autoload => true, :glob => Rails.env
63
63
  end
64
64
 
65
65
  paths
@@ -110,7 +110,7 @@ module Rails
110
110
 
111
111
  def colorize_logging=(val)
112
112
  @colorize_logging = val
113
- Rails::LogSubscriber.colorize_logging = val
113
+ ActiveSupport::LogSubscriber.colorize_logging = val
114
114
  self.generators.colorize_logging = val
115
115
  end
116
116
 
@@ -7,14 +7,14 @@ module Rails
7
7
  config.generators.templates.unshift(*paths.lib.templates.to_a)
8
8
  end
9
9
 
10
- initializer :ensure_load_once_paths_as_subset do
11
- extra = ActiveSupport::Dependencies.load_once_paths -
12
- ActiveSupport::Dependencies.load_paths
10
+ initializer :ensure_autoload_once_paths_as_subset do
11
+ extra = ActiveSupport::Dependencies.autoload_once_paths -
12
+ ActiveSupport::Dependencies.autoload_paths
13
13
 
14
14
  unless extra.empty?
15
15
  abort <<-end_error
16
- load_once_paths must be a subset of the load_paths.
17
- Extra items in load_once_paths: #{extra * ','}
16
+ autoload_once_paths must be a subset of the autoload_paths.
17
+ Extra items in autoload_once_paths: #{extra * ','}
18
18
  end_error
19
19
  end
20
20
  end
@@ -32,7 +32,7 @@ module Rails
32
32
  end
33
33
 
34
34
  initializer :build_middleware_stack do
35
- app
35
+ build_middleware_stack
36
36
  end
37
37
 
38
38
  initializer :eager_load! do
@@ -1,23 +1,5 @@
1
1
  require 'rbconfig'
2
-
3
- module Rails
4
- module ScriptRailsLoader
5
- RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
6
- SCRIPT_RAILS = File.join('script', 'rails')
7
-
8
- def self.exec_script_rails!
9
- cwd = Dir.pwd
10
- exec RUBY, SCRIPT_RAILS, *ARGV if File.exists?(SCRIPT_RAILS)
11
- Dir.chdir("..") do
12
- # Recurse in a chdir block: if the search fails we want to be sure
13
- # the application is generated in the original working directory.
14
- exec_script_rails! unless cwd == Dir.pwd
15
- end
16
- rescue SystemCallError
17
- # could not chdir, no problem just return
18
- end
19
- end
20
- end
2
+ require 'rails/script_rails_loader'
21
3
 
22
4
  Rails::ScriptRailsLoader.exec_script_rails!
23
5
 
@@ -13,27 +13,27 @@ command = aliases[command] || command
13
13
  case command
14
14
  when 'generate', 'destroy', 'plugin', 'benchmarker', 'profiler'
15
15
  require APP_PATH
16
- Rails::Application.require_environment!
16
+ Rails.application.require_environment!
17
17
  require "rails/commands/#{command}"
18
18
 
19
19
  when 'console'
20
20
  require 'rails/commands/console'
21
21
  require APP_PATH
22
- Rails::Application.require_environment!
23
- Rails::Console.start(Rails::Application)
22
+ Rails.application.require_environment!
23
+ Rails::Console.start(Rails.application)
24
24
 
25
25
  when 'server'
26
26
  require 'rails/commands/server'
27
27
  Rails::Server.new.tap { |server|
28
28
  require APP_PATH
29
- Dir.chdir(Rails::Application.root)
29
+ Dir.chdir(Rails.application.root)
30
30
  server.start
31
31
  }
32
32
 
33
33
  when 'dbconsole'
34
34
  require 'rails/commands/dbconsole'
35
35
  require APP_PATH
36
- Rails::DBConsole.start(Rails::Application)
36
+ Rails::DBConsole.start(Rails.application)
37
37
 
38
38
  when 'application', 'runner'
39
39
  require "rails/commands/#{command}"
@@ -4,7 +4,7 @@ if %w(--version -v).include? ARGV.first
4
4
  exit(0)
5
5
  end
6
6
 
7
- if ARGV.first != "new" || ARGV.empty?
7
+ if ARGV.first != "new"
8
8
  ARGV[0] = "--help"
9
9
  else
10
10
  ARGV.shift
@@ -23,10 +23,7 @@ module Rails
23
23
  opt.parse!(ARGV)
24
24
  end
25
25
 
26
- @app.initialize!
27
- require "rails/console/app"
28
- require "rails/console/sandbox" if options[:sandbox]
29
- require "rails/console/helpers"
26
+ @app.load_console(options[:sandbox])
30
27
 
31
28
  if options[:debugger]
32
29
  begin
File without changes
@@ -3,7 +3,7 @@
3
3
  # Installing plugins:
4
4
  #
5
5
  # $ rails plugin install continuous_builder asset_timestamping
6
- #
6
+ #
7
7
  # Specifying revisions:
8
8
  #
9
9
  # * Subversion revision is a single integer.
@@ -14,12 +14,11 @@
14
14
  # 'tag 1.8.0' (equivalent to 'refs/tags/1.8.0')
15
15
  #
16
16
  #
17
- # This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
17
+ # This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
18
18
  # and is licensed MIT: (http://www.opensource.org/licenses/mit-license.php)
19
19
 
20
20
  $verbose = false
21
21
 
22
-
23
22
  require 'open-uri'
24
23
  require 'fileutils'
25
24
  require 'tempfile'
@@ -40,18 +39,18 @@ class RailsEnvironment
40
39
  dir = File.dirname(dir)
41
40
  end
42
41
  end
43
-
42
+
44
43
  def self.default
45
44
  @default ||= find
46
45
  end
47
-
46
+
48
47
  def self.default=(rails_env)
49
48
  @default = rails_env
50
49
  end
51
-
50
+
52
51
  def install(name_uri_or_plugin)
53
52
  if name_uri_or_plugin.is_a? String
54
- if name_uri_or_plugin =~ /:\/\//
53
+ if name_uri_or_plugin =~ /:\/\//
55
54
  plugin = Plugin.new(name_uri_or_plugin)
56
55
  else
57
56
  plugin = Plugins[name_uri_or_plugin]
@@ -65,7 +64,7 @@ class RailsEnvironment
65
64
  puts "Plugin not found: #{name_uri_or_plugin}"
66
65
  end
67
66
  end
68
-
67
+
69
68
  def use_svn?
70
69
  require 'active_support/core_ext/kernel'
71
70
  silence_stderr {`svn --version` rescue nil}
@@ -97,7 +96,7 @@ class RailsEnvironment
97
96
  ext = `svn propget svn:externals "#{root}/vendor/plugins"`
98
97
  lines = ext.respond_to?(:lines) ? ext.lines : ext
99
98
  lines.reject{ |line| line.strip == '' }.map do |line|
100
- line.strip.split(/\s+/, 2)
99
+ line.strip.split(/\s+/, 2)
101
100
  end
102
101
  end
103
102
 
@@ -111,38 +110,37 @@ class RailsEnvironment
111
110
  system("svn propset -q svn:externals -F \"#{file.path}\" \"#{root}/vendor/plugins\"")
112
111
  end
113
112
  end
114
-
115
113
  end
116
114
 
117
115
  class Plugin
118
116
  attr_reader :name, :uri
119
-
117
+
120
118
  def initialize(uri, name = nil)
121
119
  @uri = uri
122
120
  guess_name(uri)
123
121
  end
124
-
122
+
125
123
  def self.find(name)
126
124
  new(name)
127
125
  end
128
-
126
+
129
127
  def to_s
130
128
  "#{@name.ljust(30)}#{@uri}"
131
129
  end
132
-
130
+
133
131
  def svn_url?
134
132
  @uri =~ /svn(?:\+ssh)?:\/\/*/
135
133
  end
136
-
134
+
137
135
  def git_url?
138
136
  @uri =~ /^git:\/\// || @uri =~ /\.git$/
139
137
  end
140
-
138
+
141
139
  def installed?
142
140
  File.directory?("#{rails_env.root}/vendor/plugins/#{name}") \
143
141
  or rails_env.externals.detect{ |name, repo| self.uri == repo }
144
142
  end
145
-
143
+
146
144
  def install(method=nil, options = {})
147
145
  method ||= rails_env.best_install_method?
148
146
  if :http == method
@@ -173,7 +171,7 @@ class Plugin
173
171
  if rails_env.use_externals?
174
172
  # clean up svn:externals
175
173
  externals = rails_env.externals
176
- externals.reject!{|n,u| name == n or name == u}
174
+ externals.reject!{|n, u| name == n or name == u}
177
175
  rails_env.externals = externals
178
176
  end
179
177
  end
@@ -192,7 +190,7 @@ class Plugin
192
190
  FileUtils.rm_rf tmp if svn_url?
193
191
  end
194
192
 
195
- private
193
+ private
196
194
 
197
195
  def run_install_hook
198
196
  install_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/install.rb"
@@ -207,11 +205,11 @@ class Plugin
207
205
  def install_using_export(options = {})
208
206
  svn_command :export, options
209
207
  end
210
-
208
+
211
209
  def install_using_checkout(options = {})
212
210
  svn_command :checkout, options
213
211
  end
214
-
212
+
215
213
  def install_using_externals(options = {})
216
214
  externals = rails_env.externals
217
215
  externals.push([@name, uri])
@@ -229,7 +227,7 @@ class Plugin
229
227
  fetcher.fetch
230
228
  end
231
229
  end
232
-
230
+
233
231
  def install_using_git(options = {})
234
232
  root = rails_env.root
235
233
  mkdir_p(install_path = "#{root}/vendor/plugins/#{name}")
@@ -268,7 +266,7 @@ class Plugin
268
266
  end
269
267
  @name.gsub!(/\.git$/, '') if @name =~ /\.git$/
270
268
  end
271
-
269
+
272
270
  def rails_env
273
271
  @rails_env || RailsEnvironment.default
274
272
  end
@@ -277,45 +275,44 @@ end
277
275
  # load default environment and parse arguments
278
276
  require 'optparse'
279
277
  module Commands
280
-
281
278
  class Plugin
282
279
  attr_reader :environment, :script_name, :sources
283
280
  def initialize
284
281
  @environment = RailsEnvironment.default
285
282
  @rails_root = RailsEnvironment.default.root
286
- @script_name = File.basename($0)
283
+ @script_name = File.basename($0)
287
284
  @sources = []
288
285
  end
289
-
286
+
290
287
  def environment=(value)
291
288
  @environment = value
292
289
  RailsEnvironment.default = value
293
290
  end
294
-
291
+
295
292
  def options
296
293
  OptionParser.new do |o|
297
294
  o.set_summary_indent(' ')
298
295
  o.banner = "Usage: plugin [OPTIONS] command"
299
296
  o.define_head "Rails plugin manager."
300
-
301
- o.separator ""
297
+
298
+ o.separator ""
302
299
  o.separator "GENERAL OPTIONS"
303
-
300
+
304
301
  o.on("-r", "--root=DIR", String,
305
302
  "Set an explicit rails app directory.",
306
303
  "Default: #{@rails_root}") { |rails_root| @rails_root = rails_root; self.environment = RailsEnvironment.new(@rails_root) }
307
304
  o.on("-s", "--source=URL1,URL2", Array,
308
305
  "Use the specified plugin repositories instead of the defaults.") { |sources| @sources = sources}
309
-
306
+
310
307
  o.on("-v", "--verbose", "Turn on verbose output.") { |verbose| $verbose = verbose }
311
308
  o.on("-h", "--help", "Show this help message.") { puts o; exit }
312
-
309
+
313
310
  o.separator ""
314
311
  o.separator "COMMANDS"
315
-
312
+
316
313
  o.separator " install Install plugin(s) from known repositories or URLs."
317
314
  o.separator " remove Uninstall plugins."
318
-
315
+
319
316
  o.separator ""
320
317
  o.separator "EXAMPLES"
321
318
  o.separator " Install a plugin:"
@@ -328,41 +325,41 @@ module Commands
328
325
  o.separator " #{@script_name} plugin install -x continuous_builder\n"
329
326
  end
330
327
  end
331
-
328
+
332
329
  def parse!(args=ARGV)
333
330
  general, sub = split_args(args)
334
331
  options.parse!(general)
335
-
332
+
336
333
  command = general.shift
337
334
  if command =~ /^(install|remove)$/
338
335
  command = Commands.const_get(command.capitalize).new(self)
339
336
  command.parse!(sub)
340
337
  else
341
- puts "Unknown command: #{command}"
338
+ puts "Unknown command: #{command}" unless command.blank?
342
339
  puts options
343
340
  exit 1
344
341
  end
345
342
  end
346
-
343
+
347
344
  def split_args(args)
348
345
  left = []
349
346
  left << args.shift while args[0] and args[0] =~ /^-/
350
347
  left << args.shift if args[0]
351
- return [left, args]
348
+ [left, args]
352
349
  end
353
-
350
+
354
351
  def self.parse!(args=ARGV)
355
352
  Plugin.new.parse!(args)
356
353
  end
357
354
  end
358
-
355
+
359
356
  class Install
360
357
  def initialize(base_command)
361
358
  @base_command = base_command
362
359
  @method = :http
363
360
  @options = { :quiet => false, :revision => nil, :force => false }
364
361
  end
365
-
362
+
366
363
  def options
367
364
  OptionParser.new do |o|
368
365
  o.set_summary_indent(' ')
@@ -370,8 +367,8 @@ module Commands
370
367
  o.define_head "Install one or more plugins."
371
368
  o.separator ""
372
369
  o.separator "Options:"
373
- o.on( "-x", "--externals",
374
- "Use svn:externals to grab the plugin.",
370
+ o.on( "-x", "--externals",
371
+ "Use svn:externals to grab the plugin.",
375
372
  "Enables plugin updates and plugin versioning.") { |v| @method = :externals }
376
373
  o.on( "-o", "--checkout",
377
374
  "Use svn checkout to grab the plugin.",
@@ -392,7 +389,7 @@ module Commands
392
389
  o.separator "a plugin repository."
393
390
  end
394
391
  end
395
-
392
+
396
393
  def determine_install_method
397
394
  best = @base_command.environment.best_install_method
398
395
  @method = :http if best == :http and @method == :export
@@ -410,9 +407,13 @@ module Commands
410
407
  end
411
408
  @method
412
409
  end
413
-
410
+
414
411
  def parse!(args)
415
412
  options.parse!(args)
413
+ if args.blank?
414
+ puts options
415
+ exit 1
416
+ end
416
417
  environment = @base_command.environment
417
418
  install_method = determine_install_method
418
419
  puts "Plugins will be installed using #{install_method}" if $verbose
@@ -430,7 +431,7 @@ module Commands
430
431
  def initialize(base_command)
431
432
  @base_command = base_command
432
433
  end
433
-
434
+
434
435
  def options
435
436
  OptionParser.new do |o|
436
437
  o.set_summary_indent(' ')
@@ -438,9 +439,13 @@ module Commands
438
439
  o.define_head "Remove plugins."
439
440
  end
440
441
  end
441
-
442
+
442
443
  def parse!(args)
443
444
  options.parse!(args)
445
+ if args.blank?
446
+ puts options
447
+ exit 1
448
+ end
444
449
  root = @base_command.environment.root
445
450
  args.each do |name|
446
451
  ::Plugin.new(name).uninstall
@@ -470,7 +475,7 @@ module Commands
470
475
  end
471
476
  end
472
477
  end
473
-
478
+
474
479
  class RecursiveHTTPFetcher
475
480
  attr_accessor :quiet
476
481
  def initialize(urls_to_fetch, level = 1, cwd = ".")
@@ -511,7 +516,7 @@ class RecursiveHTTPFetcher
511
516
  end
512
517
  links
513
518
  end
514
-
519
+
515
520
  def download(link)
516
521
  puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
517
522
  open(link) do |stream|
@@ -520,13 +525,13 @@ class RecursiveHTTPFetcher
520
525
  end
521
526
  end
522
527
  end
523
-
528
+
524
529
  def fetch(links = @urls_to_fetch)
525
530
  links.each do |l|
526
531
  (l =~ /\/$/ || links == @urls_to_fetch) ? fetch_dir(l) : download(l)
527
532
  end
528
533
  end
529
-
534
+
530
535
  def fetch_dir(url)
531
536
  @level += 1
532
537
  push_d(File.basename(url)) if @level > 0