rails 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails might be problematic. Click here for more details.

Files changed (177) hide show
  1. data/CHANGELOG +1020 -10
  2. data/MIT-LICENSE +1 -1
  3. data/README +110 -60
  4. data/Rakefile +74 -139
  5. data/bin/about +1 -1
  6. data/bin/console +1 -1
  7. data/bin/destroy +1 -1
  8. data/bin/generate +1 -1
  9. data/bin/performance/request +3 -0
  10. data/bin/plugin +1 -1
  11. data/bin/process/{spinner → inspector} +1 -1
  12. data/bin/rails +10 -12
  13. data/bin/runner +1 -1
  14. data/bin/server +1 -1
  15. data/{lib/rails_info.rb → builtin/rails_info/rails/info.rb} +33 -14
  16. data/builtin/rails_info/rails/info_controller.rb +9 -0
  17. data/builtin/rails_info/rails/info_helper.rb +2 -0
  18. data/builtin/rails_info/rails_info_controller.rb +2 -0
  19. data/configs/apache.conf +1 -1
  20. data/configs/databases/frontbase.yml +28 -0
  21. data/configs/databases/mysql.yml +54 -0
  22. data/configs/databases/oracle.yml +39 -0
  23. data/configs/databases/postgresql.yml +48 -0
  24. data/configs/databases/sqlite2.yml +16 -0
  25. data/configs/databases/sqlite3.yml +19 -0
  26. data/configs/initializers/inflections.rb +10 -0
  27. data/configs/initializers/mime_types.rb +5 -0
  28. data/configs/lighttpd.conf +29 -15
  29. data/configs/routes.rb +27 -11
  30. data/doc/README_FOR_APP +1 -1
  31. data/environments/boot.rb +103 -14
  32. data/environments/development.rb +5 -6
  33. data/environments/environment.rb +36 -30
  34. data/environments/production.rb +2 -3
  35. data/environments/test.rb +5 -2
  36. data/fresh_rakefile +2 -2
  37. data/helpers/application.rb +8 -2
  38. data/helpers/test_helper.rb +10 -0
  39. data/html/404.html +27 -5
  40. data/html/422.html +30 -0
  41. data/html/500.html +27 -5
  42. data/html/index.html +6 -6
  43. data/html/javascripts/application.js +2 -0
  44. data/html/javascripts/controls.js +532 -319
  45. data/html/javascripts/dragdrop.js +521 -133
  46. data/html/javascripts/effects.js +708 -442
  47. data/html/javascripts/prototype.js +3393 -953
  48. data/html/robots.txt +5 -1
  49. data/lib/code_statistics.rb +2 -2
  50. data/lib/commands/console.rb +18 -9
  51. data/lib/commands/performance/profiler.rb +25 -9
  52. data/lib/commands/performance/request.rb +6 -0
  53. data/lib/commands/plugin.rb +196 -96
  54. data/lib/commands/process/inspector.rb +68 -0
  55. data/lib/commands/process/reaper.rb +90 -71
  56. data/lib/commands/process/spawner.rb +188 -21
  57. data/lib/commands/process/spinner.rb +3 -3
  58. data/lib/commands/runner.rb +28 -7
  59. data/lib/commands/server.rb +20 -9
  60. data/lib/commands/servers/base.rb +31 -0
  61. data/lib/commands/servers/lighttpd.rb +60 -26
  62. data/lib/commands/servers/mongrel.rb +69 -0
  63. data/lib/commands/servers/webrick.rb +18 -11
  64. data/lib/console_app.rb +30 -0
  65. data/lib/console_sandbox.rb +2 -2
  66. data/lib/console_with_helpers.rb +26 -0
  67. data/lib/dispatcher.rb +3 -78
  68. data/lib/fcgi_handler.rb +98 -64
  69. data/lib/initializer.rb +323 -194
  70. data/lib/rails/plugin/loader.rb +150 -0
  71. data/lib/rails/plugin/locator.rb +78 -0
  72. data/lib/rails/plugin.rb +84 -0
  73. data/lib/{rails_version.rb → rails/version.rb} +1 -1
  74. data/lib/rails_generator/base.rb +85 -25
  75. data/lib/rails_generator/commands.rb +122 -40
  76. data/lib/rails_generator/generated_attribute.rb +42 -0
  77. data/lib/rails_generator/generators/applications/app/USAGE +0 -7
  78. data/lib/rails_generator/generators/applications/app/app_generator.rb +67 -28
  79. data/lib/rails_generator/generators/components/controller/USAGE +11 -12
  80. data/lib/rails_generator/generators/components/controller/controller_generator.rb +2 -3
  81. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +1 -11
  82. data/lib/rails_generator/generators/components/controller/templates/{view.rhtml → view.html.erb} +0 -0
  83. data/lib/rails_generator/generators/components/integration_test/USAGE +8 -0
  84. data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
  85. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
  86. data/lib/rails_generator/generators/components/mailer/USAGE +9 -11
  87. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +10 -8
  88. data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
  89. data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -3
  90. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +9 -25
  91. data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
  92. data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -3
  93. data/lib/rails_generator/generators/components/migration/USAGE +23 -8
  94. data/lib/rails_generator/generators/components/migration/migration_generator.rb +15 -2
  95. data/lib/rails_generator/generators/components/migration/templates/migration.rb +7 -3
  96. data/lib/rails_generator/generators/components/model/USAGE +21 -11
  97. data/lib/rails_generator/generators/components/model/model_generator.rb +28 -1
  98. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +18 -4
  99. data/lib/rails_generator/generators/components/model/templates/migration.rb +16 -0
  100. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +2 -4
  101. data/lib/rails_generator/generators/components/observer/USAGE +13 -0
  102. data/lib/rails_generator/generators/components/observer/observer_generator.rb +16 -0
  103. data/lib/rails_generator/generators/components/observer/templates/observer.rb +2 -0
  104. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +8 -0
  105. data/lib/rails_generator/generators/components/plugin/USAGE +10 -18
  106. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +6 -0
  107. data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
  108. data/lib/rails_generator/generators/components/plugin/templates/README +10 -1
  109. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +1 -1
  110. data/lib/rails_generator/generators/components/plugin/templates/USAGE +1 -1
  111. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -1
  112. data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
  113. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -1
  114. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +1 -1
  115. data/lib/rails_generator/generators/components/plugin/templates/uninstall.rb +1 -0
  116. data/lib/rails_generator/generators/components/resource/USAGE +23 -0
  117. data/lib/rails_generator/generators/components/resource/resource_generator.rb +74 -0
  118. data/lib/rails_generator/generators/components/resource/templates/controller.rb +2 -0
  119. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +8 -0
  120. data/lib/rails_generator/generators/components/resource/templates/helper.rb +2 -0
  121. data/lib/rails_generator/generators/components/scaffold/USAGE +24 -31
  122. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +45 -137
  123. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +65 -34
  124. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +23 -76
  125. data/lib/rails_generator/generators/components/scaffold/templates/layout.html.erb +17 -0
  126. data/lib/rails_generator/generators/components/scaffold/templates/style.css +5 -5
  127. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb +19 -0
  128. data/lib/rails_generator/generators/components/scaffold/templates/view_index.html.erb +24 -0
  129. data/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb +18 -0
  130. data/lib/rails_generator/generators/components/scaffold/templates/view_show.html.erb +10 -0
  131. data/lib/rails_generator/generators/components/session_migration/USAGE +6 -11
  132. data/lib/rails_generator/generators/components/session_migration/session_migration_generator.rb +7 -1
  133. data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +8 -7
  134. data/lib/rails_generator/lookup.rb +46 -12
  135. data/lib/rails_generator/options.rb +11 -8
  136. data/lib/rails_generator/scripts/destroy.rb +23 -0
  137. data/lib/rails_generator/scripts.rb +7 -4
  138. data/lib/rails_generator/secret_key_generator.rb +160 -0
  139. data/lib/rails_generator/spec.rb +1 -1
  140. data/lib/rails_generator.rb +1 -1
  141. data/lib/railties_path.rb +1 -1
  142. data/lib/ruby_version_check.rb +17 -0
  143. data/lib/source_annotation_extractor.rb +62 -0
  144. data/lib/tasks/annotations.rake +23 -0
  145. data/lib/tasks/databases.rake +328 -133
  146. data/lib/tasks/documentation.rake +72 -68
  147. data/lib/tasks/framework.rake +99 -58
  148. data/lib/tasks/log.rake +9 -0
  149. data/lib/tasks/misc.rake +2 -17
  150. data/lib/tasks/rails.rb +2 -2
  151. data/lib/tasks/routes.rake +17 -0
  152. data/lib/tasks/statistics.rake +10 -8
  153. data/lib/tasks/testing.rake +99 -31
  154. data/lib/tasks/tmp.rake +37 -0
  155. data/lib/test_help.rb +8 -5
  156. data/lib/webrick_server.rb +11 -16
  157. metadata +312 -272
  158. data/bin/breakpointer +0 -3
  159. data/builtin/controllers/rails_info_controller.rb +0 -11
  160. data/configs/database.yml +0 -85
  161. data/lib/binding_of_caller.rb +0 -85
  162. data/lib/breakpoint.rb +0 -523
  163. data/lib/breakpoint_client.rb +0 -196
  164. data/lib/commands/breakpointer.rb +0 -1
  165. data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +0 -3
  166. data/lib/rails_generator/generators/components/scaffold/templates/form_scaffolding.rhtml +0 -1
  167. data/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml +0 -13
  168. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +0 -9
  169. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +0 -27
  170. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +0 -8
  171. data/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml +0 -8
  172. data/lib/rails_generator/generators/components/web_service/USAGE +0 -28
  173. data/lib/rails_generator/generators/components/web_service/templates/api_definition.rb +0 -5
  174. data/lib/rails_generator/generators/components/web_service/templates/controller.rb +0 -8
  175. data/lib/rails_generator/generators/components/web_service/templates/functional_test.rb +0 -19
  176. data/lib/rails_generator/generators/components/web_service/web_service_generator.rb +0 -29
  177. data/lib/tasks/javascripts.rake +0 -6
