rapt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+
2
+ = 0.1.0
3
+
4
+ * Converted from original Rails plugin code
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2006 Geoffrey Grosenbach boss@topfunky.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,4 @@
1
+ Rapt
2
+ ====
3
+
4
+ A plugin manager for Ruby on Rails.
@@ -0,0 +1,74 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ $:.unshift(File.dirname(__FILE__) + "/lib/commands")
10
+ require 'plugin'
11
+
12
+ PKG_NAME = 'rapt'
13
+ PKG_VERSION = '0.1.0'
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+
16
+ RELEASE_NAME = "REL #{PKG_VERSION}"
17
+
18
+ RUBY_FORGE_PROJECT = PKG_NAME
19
+ RUBY_FORGE_USER = "topfunky"
20
+
21
+ desc "Default Task"
22
+ task :default => :test
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.pattern = 'test/**/*_test.rb'
27
+ t.verbose = true
28
+ end
29
+
30
+ # Genereate the RDoc documentation
31
+ Rake::RDocTask.new { |rdoc|
32
+ rdoc.rdoc_dir = 'doc'
33
+ rdoc.title = "Rapt -- Rails plugin manager"
34
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
35
+ rdoc.rdoc_files.include('README', 'CHANGELOG')
36
+ rdoc.rdoc_files.include('lib/plugin.rb')
37
+ rdoc.rdoc_files.include('lib/plugin/*.rb')
38
+ }
39
+
40
+ # Create compressed packages
41
+ spec = Gem::Specification.new do |s|
42
+ s.platform = Gem::Platform::RUBY
43
+ s.name = PKG_NAME
44
+ s.summary = "Rails plugin manager."
45
+ s.description = %q{Install, remove, and discover new plugins for your Ruby on Rails app.}
46
+ s.version = PKG_VERSION
47
+
48
+ s.authors = ["Ryan Tomayko", "Geoffrey Grosenbach"]
49
+ s.email = "boss@topfunky.com"
50
+ s.rubyforge_project = RUBY_FORGE_PROJECT
51
+ s.homepage = "http://nubyonrails.com/pages/rapt"
52
+
53
+ s.has_rdoc = false
54
+ s.requirements << 'none'
55
+ s.require_path = 'lib'
56
+
57
+ s.files = [ "Rakefile", "README", "CHANGELOG", "MIT-LICENSE" ]
58
+ %w(bin lib test).each do |dir|
59
+ s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
60
+ end
61
+ s.executables = ["rapt"]
62
+ end
63
+
64
+ Rake::GemPackageTask.new(spec) do |p|
65
+ p.gem_spec = spec
66
+ p.need_tar = true
67
+ p.need_zip = true
68
+ end
69
+
70
+ # desc "Publish the API documentation"
71
+ # task :pgem => [:package] do
72
+ # Rake::SshFilePublisher.new("boss@topfunky.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
73
+ # end
74
+
@@ -0,0 +1,6 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require "commands/plugin"
4
+
5
+ Commands::Plugin.parse!
6
+
@@ -0,0 +1,65 @@
1
+ # Rails Plugin Manager.
2
+ #
3
+ # Listing available plugins:
4
+ #
5
+ # $ ./script/plugin list
6
+ # continuous_builder http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder
7
+ # asset_timestamping http://svn.aviditybytes.com/rails/plugins/asset_timestamping
8
+ # enumerations_mixin http://svn.protocool.com/rails/plugins/enumerations_mixin/trunk
9
+ # calculations http://techno-weenie.net/svn/projects/calculations/
10
+ # ...
11
+ #
12
+ # Installing plugins:
13
+ #
14
+ # $ ./script/plugin install continuous_builder asset_timestamping
15
+ #
16
+ # Finding Repositories:
17
+ #
18
+ # $ ./script/plugin discover
19
+ #
20
+ # Adding Repositories:
21
+ #
22
+ # $ ./script/plugin source http://svn.protocool.com/rails/plugins/
23
+ #
24
+ # How it works:
25
+ #
26
+ # * Maintains a list of subversion repositories that are assumed to have
27
+ # a plugin directory structure. Manage them with the (source, unsource,
28
+ # and sources commands)
29
+ #
30
+ # * The discover command scrapes the following page for things that
31
+ # look like subversion repositories with plugins:
32
+ # http://wiki.rubyonrails.org/rails/pages/Plugins
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
+ #
38
+ # * If `vendor/plugins` is under subversion control, the script will
39
+ # modify the svn:externals property and perform an update. You can
40
+ # use normal subversion commands to keep the plugins up to date.
41
+ #
42
+ # * Or, if `vendor/plugins` is not under subversion control, the
43
+ # plugin is pulled via `svn checkout` or `svn export` but looks
44
+ # exactly the same.
45
+ #
46
+ # This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
47
+ # and is licensed MIT: (http://www.opensource.org/licenses/mit-license.php)
48
+
49
+ $verbose = false
50
+
51
+ require 'open-uri'
52
+ require 'fileutils'
53
+ require 'tempfile'
54
+
55
+ include FileUtils
56
+
57
+ require File.dirname(__FILE__) + '/plugin/rails_environment'
58
+ require File.dirname(__FILE__) + '/plugin/plugin'
59
+ require File.dirname(__FILE__) + '/plugin/repositories'
60
+ require File.dirname(__FILE__) + '/plugin/repository'
61
+ require File.dirname(__FILE__) + '/plugin/commands'
62
+ require File.dirname(__FILE__) + '/plugin/recursive_http_fetcher'
63
+
64
+
65
+
@@ -0,0 +1,486 @@
1
+
2
+ # Load default environment and parse arguments
3
+ require 'optparse'
4
+ module Commands
5
+
6
+ class Plugin
7
+ attr_reader :environment, :script_name, :sources
8
+ def initialize
9
+ @environment = RailsEnvironment.default
10
+ @rails_root = RailsEnvironment.default.root
11
+ @script_name = File.basename($0)
12
+ @sources = []
13
+ end
14
+
15
+ def environment=(value)
16
+ @environment = value
17
+ RailsEnvironment.default = value
18
+ end
19
+
20
+ def options
21
+ OptionParser.new do |o|
22
+ o.set_summary_indent(' ')
23
+ o.banner = "Usage: #{@script_name} [OPTIONS] command"
24
+ o.define_head "Rails plugin manager."
25
+
26
+ o.separator ""
27
+ o.separator "GENERAL OPTIONS"
28
+
29
+ o.on("-r", "--root=DIR", String,
30
+ "Set an explicit rails app directory.",
31
+ "Default: #{@rails_root}") { |@rails_root| self.environment = RailsEnvironment.new(@rails_root) }
32
+ o.on("-s", "--source=URL1,URL2", Array,
33
+ "Use the specified plugin repositories instead of the defaults.") { |@sources|}
34
+
35
+ o.on("-v", "--verbose", "Turn on verbose output.") { |$verbose| }
36
+ o.on("-h", "--help", "Show this help message.") { puts o; exit }
37
+
38
+ o.separator ""
39
+ o.separator "COMMANDS"
40
+
41
+ o.separator " discover Discover plugin repositories."
42
+ o.separator " list List available plugins."
43
+ o.separator " about Show basic info about a plugin."
44
+ o.separator " install Install plugin(s) from known repositories or URLs."
45
+ o.separator " update Update installed plugins."
46
+ o.separator " remove Uninstall plugins."
47
+ o.separator " source Add a plugin source repository."
48
+ o.separator " unsource Remove a plugin repository."
49
+ o.separator " sources List currently configured plugin repositories."
50
+
51
+ o.separator ""
52
+ o.separator "EXAMPLES"
53
+ o.separator " Install a plugin:"
54
+ o.separator " #{@script_name} install continuous_builder\n"
55
+ o.separator " Install a plugin from a subversion URL:"
56
+ o.separator " #{@script_name} install http://dev.rubyonrails.com/svn/rails/plugins/continuous_builder\n"
57
+ o.separator " Install a plugin and add a svn:externals entry to vendor/plugins"
58
+ o.separator " #{@script_name} install -x continuous_builder\n"
59
+ o.separator " Show information about the acts_as_chunky_bacon plugin:"
60
+ o.separator " #{@script_name} about acts_as_chunky_bacon\n"
61
+ o.separator " List all available plugins:"
62
+ o.separator " #{@script_name} list\n"
63
+ o.separator " List plugins in the specified repository:"
64
+ o.separator " #{@script_name} list --source=http://dev.rubyonrails.com/svn/rails/plugins/\n"
65
+ o.separator " Discover and prompt to add new repositories:"
66
+ o.separator " #{@script_name} discover\n"
67
+ o.separator " Discover new repositories but just list them, don't add anything:"
68
+ o.separator " #{@script_name} discover -l\n"
69
+ o.separator " Add a new repository to the source list:"
70
+ o.separator " #{@script_name} source http://dev.rubyonrails.com/svn/rails/plugins/\n"
71
+ o.separator " Remove a repository from the source list:"
72
+ o.separator " #{@script_name} unsource http://dev.rubyonrails.com/svn/rails/plugins/\n"
73
+ o.separator " Show currently configured repositories:"
74
+ o.separator " #{@script_name} sources\n"
75
+ o.separator " Show the options for the list command:"
76
+ o.separator " #{@script_name} list -h\n"
77
+ end
78
+ end
79
+
80
+ def parse!(args=ARGV)
81
+ general, sub = split_args(args)
82
+ options.parse!(general)
83
+
84
+ command = general.shift
85
+ if command =~ /^(list|discover|install|source|unsource|sources|remove|update|about)$/
86
+ command = Commands.const_get(command.capitalize).new(self)
87
+ command.parse!(sub)
88
+ else
89
+ puts "Unknown command: #{command}"
90
+ puts options
91
+ exit 1
92
+ end
93
+ end
94
+
95
+ def split_args(args)
96
+ left = []
97
+ left << args.shift while args[0] and args[0] =~ /^-/
98
+ left << args.shift if args[0]
99
+ return [left, args]
100
+ end
101
+
102
+ def self.parse!(args=ARGV)
103
+ Plugin.new.parse!(args)
104
+ end
105
+ end
106
+
107
+
108
+ class List
109
+ def initialize(base_command)
110
+ @base_command = base_command
111
+ @sources = []
112
+ @local = false
113
+ @remote = false
114
+ @cached = true
115
+ end
116
+
117
+ def options
118
+ OptionParser.new do |o|
119
+ o.set_summary_indent(' ')
120
+ o.banner = "Usage: #{@base_command.script_name} list [OPTIONS] [PATTERN]"
121
+ o.define_head "List available plugins."
122
+ o.separator ""
123
+ o.separator "Options:"
124
+ o.separator ""
125
+ o.on( "-s", "--source=URL1,URL2", Array,
126
+ "Use the specified plugin repositories.") {|@sources| @remote = true; @cached = false }
127
+ o.on( "--local",
128
+ "List locally installed plugins.") {|@local| @cached = false }
129
+ o.on( "--cached",
130
+ "List the known plugins in the local sources cache. This is the default behavior.") {|@cached|}
131
+ o.on( "--remote",
132
+ "List remotely available plugins.",
133
+ "unless --local is provided.") {|@remote| @cached = false }
134
+ end
135
+ end
136
+
137
+ def parse!(args)
138
+ options.order!(args)
139
+ unless @sources.empty?
140
+ @sources.map!{ |uri| Repository.new(uri) }
141
+ else
142
+ @sources = Repositories.instance.all
143
+ end
144
+ if @remote
145
+ @sources.map{|r| r.plugins}.flatten.each do |plugin|
146
+ if @local or !plugin.installed?
147
+ puts plugin.to_s
148
+ end
149
+ end
150
+ elsif @cached
151
+ Repositories.instance.cached_plugins.each { |plugin| puts plugin.to_s }
152
+ puts "\nThere are #{Repositories.instance.plugin_count} plugins in the source cache.\n\n"
153
+ else
154
+ cd "#{@base_command.environment.root}/vendor/plugins"
155
+ Dir["*"].select{|p| File.directory?(p)}.each do |name|
156
+ puts name
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+
163
+ class Sources
164
+ def initialize(base_command)
165
+ @base_command = base_command
166
+ end
167
+
168
+ def options
169
+ OptionParser.new do |o|
170
+ o.set_summary_indent(' ')
171
+ o.banner = "Usage: #{@base_command.script_name} sources [OPTIONS] [PATTERN]"
172
+ o.define_head "List configured plugin repositories."
173
+ o.separator ""
174
+ o.separator "Options:"
175
+ o.separator ""
176
+ o.on( "-c", "--check",
177
+ "Report status of repository.") { |@sources| } # TODO Implement
178
+ o.on( "-r", "--refresh",
179
+ "Refresh the source cache with the list of plugins available in each repository.") { refresh }
180
+ end
181
+ end
182
+
183
+ def parse!(args)
184
+ options.parse!(args)
185
+ Repositories.each do |repo|
186
+ puts repo.uri
187
+ end
188
+ end
189
+
190
+ def refresh
191
+ puts "Refreshing source cache (may take a few minutes)..."
192
+ repositories = Repositories.instance
193
+ repositories.refresh!
194
+ repositories.save
195
+ end
196
+ end
197
+
198
+
199
+ class Source
200
+ def initialize(base_command)
201
+ @base_command = base_command
202
+ end
203
+
204
+ def options
205
+ OptionParser.new do |o|
206
+ o.set_summary_indent(' ')
207
+ o.banner = "Usage: #{@base_command.script_name} source REPOSITORY"
208
+ o.define_head "Add a new repository."
209
+ end
210
+ end
211
+
212
+ def parse!(args)
213
+ options.parse!(args)
214
+ count = 0
215
+ args.each do |uri|
216
+ if Repositories.instance.add(uri)
217
+ puts "added: #{uri.ljust(50)}" if $verbose
218
+ count += 1
219
+ else
220
+ puts "failed: #{uri.ljust(50)}"
221
+ end
222
+ end
223
+ Repositories.instance.save
224
+ puts "Added #{count} repositories."
225
+ end
226
+ end
227
+
228
+
229
+ class Unsource
230
+ def initialize(base_command)
231
+ @base_command = base_command
232
+ end
233
+
234
+ def options
235
+ OptionParser.new do |o|
236
+ o.set_summary_indent(' ')
237
+ o.banner = "Usage: #{@base_command.script_name} source URI [URI [URI]...]"
238
+ o.define_head "Remove repositories from the default search list."
239
+ o.separator ""
240
+ o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
241
+ end
242
+ end
243
+
244
+ def parse!(args)
245
+ options.parse!(args)
246
+ count = 0
247
+ args.each do |uri|
248
+ if Repositories.instance.remove(uri)
249
+ count += 1
250
+ puts "removed: #{uri.ljust(50)}"
251
+ else
252
+ puts "failed: #{uri.ljust(50)}"
253
+ end
254
+ end
255
+ Repositories.instance.save
256
+ puts "Removed #{count} repositories."
257
+ end
258
+ end
259
+
260
+
261
+ class Discover
262
+ def initialize(base_command)
263
+ @base_command = base_command
264
+ @list = false
265
+ @prompt = true
266
+ end
267
+
268
+ def options
269
+ OptionParser.new do |o|
270
+ o.set_summary_indent(' ')
271
+ o.banner = "Usage: #{@base_command.script_name} discover URI [URI [URI]...]"
272
+ o.define_head "Discover repositories referenced on a page."
273
+ o.separator ""
274
+ o.separator "Options:"
275
+ o.separator ""
276
+ o.on( "-l", "--list",
277
+ "List but don't prompt or add discovered repositories.") { |@list| @prompt = !@list }
278
+ o.on( "-n", "--no-prompt",
279
+ "Add all new repositories without prompting.") { |v| @prompt = false }
280
+ end
281
+ end
282
+
283
+ def parse!(args)
284
+ options.parse!(args)
285
+ args = ['http://wiki.rubyonrails.org/rails/pages/Plugins', 'http://agilewebdevelopment.com/plugins/scrape'] if args.empty?
286
+ args.each do |uri|
287
+ scrape(uri) do |repo_uri|
288
+ catch(:next_uri) do
289
+ if @prompt
290
+ begin
291
+ $stdout.print "Add #{repo_uri}? [Y/n] "
292
+ throw :next_uri if $stdin.gets !~ /^y?$/i
293
+ rescue Interrupt
294
+ $stdout.puts
295
+ exit 1
296
+ end
297
+ elsif @list
298
+ puts repo_uri
299
+ throw :next_uri
300
+ end
301
+ Repositories.instance.add(repo_uri)
302
+ puts "discovered: #{repo_uri}" if $verbose or !@prompt
303
+ end
304
+ end
305
+ end
306
+ Repositories.instance.save
307
+ end
308
+
309
+ def scrape(uri)
310
+ require 'open-uri'
311
+ puts "Scraping #{uri}" if $verbose
312
+ dupes = []
313
+ content = open(uri).each do |line|
314
+ begin
315
+ if line =~ /<a[^>]*href=['"]([^'"]*)['"]/ || line =~ /(svn:\/\/[^<|\n]*)/
316
+ uri = $1
317
+ if uri =~ /^\w+:\/\// && uri =~ /\/plugins\// && uri !~ /\/browser\// && uri !~ /^http:\/\/wiki\.rubyonrails/ && uri !~ /http:\/\/instiki/
318
+ uri = extract_repository_uri(uri)
319
+ yield uri unless dupes.include?(uri) || Repositories.instance.exist?(uri)
320
+ dupes << uri
321
+ end
322
+ end
323
+ rescue
324
+ puts "Problems scraping '#{uri}': #{$!.to_s}"
325
+ end
326
+ end
327
+ end
328
+
329
+ def extract_repository_uri(uri)
330
+ uri.match(/(svn|https?):.*\/plugins\//i)[0]
331
+ end
332
+ end
333
+
334
+ class Install
335
+ def initialize(base_command)
336
+ @base_command = base_command
337
+ @method = :http
338
+ @options = { :quiet => false, :revision => nil, :force => false }
339
+ end
340
+
341
+ def options
342
+ OptionParser.new do |o|
343
+ o.set_summary_indent(' ')
344
+ o.banner = "Usage: #{@base_command.script_name} install PLUGIN [PLUGIN [PLUGIN] ...]"
345
+ o.define_head "Install one or more plugins."
346
+ o.separator ""
347
+ o.separator "Options:"
348
+ o.on( "-x", "--externals",
349
+ "Use svn:externals to grab the plugin.",
350
+ "Enables plugin updates and plugin versioning.") { |v| @method = :externals }
351
+ o.on( "-o", "--checkout",
352
+ "Use svn checkout to grab the plugin.",
353
+ "Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
354
+ o.on( "-q", "--quiet",
355
+ "Suppresses the output from installation.",
356
+ "Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
357
+ o.on( "-r REVISION", "--revision REVISION",
358
+ "Checks out the given revision from subversion.",
359
+ "Ignored if subversion is not used.") { |v| @options[:revision] = v }
360
+ o.on( "-f", "--force",
361
+ "Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
362
+ o.separator ""
363
+ o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
364
+ o.separator "a plugin repository."
365
+ end
366
+ end
367
+
368
+ def determine_install_method
369
+ best = @base_command.environment.best_install_method?
370
+ @method = :http if best == :http and @method == :export
371
+ case
372
+ when (best == :http and @method != :http)
373
+ msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
374
+ when (best == :export and (@method != :export and @method != :http))
375
+ msg = "Cannot install using #{@method} because this project is not under subversion."
376
+ when (best != :externals and @method == :externals)
377
+ msg = "Cannot install using externals because vendor/plugins is not under subversion."
378
+ end
379
+ if msg
380
+ puts msg
381
+ exit 1
382
+ end
383
+ @method
384
+ end
385
+
386
+ def parse!(args)
387
+ options.parse!(args)
388
+ environment = @base_command.environment
389
+ install_method = determine_install_method
390
+ puts "Plugins will be installed using #{install_method}" if $verbose
391
+ args.each do |name|
392
+ ::Plugin.find(name).install(install_method, @options)
393
+ end
394
+ rescue
395
+ puts "Plugin not found: #{args.inspect}"
396
+ exit 1
397
+ end
398
+ end
399
+
400
+ class Update
401
+ def initialize(base_command)
402
+ @base_command = base_command
403
+ end
404
+
405
+ def options
406
+ OptionParser.new do |o|
407
+ o.set_summary_indent(' ')
408
+ o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
409
+ o.on( "-r REVISION", "--revision REVISION",
410
+ "Checks out the given revision from subversion.",
411
+ "Ignored if subversion is not used.") { |v| @revision = v }
412
+ o.define_head "Update plugins."
413
+ end
414
+ end
415
+
416
+ def parse!(args)
417
+ options.parse!(args)
418
+ root = @base_command.environment.root
419
+ cd root
420
+ args = Dir["vendor/plugins/*"].map do |f|
421
+ File.directory?("#{f}/.svn") ? File.basename(f) : nil
422
+ end.compact if args.empty?
423
+ cd "vendor/plugins"
424
+ args.each do |name|
425
+ if File.directory?(name)
426
+ puts "Updating plugin: #{name}"
427
+ system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}")
428
+ else
429
+ puts "Plugin doesn't exist: #{name}"
430
+ end
431
+ end
432
+ end
433
+ end
434
+
435
+ class Remove
436
+ def initialize(base_command)
437
+ @base_command = base_command
438
+ end
439
+
440
+ def options
441
+ OptionParser.new do |o|
442
+ o.set_summary_indent(' ')
443
+ o.banner = "Usage: #{@base_command.script_name} remove name [name]..."
444
+ o.define_head "Remove plugins."
445
+ end
446
+ end
447
+
448
+ def parse!(args)
449
+ options.parse!(args)
450
+ root = @base_command.environment.root
451
+ args.each do |name|
452
+ ::Plugin.new(name).uninstall
453
+ end
454
+ end
455
+ end
456
+
457
+ class About
458
+ def initialize(base_command)
459
+ @base_command = base_command
460
+ end
461
+
462
+ def options
463
+ OptionParser.new do |o|
464
+ o.set_summary_indent(' ')
465
+ o.banner = "Usage: #{@base_command.script_name} about name [name]..."
466
+ o.define_head "Shows plugin info at {url}/about.yml."
467
+ end
468
+ end
469
+
470
+ def parse!(args)
471
+ options.parse!(args)
472
+ args.each do |name|
473
+ if plugin = ::Plugin.find(name)
474
+ if about_hash = plugin.about
475
+ puts about_hash.to_yaml + "\n"
476
+ next
477
+ end
478
+ end
479
+
480
+ puts "Plugin #{name} could not be found in the known repositories."
481
+ puts
482
+ end
483
+ end
484
+ end
485
+ end
486
+