data/html/robots.txt CHANGED
@@ -1 +1,5 @@
1
- # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -1,6 +1,6 @@
1
1
  class CodeStatistics #:nodoc:
2
2
 
3
- TEST_TYPES = ['Units', 'Functionals', 'Unit tests', 'Functional tests']
3
+ TEST_TYPES = %w(Units Functionals Unit\ tests Functional\ tests Integration\ tests)
4
4
 
5
5
  def initialize(*pairs)
6
6
  @pairs = pairs
@@ -83,7 +83,7 @@ class CodeStatistics #:nodoc:
83
83
  loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue loc_over_m = 0
84
84
 
85
85
  start = if TEST_TYPES.include? name
86
- "| #{name.ljust(18)} "
86
+ "| #{name.ljust(20)} "
87
87
  else
88
88
  "| #{name.ljust(20)} "
89
89
  end
@@ -1,23 +1,32 @@
1
- irb = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
1
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
2
2
 
3
3
  require 'optparse'
4
4
  options = { :sandbox => false, :irb => irb }
5
5
  OptionParser.new do |opt|
6
6
  opt.banner = "Usage: console [environment] [options]"
7
- opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |options[:sandbox]| }
8
- opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |options[:irb]| }
7
+ opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
8
+ opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
9
9
  opt.parse!(ARGV)
10
10
  end
11
11
 
12
12
  libs = " -r irb/completion"
13
- libs << " -r #{RAILS_ROOT}/config/environment"
13
+ libs << %( -r "#{RAILS_ROOT}/config/environment")
14
+ libs << " -r console_app"
14
15
  libs << " -r console_sandbox" if options[:sandbox]
16
+ libs << " -r console_with_helpers"
17
+
18
+ ENV['RAILS_ENV'] = case ARGV.first
19
+ when "p": "production"
20
+ when "d": "development"
21
+ when "t": "test"
22
+ else
23
+ ARGV.first || ENV['RAILS_ENV'] || 'development'
24
+ end
15
25
 
16
- ENV['RAILS_ENV'] = ARGV.first || 'development'
17
26
  if options[:sandbox]
18
- puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
19
- puts "Any modifications you make will be rolled back on exit."
27
+ puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails::VERSION::STRING})"
28
+ puts "Any modifications you make will be rolled back on exit"
20
29
  else
21
- puts "Loading #{ENV['RAILS_ENV']} environment."
30
+ puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails::VERSION::STRING})"
22
31
  end
23
- exec "#{options[:irb]} #{libs} --prompt-mode simple"
32
+ exec "#{options[:irb]} #{libs} --simple-prompt"
@@ -1,5 +1,5 @@
1
1
  if ARGV.empty?
2
- $stderr.puts "Usage: ./script/performance/profiler 'Person.expensive_method(10)' [times]"
2
+ $stderr.puts "Usage: ./script/performance/profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]"
3
3
  exit(1)
4
4
  end
5
5
 
@@ -16,14 +16,30 @@ end
16
16
 
17
17
  # Use the ruby-prof extension if available. Fall back to stdlib profiler.
18
18
  begin
19
- require 'prof'
20
- $stderr.puts 'Using the ruby-prof extension.'
21
- Prof.clock_mode = Prof::GETTIMEOFDAY
22
- Prof.start
23
- profile_me
24
- results = Prof.stop
25
- require 'rubyprof_ext'
26
- Prof.print_profile(results, $stderr)
19
+ begin
20
+ require "ruby-prof"
21
+ $stderr.puts 'Using the ruby-prof extension.'
22
+ RubyProf.clock_mode = RubyProf::WALL_TIME
23
+ RubyProf.start
24
+ profile_me
25
+ results = RubyProf.stop
26
+ if ARGV[2]
27
+ printer_class = RubyProf.const_get((ARGV[2] + "_printer").classify)
28
+ else
29
+ printer_class = RubyProf::FlatPrinter
30
+ end
31
+ printer = printer_class.new(results)
32
+ printer.print($stderr, 0)
33
+ rescue LoadError
34
+ require "prof"
35
+ $stderr.puts 'Using the old ruby-prof extension.'
36
+ Prof.clock_mode = Prof::GETTIMEOFDAY
37
+ Prof.start
38
+ profile_me
39
+ results = Prof.stop
40
+ require 'rubyprof_ext'
41
+ Prof.print_profile(results, $stderr)
42
+ end
27
43
  rescue LoadError
28
44
  require 'profiler'
29
45
  $stderr.puts 'Using the standard Ruby profiler.'
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require 'config/environment'
3
+ require 'application'
4
+ require 'action_controller/request_profiler'
5
+
6
+ ActionController::RequestProfiler.run(ARGV)
@@ -31,10 +31,13 @@
31
31
  # look like subversion repositories with plugins:
32
32
  # http://wiki.rubyonrails.org/rails/pages/Plugins
33
33
  #
34
+ # * Unless you specify that you want to use svn, script/plugin uses plain old
35
+ # HTTP for downloads. The following bullets are true if you specify
36
+ # that you want to use svn.
37
+ #
34
38
  # * If `vendor/plugins` is under subversion control, the script will
35
39
  # modify the svn:externals property and perform an update. You can
36
- # use normal subversion commands to keep the plugins up to date or
37
- # you can use the built in update command.
40
+ # use normal subversion commands to keep the plugins up to date.
38
41
  #
39
42
  # * Or, if `vendor/plugins` is not under subversion control, the
40
43
  # plugin is pulled via `svn checkout` or `svn export` but looks
@@ -58,7 +61,7 @@ class RailsEnvironment
58
61
  def initialize(dir)
59
62
  @root = dir
60
63
  end
61
-
64
+
62
65
  def self.find(dir=nil)
63
66
  dir ||= pwd
64
67
  while dir.length > 1
@@ -88,26 +91,27 @@ class RailsEnvironment
88
91
  unless plugin.nil?
89
92
  plugin.install
90
93
  else
91
- puts "plugin not found: #{name_uri_or_plugin}"
94
+ puts "Plugin not found: #{name_uri_or_plugin}"
92
95
  end
93
96
  end
94
97
 
95
98
  def use_svn?
96
- `svn --version` rescue nil
99
+ require 'active_support/core_ext/kernel'
100
+ silence_stderr {`svn --version` rescue nil}
97
101
  !$?.nil? && $?.success?
98
102
  end
99
103
 
100
104
  def use_externals?
101
- File.directory?("#{root}/vendor/plugins/.svn")
105
+ use_svn? && File.directory?("#{root}/vendor/plugins/.svn")
102
106
  end
103
-
107
+
104
108
  def use_checkout?
105
109
  # this is a bit of a guess. we assume that if the rails environment
106
- # is under subversion than they probably want the plugin checked out
110
+ # is under subversion then they probably want the plugin checked out
107
111
  # instead of exported. This can be overridden on the command line
108
112
  File.directory?("#{root}/.svn")
109
113
  end
110
-
114
+
111
115
  def best_install_method
112
116
  return :http unless use_svn?
113
117
  case
@@ -119,12 +123,12 @@ class RailsEnvironment
119
123
 
120
124
  def externals
121
125
  return [] unless use_externals?
122
- ext = `svn propget svn:externals #{root}/vendor/plugins`
126
+ ext = `svn propget svn:externals "#{root}/vendor/plugins"`
123
127
  ext.reject{ |line| line.strip == '' }.map do |line|
124
128
  line.strip.split(/\s+/, 2)
125
129
  end
126
130
  end
127
-
131
+
128
132
  def externals=(items)
129
133
  unless items.is_a? String
130
134
  items = items.map{|name,uri| "#{name.ljust(29)} #{uri.chomp('/')}"}.join("\n")
@@ -132,7 +136,7 @@ class RailsEnvironment
132
136
  Tempfile.open("svn-set-prop") do |file|
133
137
  file.write(items)
134
138
  file.flush
135
- system("svn propset -q svn:externals -F #{file.path} #{root}/vendor/plugins")
139
+ system("svn propset -q svn:externals -F \"#{file.path}\" \"#{root}/vendor/plugins\"")
136
140
  end
137
141
  end
138
142
 
@@ -146,49 +150,112 @@ class Plugin
146
150
  guess_name(uri)
147
151
  end
148
152
 
153
+ def self.find(name)
154
+ name =~ /\// ? new(name) : Repositories.instance.find_plugin(name)
155
+ end
156
+
149
157
  def to_s
150
158
  "#{@name.ljust(30)}#{@uri}"
151
159
  end
152
160
 
161
+ def svn_url?
162
+ @uri =~ /svn(?:\+ssh)?:\/\/*/
163
+ end
164
+
153
165
  def installed?
154
166
  File.directory?("#{rails_env.root}/vendor/plugins/#{name}") \
155
167
  or rails_env.externals.detect{ |name, repo| self.uri == repo }
156
168
  end
157
169
 
158
- def install(method=nil)
170
+ def install(method=nil, options = {})
159
171
  method ||= rails_env.best_install_method?
172
+ method = :export if method == :http and svn_url?
173
+
174
+ uninstall if installed? and options[:force]
175
+
160
176
  unless installed?
161
- send("install_using_#{method}")
177
+ send("install_using_#{method}", options)
178
+ run_install_hook
162
179
  else
163
- puts "already installed: #{name} (#{uri})"
180
+ puts "already installed: #{name} (#{uri}). pass --force to reinstall"
164
181
  end
165
182
  end
166
-
183
+
184
+ def uninstall
185
+ path = "#{rails_env.root}/vendor/plugins/#{name}"
186
+ if File.directory?(path)
187
+ puts "Removing 'vendor/plugins/#{name}'" if $verbose
188
+ run_uninstall_hook
189
+ rm_r path
190
+ else
191
+ puts "Plugin doesn't exist: #{path}"
192
+ end
193
+ # clean up svn:externals
194
+ externals = rails_env.externals
195
+ externals.reject!{|n,u| name == n or name == u}
196
+ rails_env.externals = externals
197
+ end
198
+
199
+ def info
200
+ tmp = "#{rails_env.root}/_tmp_about.yml"
201
+ if svn_url?
202
+ cmd = "svn export #{@uri} \"#{rails_env.root}/#{tmp}\""
203
+ puts cmd if $verbose
204
+ system(cmd)
205
+ end
206
+ open(svn_url? ? tmp : File.join(@uri, 'about.yml')) do |stream|
207
+ stream.read
208
+ end rescue "No about.yml found in #{uri}"
209
+ ensure
210
+ FileUtils.rm_rf tmp if svn_url?
211
+ end
212
+
167
213
  private
168
- def install_using_export
169
- root = rails_env.root
170
- mkdir_p "#{root}/vendor/plugins"
171
- system("svn export #{uri} #{root}/vendor/plugins/#{name}")
214
+
215
+ def run_install_hook
216
+ install_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/install.rb"
217
+ load install_hook_file if File.exists? install_hook_file
218
+ end
219
+
220
+ def run_uninstall_hook
221
+ uninstall_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/uninstall.rb"
222
+ load uninstall_hook_file if File.exists? uninstall_hook_file
223
+ end
224
+
225
+ def install_using_export(options = {})
226
+ svn_command :export, options
172
227
  end
173
228
 
174
- def install_using_checkout
175
- root = rails_env.root
176
- mkdir_p "#{root}/vendor/plugins"
177
- system("svn checkout #{uri} #{root}/vendor/plugins/#{name}")
229
+ def install_using_checkout(options = {})
230
+ svn_command :checkout, options
178
231
  end
179
232
 
180
- def install_using_externals
233
+ def install_using_externals(options = {})
181
234
  externals = rails_env.externals
182
235
  externals.push([@name, uri])
183
236
  rails_env.externals = externals
184
- install_using_checkout
237
+ install_using_checkout(options)
238
+ end
239
+
240
+ def install_using_http(options = {})
241
+ root = rails_env.root
242
+ mkdir_p "#{root}/vendor/plugins/#{@name}"
243
+ Dir.chdir "#{root}/vendor/plugins/#{@name}" do
244
+ puts "fetching from '#{uri}'" if $verbose
245
+ fetcher = RecursiveHTTPFetcher.new(uri, -1)
246
+ fetcher.quiet = true if options[:quiet]
247
+ fetcher.fetch
248
+ end
185
249
  end
186
250
 
187
- def install_using_http
251
+ def svn_command(cmd, options = {})
188
252
  root = rails_env.root
189
253
  mkdir_p "#{root}/vendor/plugins"
190
- Dir.chdir "#{root}/vendor/plugins"
191
- RecursiveHTTPFetcher.new(uri).fetch
254
+ base_cmd = "svn #{cmd} #{uri} \"#{root}/vendor/plugins/#{name}\""
255
+ base_cmd += ' -q' if options[:quiet] and not $verbose
256
+ base_cmd += " -r #{options[:revision]}" if options[:revision]
257
+ puts base_cmd if $verbose
258
+ system(base_cmd)
192
259
  end
193
260
 
194
261
  def guess_name(url)
@@ -239,7 +306,6 @@ class Repositories
239
306
  return plugin if plugin.name == name
240
307
  end
241
308
  end
242
-
243
309
  return nil
244
310
  end
245
311
 
@@ -298,8 +364,7 @@ class Repository
298
364
  attr_reader :uri, :plugins
299
365
 
300
366
  def initialize(uri)
301
- uri << "/" unless uri =~ /\/$/
302
- @uri = uri
367
+ @uri = uri.chomp('/') << "/"
303
368
  @plugins = nil
304
369
  end
305
370
 
@@ -310,7 +375,7 @@ class Repository
310
375
  puts index
311
376
  end
312
377
 
313
- @plugins = index.split(/\n/).reject{ |line| line !~ /\/$/ }
378
+ @plugins = index.reject{ |line| line !~ /\/$/ }
314
379
  @plugins.map! { |name| Plugin.new(File.join(@uri, name), name) }
315
380
  end
316
381
 
@@ -323,7 +388,7 @@ class Repository
323
388
 
324
389
  private
325
390
  def index
326
- @index ||= `svn ls #{@uri}`
391
+ @index ||= RecursiveHTTPFetcher.new(@uri).ls
327
392
  end
328
393
  end
329
394
 
@@ -406,12 +471,12 @@ module Commands
406
471
  options.parse!(general)
407
472
 
408
473
  command = general.shift
409
- if command =~ /^(list|discover|install|source|unsource|sources|remove|update)$/
474
+ if command =~ /^(list|discover|install|source|unsource|sources|remove|update|info)$/
410
475
  command = Commands.const_get(command.capitalize).new(self)
411
476
  command.parse!(sub)
412
477
  else
413
478
  puts "Unknown command: #{command}"
414
- puts "Try: #{$0} --help"
479
+ puts options
415
480
  exit 1
416
481
  end
417
482
  end
@@ -435,7 +500,6 @@ module Commands
435
500
  @sources = []
436
501
  @local = false
437
502
  @remote = true
438
- @details = false
439
503
  end
440
504
 
441
505
  def options
@@ -451,10 +515,8 @@ module Commands
451
515
  o.on( "--local",
452
516
  "List locally installed plugins.") {|@local| @remote = false}
453
517
  o.on( "--remote",
454
- "List remotely availabled plugins. This is the default behavior",
518
+ "List remotely available plugins. This is the default behavior",
455
519
  "unless --local is provided.") {|@remote|}
456
- o.on( "-l", "--long",
457
- "Long listing / details about each plugin.") {|@details|}
458
520
  end
459
521
  end
460
522
 
@@ -469,14 +531,12 @@ module Commands
469
531
  @sources.map{|r| r.plugins}.flatten.each do |plugin|
470
532
  if @local or !plugin.installed?
471
533
  puts plugin.to_s
472
- system "svn info #{plugin.uri}" if @details
473
534
  end
474
535
  end
475
536
  else
476
537
  cd "#{@base_command.environment.root}/vendor/plugins"
477
538
  Dir["*"].select{|p| File.directory?(p)}.each do |name|
478
539
  puts name
479
- system "svn info #{name}" if @details
480
540
  end
481
541
  end
482
542
  end
@@ -518,8 +578,8 @@ module Commands
518
578
  def options
519
579
  OptionParser.new do |o|
520
580
  o.set_summary_indent(' ')
521
- o.banner = "Usage: #{@base_command.script_name} source REPOSITORY"
522
- o.define_head "Add a new repository."
581
+ o.banner = "Usage: #{@base_command.script_name} source REPOSITORY [REPOSITORY [REPOSITORY]...]"
582
+ o.define_head "Add new repositories to the default search list."
523
583
  end
524
584
  end
525
585
 
@@ -625,13 +685,17 @@ module Commands
625
685
  puts "Scraping #{uri}" if $verbose
626
686
  dupes = []
627
687
  content = open(uri).each do |line|
628
- if line =~ /<a[^>]*href=['"]([^'"]*)['"]/
629
- uri = $1
630
- if uri =~ /\/plugins\// and uri !~ /\/browser\//
631
- uri = extract_repository_uri(uri)
632
- yield uri unless dupes.include?(uri) or Repositories.instance.exist?(uri)
633
- dupes << uri
688
+ begin
689
+ if line =~ /<a[^>]*href=['"]([^'"]*)['"]/ || line =~ /(svn:\/\/[^<|\n]*)/
690
+ uri = $1
691
+ if uri =~ /^\w+:\/\// && uri =~ /\/plugins\// && uri !~ /\/browser\// && uri !~ /^http:\/\/wiki\.rubyonrails/ && uri !~ /http:\/\/instiki/
692
+ uri = extract_repository_uri(uri)
693
+ yield uri unless dupes.include?(uri) || Repositories.instance.exist?(uri)
694
+ dupes << uri
695
+ end
634
696
  end
697
+ rescue
698
+ puts "Problems scraping '#{uri}': #{$!.to_s}"
635
699
  end
636
700
  end
637
701
  end
@@ -644,7 +708,8 @@ module Commands
644
708
  class Install
645
709
  def initialize(base_command)
646
710
  @base_command = base_command
647
- @method = :export
711
+ @method = :http
712
+ @options = { :quiet => false, :revision => nil, :force => false }
648
713
  end
649
714
 
650
715
  def options
@@ -660,6 +725,14 @@ module Commands
660
725
  o.on( "-o", "--checkout",
661
726
  "Use svn checkout to grab the plugin.",
662
727
  "Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
728
+ o.on( "-q", "--quiet",
729
+ "Suppresses the output from installation.",
730
+ "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
731
+ o.on( "-r REVISION", "--revision REVISION",
732
+ "Checks out the given revision from subversion.",
733
+ "Ignored if subversion is not used.") { |v| @options[:revision] = v }
734
+ o.on( "-f", "--force",
735
+ "Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
663
736
  o.separator ""
664
737
  o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
665
738
  o.separator "a plugin repository."
@@ -672,8 +745,8 @@ module Commands
672
745
  case
673
746
  when (best == :http and @method != :http)
674
747
  msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
675
- when (best == :export and (@method != :export and method != :http))
676
- msg = "Cannot install using #{requested} because this project is not under subversion."
748
+ when (best == :export and (@method != :export and @method != :http))
749
+ msg = "Cannot install using #{@method} because this project is not under subversion."
677
750
  when (best != :externals and @method == :externals)
678
751
  msg = "Cannot install using externals because vendor/plugins is not under subversion."
679
752
  end
@@ -689,23 +762,51 @@ module Commands
689
762
  environment = @base_command.environment
690
763
  install_method = determine_install_method
691
764
  puts "Plugins will be installed using #{install_method}" if $verbose
692
- args.each do |name|
693
- if name =~ /\// then
694
- ::Plugin.new(name).install(install_method)
765
+ args.each do |name|
766
+ ::Plugin.find(name).install(install_method, @options)
767
+ end
768
+ rescue StandardError => e
769
+ puts "Plugin not found: #{args.inspect}"
770
+ puts e.inspect if $verbose
771
+ exit 1
772
+ end
773
+ end
774
+
775
+ class Update
776
+ def initialize(base_command)
777
+ @base_command = base_command
778
+ end
779
+
780
+ def options
781
+ OptionParser.new do |o|
782
+ o.set_summary_indent(' ')
783
+ o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
784
+ o.on( "-r REVISION", "--revision REVISION",
785
+ "Checks out the given revision from subversion.",
786
+ "Ignored if subversion is not used.") { |v| @revision = v }
787
+ o.define_head "Update plugins."
788
+ end
789
+ end
790
+
791
+ def parse!(args)
792
+ options.parse!(args)
793
+ root = @base_command.environment.root
794
+ cd root
795
+ args = Dir["vendor/plugins/*"].map do |f|
796
+ File.directory?("#{f}/.svn") ? File.basename(f) : nil
797
+ end.compact if args.empty?
798
+ cd "vendor/plugins"
799
+ args.each do |name|
800
+ if File.directory?(name)
801
+ puts "Updating plugin: #{name}"
802
+ system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}")
695
803
  else
696
- plugin = Repositories.instance.find_plugin(name)
697
- unless plugin.nil?
698
- plugin.install(install_method)
699
- else
700
- puts "Plugin not found: #{name}"
701
- exit 1
702
- end
804
+ puts "Plugin doesn't exist: #{name}"
703
805
  end
704
806
  end
705
807
  end
706
808
  end
707
809
 
708
-
709
810
  class Remove
710
811
  def initialize(base_command)
711
812
  @base_command = base_command
@@ -723,57 +824,53 @@ module Commands
723
824
  options.parse!(args)
724
825
  root = @base_command.environment.root
725
826
  args.each do |name|
726
- path = "#{root}/vendor/plugins/#{name}"
727
- if File.directory?(path)
728
- rm_r path
729
- else
730
- puts "Plugin doesn't exist: #{path}"
731
- end
732
- # clean up svn:externals
733
- externals = @base_command.environment.externals
734
- externals.reject!{|n,u| name == n or name == u}
735
- @base_command.environment.externals = externals
827
+ ::Plugin.new(name).uninstall
736
828
  end
737
829
  end
738
830
  end
739
831
 
740
- class Update
832
+ class Info
741
833
  def initialize(base_command)
742
834
  @base_command = base_command
743
835
  end
744
-
836
+
745
837
  def options
746
838
  OptionParser.new do |o|
747
839
  o.set_summary_indent(' ')
748
- o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
749
- o.define_head "Update plugins."
840
+ o.banner = "Usage: #{@base_command.script_name} info name [name]..."
841
+ o.define_head "Shows plugin info at {url}/about.yml."
750
842
  end
751
843
  end
752
-
844
+
753
845
  def parse!(args)
754
846
  options.parse!(args)
755
- root = @base_command.environment.root
756
- args = Dir["#{root}/vendor/plugins/*"].map do |f|
757
- File.directory?("#{f}/.svn") ? File.basename(f) : nil
758
- end.compact if args.empty?
759
- cd "#{root}/vendor/plugins"
760
847
  args.each do |name|
761
- if File.directory?(name)
762
- puts "Updating plugin: #{name}"
763
- system("svn #{$verbose ? '' : '-q'} up #{name}")
764
- else
765
- puts "Plugin doesn't exist: #{name}"
766
- end
848
+ puts ::Plugin.find(name).info
849
+ puts
767
850
  end
768
851
  end
769
852
  end
770
-
771
853
  end
772
854
 
773
855
  class RecursiveHTTPFetcher
774
- def initialize(urls_to_fetch, cwd = ".")
856
+ attr_accessor :quiet
857
+ def initialize(urls_to_fetch, level = 1, cwd = ".")
858
+ @level = level
775
859
  @cwd = cwd
776
860
  @urls_to_fetch = urls_to_fetch.to_a
861
+ @quiet = false
862
+ end
863
+
864
+ def ls
865
+ @urls_to_fetch.collect do |url|
866
+ if url =~ /^svn:\/\/.*/
867
+ `svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil
868
+ else
869
+ open(url) do |stream|
870
+ links("", stream.read)
871
+ end rescue nil
872
+ end
873
+ end.flatten
777
874
  end
778
875
 
779
876
  def push_d(dir)
@@ -789,14 +886,15 @@ class RecursiveHTTPFetcher
789
886
  links = []
790
887
  contents.scan(/href\s*=\s*\"*[^\">]*/i) do |link|
791
888
  link = link.sub(/href="/i, "")
792
- next if link =~ /^http/i || link =~ /^\./
889
+ next if link =~ /svnindex.xsl$/
890
+ next if link =~ /^(\w*:|)\/\// || link =~ /^\./
793
891
  links << File.join(base_url, link)
794
892
  end
795
893
  links
796
894
  end
797
895
 
798
896
  def download(link)
799
- puts "+ #{File.join(@cwd, File.basename(link))}"
897
+ puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
800
898
  open(link) do |stream|
801
899
  File.open(File.join(@cwd, File.basename(link)), "wb") do |file|
802
900
  file.write(stream.read)
@@ -811,12 +909,14 @@ class RecursiveHTTPFetcher
811
909
  end
812
910
 
813
911
  def fetch_dir(url)
814
- push_d(File.basename(url))
912
+ @level += 1
913
+ push_d(File.basename(url)) if @level > 0
815
914
  open(url) do |stream|
816
915
  contents = stream.read
817
916
  fetch(links(url, contents))
818
917
  end
819
- pop_d
918
+ pop_d if @level > 0
919
+ @level -= 1
820
920
  end
821
921
  end
822
922