rubycas-client 2.2.1 → 2.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +30 -0
  3. data/History.txt +21 -0
  4. data/README.rdoc +24 -20
  5. data/Rakefile +43 -54
  6. data/VERSION +1 -0
  7. data/examples/rails/README +16 -0
  8. data/examples/rails/app/controllers/advanced_example_controller.rb +31 -0
  9. data/examples/rails/app/controllers/application.rb +2 -0
  10. data/examples/rails/app/controllers/simple_example_controller.rb +16 -0
  11. data/examples/rails/app/views/advanced_example/index.html.erb +13 -0
  12. data/examples/rails/app/views/advanced_example/my_account.html.erb +11 -0
  13. data/examples/rails/app/views/simple_example/index.html.erb +6 -0
  14. data/examples/rails/config/boot.rb +109 -0
  15. data/examples/rails/config/environment.rb +39 -0
  16. data/examples/rails/config/environments/development.rb +17 -0
  17. data/examples/rails/config/environments/production.rb +22 -0
  18. data/examples/rails/config/environments/test.rb +22 -0
  19. data/examples/rails/config/initializers/inflections.rb +10 -0
  20. data/examples/rails/config/initializers/mime_types.rb +5 -0
  21. data/examples/rails/config/initializers/new_rails_defaults.rb +17 -0
  22. data/examples/rails/config/routes.rb +4 -0
  23. data/examples/rails/log/development.log +946 -0
  24. data/examples/rails/log/production.log +0 -0
  25. data/examples/rails/log/server.log +0 -0
  26. data/examples/rails/log/test.log +0 -0
  27. data/examples/rails/script/about +4 -0
  28. data/examples/rails/script/console +3 -0
  29. data/examples/rails/script/server +3 -0
  30. data/lib/casclient/client.rb +49 -36
  31. data/lib/casclient/frameworks/rails/cas_proxy_callback_controller.rb +5 -39
  32. data/lib/casclient/frameworks/rails/filter.rb +86 -113
  33. data/lib/casclient/responses.rb +29 -16
  34. data/lib/casclient/tickets/storage/active_record_ticket_store.rb +67 -0
  35. data/lib/casclient/tickets/storage.rb +167 -0
  36. data/lib/casclient/tickets.rb +3 -3
  37. data/lib/casclient.rb +3 -2
  38. data/lib/rubycas-client.rb +1 -5
  39. data/rails_generators/active_record_ticket_store/USAGE +9 -0
  40. data/rails_generators/active_record_ticket_store/active_record_ticket_store_generator.rb +29 -0
  41. data/rails_generators/active_record_ticket_store/templates/README +1 -0
  42. data/rails_generators/active_record_ticket_store/templates/migration.rb +24 -0
  43. data/rubycas-client.gemspec +103 -0
  44. data/test/teststrap.rb +10 -0
  45. data/test/units/casclient/frameworks/rails/filter_test.rb +184 -0
  46. metadata +148 -47
  47. data/Manifest.txt +0 -23
  48. data/examples/merb/README.textile +0 -12
  49. data/examples/merb/Rakefile +0 -35
  50. data/examples/merb/merb.thor +0 -2020
  51. data/examples/merb/merb_auth_cas.rb +0 -67
  52. data/examples/merb/spec/spec_helper.rb +0 -24
  53. data/init.rb +0 -6
  54. data/lib/casclient/frameworks/merb/filter.rb +0 -105
  55. data/lib/casclient/frameworks/merb/strategy.rb +0 -110
  56. data/lib/casclient/version.rb +0 -9
  57. data/setup.rb +0 -1585
data/Manifest.txt DELETED
@@ -1,23 +0,0 @@
1
- CHANGELOG.txt
2
- History.txt
3
- LICENSE.txt
4
- Manifest.txt
5
- README.rdoc
6
- Rakefile
7
- examples/merb/README.textile
8
- examples/merb/Rakefile
9
- examples/merb/merb.thor
10
- examples/merb/merb_auth_cas.rb
11
- examples/merb/spec/spec_helper.rb
12
- init.rb
13
- lib/casclient.rb
14
- lib/casclient/client.rb
15
- lib/casclient/frameworks/merb/filter.rb
16
- lib/casclient/frameworks/merb/strategy.rb
17
- lib/casclient/frameworks/rails/cas_proxy_callback_controller.rb
18
- lib/casclient/frameworks/rails/filter.rb
19
- lib/casclient/responses.rb
20
- lib/casclient/tickets.rb
21
- lib/casclient/version.rb
22
- lib/rubycas-client.rb
23
- setup.rb
@@ -1,12 +0,0 @@
1
- h1. Very flat merb app with casclient support
2
-
3
- Run rubycas-server or other CAS server on localhost:7777
4
-
5
- Then type this:
6
- <pre><code>
7
- merb -I merb_auth_cas.rb
8
- </code></pre>
9
-
10
- Then point your web browser to http://localhost:4000.
11
- You should be redirected to the CAS login screen, then
12
- to your Merb application showing your username.
@@ -1,35 +0,0 @@
1
- require 'rubygems'
2
- require 'rake/rdoctask'
3
-
4
- require 'merb-core'
5
- require 'merb-core/tasks/merb'
6
-
7
- include FileUtils
8
-
9
- # Load the basic runtime dependencies; this will include
10
- # any plugins and therefore plugin rake tasks.
11
- init_env = ENV['MERB_ENV'] || 'rake'
12
- Merb.load_dependencies(:environment => init_env)
13
-
14
- # Get Merb plugins and dependencies
15
- Merb::Plugins.rakefiles.each { |r| require r }
16
-
17
- # Load any app level custom rakefile extensions from lib/tasks
18
- tasks_path = File.join(File.dirname(__FILE__), "lib", "tasks")
19
- rake_files = Dir["#{tasks_path}/*.rake"]
20
- rake_files.each{|rake_file| load rake_file }
21
-
22
- desc "Start runner environment"
23
- task :merb_env do
24
- Merb.start_environment(:environment => init_env, :adapter => 'runner')
25
- end
26
-
27
- require 'spec/rake/spectask'
28
- require 'merb-core/test/tasks/spectasks'
29
- desc 'Default: run spec examples'
30
- task :default => 'spec'
31
-
32
- ##############################################################################
33
- # ADD YOUR CUSTOM TASKS IN /lib/tasks
34
- # NAME YOUR RAKE FILES file_name.rake
35
- ##############################################################################
@@ -1,2020 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'rubygems'
3
- require 'thor'
4
- require 'fileutils'
5
- require 'yaml'
6
-
7
- # Important - don't change this line or its position
8
- MERB_THOR_VERSION = '0.2.1'
9
-
10
- ##############################################################################
11
-
12
- module ColorfulMessages
13
-
14
- # red
15
- def error(*messages)
16
- puts messages.map { |msg| "\033[1;31m#{msg}\033[0m" }
17
- end
18
-
19
- # yellow
20
- def warning(*messages)
21
- puts messages.map { |msg| "\033[1;33m#{msg}\033[0m" }
22
- end
23
-
24
- # green
25
- def success(*messages)
26
- puts messages.map { |msg| "\033[1;32m#{msg}\033[0m" }
27
- end
28
-
29
- alias_method :message, :success
30
-
31
- # magenta
32
- def note(*messages)
33
- puts messages.map { |msg| "\033[1;35m#{msg}\033[0m" }
34
- end
35
-
36
- # blue
37
- def info(*messages)
38
- puts messages.map { |msg| "\033[1;34m#{msg}\033[0m" }
39
- end
40
-
41
- end
42
-
43
- ##############################################################################
44
-
45
- require 'rubygems/dependency_installer'
46
- require 'rubygems/uninstaller'
47
- require 'rubygems/dependency'
48
-
49
- module GemManagement
50
-
51
- include ColorfulMessages
52
-
53
- # Install a gem - looks remotely and local gem cache;
54
- # won't process rdoc or ri options.
55
- def install_gem(gem, options = {})
56
- refresh = options.delete(:refresh) || []
57
- from_cache = (options.key?(:cache) && options.delete(:cache))
58
- if from_cache
59
- install_gem_from_cache(gem, options)
60
- else
61
- version = options.delete(:version)
62
- Gem.configuration.update_sources = false
63
-
64
- # Limit source index to install dir
65
- update_source_index(options[:install_dir]) if options[:install_dir]
66
-
67
- installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
68
-
69
- # Force-refresh certain gems by excluding them from the current index
70
- if !options[:ignore_dependencies] && refresh.respond_to?(:include?) && !refresh.empty?
71
- source_index = installer.instance_variable_get(:@source_index)
72
- source_index.gems.each do |name, spec|
73
- source_index.gems.delete(name) if refresh.include?(spec.name)
74
- end
75
- end
76
-
77
- exception = nil
78
- begin
79
- installer.install gem, version
80
- rescue Gem::InstallError => e
81
- exception = e
82
- rescue Gem::GemNotFoundException => e
83
- if from_cache && gem_file = find_gem_in_cache(gem, version)
84
- puts "Located #{gem} in gem cache..."
85
- installer.install gem_file
86
- else
87
- exception = e
88
- end
89
- rescue => e
90
- exception = e
91
- end
92
- if installer.installed_gems.empty? && exception
93
- error "Failed to install gem '#{gem} (#{version || 'any version'})' (#{exception.message})"
94
- end
95
- ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options)
96
- installer.installed_gems.each do |spec|
97
- success "Successfully installed #{spec.full_name}"
98
- end
99
- return !installer.installed_gems.empty?
100
- end
101
- end
102
-
103
- # Install a gem - looks in the system's gem cache instead of remotely;
104
- # won't process rdoc or ri options.
105
- def install_gem_from_cache(gem, options = {})
106
- version = options.delete(:version)
107
- Gem.configuration.update_sources = false
108
- installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
109
- exception = nil
110
- begin
111
- if gem_file = find_gem_in_cache(gem, version)
112
- puts "Located #{gem} in gem cache..."
113
- installer.install gem_file
114
- else
115
- raise Gem::InstallError, "Unknown gem #{gem}"
116
- end
117
- rescue Gem::InstallError => e
118
- exception = e
119
- end
120
- if installer.installed_gems.empty? && exception
121
- error "Failed to install gem '#{gem}' (#{e.message})"
122
- end
123
- ensure_bin_wrapper_for_installed_gems(installer.installed_gems, options)
124
- installer.installed_gems.each do |spec|
125
- success "Successfully installed #{spec.full_name}"
126
- end
127
- end
128
-
129
- # Install a gem from source - builds and packages it first then installs.
130
- #
131
- # Examples:
132
- # install_gem_from_source(source_dir, :install_dir => ...)
133
- # install_gem_from_source(source_dir, gem_name)
134
- # install_gem_from_source(source_dir, :skip => [...])
135
- def install_gem_from_source(source_dir, *args)
136
- installed_gems = []
137
- opts = args.last.is_a?(Hash) ? args.pop : {}
138
- Dir.chdir(source_dir) do
139
- gem_name = args[0] || File.basename(source_dir)
140
- gem_pkg_dir = File.join(source_dir, 'pkg')
141
- gem_pkg_glob = File.join(gem_pkg_dir, "#{gem_name}-*.gem")
142
- skip_gems = opts.delete(:skip) || []
143
-
144
- # Cleanup what's already there
145
- clobber(source_dir)
146
- FileUtils.mkdir_p(gem_pkg_dir) unless File.directory?(gem_pkg_dir)
147
-
148
- # Recursively process all gem packages within the source dir
149
- skip_gems << gem_name
150
- packages = package_all(source_dir, skip_gems)
151
-
152
- if packages.length == 1
153
- # The are no subpackages for the main package
154
- refresh = [gem_name]
155
- else
156
- # Gather all packages into the top-level pkg directory
157
- packages.each do |pkg|
158
- FileUtils.copy_entry(pkg, File.join(gem_pkg_dir, File.basename(pkg)))
159
- end
160
-
161
- # Finally package the main gem - without clobbering the already copied pkgs
162
- package(source_dir, false)
163
-
164
- # Gather subgems to refresh during installation of the main gem
165
- refresh = packages.map do |pkg|
166
- File.basename(pkg, '.gem')[/^(.*?)-([\d\.]+)$/, 1] rescue nil
167
- end.compact
168
-
169
- # Install subgems explicitly even if ignore_dependencies is set
170
- if opts[:ignore_dependencies]
171
- refresh.each do |name|
172
- gem_pkg = Dir[File.join(gem_pkg_dir, "#{name}-*.gem")][0]
173
- install_pkg(gem_pkg, opts)
174
- end
175
- end
176
- end
177
-
178
- ensure_bin_wrapper_for(opts[:install_dir], opts[:bin_dir], *installed_gems)
179
-
180
- # Finally install the main gem
181
- if install_pkg(Dir[gem_pkg_glob][0], opts.merge(:refresh => refresh))
182
- installed_gems = refresh
183
- else
184
- installed_gems = []
185
- end
186
- end
187
- installed_gems
188
- end
189
-
190
- def install_pkg(gem_pkg, opts = {})
191
- if (gem_pkg && File.exists?(gem_pkg))
192
- # Needs to be executed from the directory that contains all packages
193
- Dir.chdir(File.dirname(gem_pkg)) { install_gem(gem_pkg, opts) }
194
- else
195
- false
196
- end
197
- end
198
-
199
- # Uninstall a gem.
200
- def uninstall_gem(gem, options = {})
201
- if options[:version] && !options[:version].is_a?(Gem::Requirement)
202
- options[:version] = Gem::Requirement.new ["= #{options[:version]}"]
203
- end
204
- update_source_index(options[:install_dir]) if options[:install_dir]
205
- Gem::Uninstaller.new(gem, options).uninstall rescue nil
206
- end
207
-
208
- def clobber(source_dir)
209
- Dir.chdir(source_dir) do
210
- system "#{Gem.ruby} -S rake -s clobber" unless File.exists?('Thorfile')
211
- end
212
- end
213
-
214
- def package(source_dir, clobber = true)
215
- Dir.chdir(source_dir) do
216
- if File.exists?('Thorfile')
217
- thor ":package"
218
- elsif File.exists?('Rakefile')
219
- rake "clobber" if clobber
220
- rake "package"
221
- end
222
- end
223
- Dir[File.join(source_dir, 'pkg/*.gem')]
224
- end
225
-
226
- def package_all(source_dir, skip = [], packages = [])
227
- if Dir[File.join(source_dir, '{Rakefile,Thorfile}')][0]
228
- name = File.basename(source_dir)
229
- Dir[File.join(source_dir, '*', '{Rakefile,Thorfile}')].each do |taskfile|
230
- package_all(File.dirname(taskfile), skip, packages)
231
- end
232
- packages.push(*package(source_dir)) unless skip.include?(name)
233
- end
234
- packages.uniq
235
- end
236
-
237
- def rake(cmd)
238
- cmd << " >/dev/null" if $SILENT && !Gem.win_platform?
239
- system "#{Gem.ruby} -S #{which('rake')} -s #{cmd} >/dev/null"
240
- end
241
-
242
- def thor(cmd)
243
- cmd << " >/dev/null" if $SILENT && !Gem.win_platform?
244
- system "#{Gem.ruby} -S #{which('thor')} #{cmd}"
245
- end
246
-
247
- # Use the local bin/* executables if available.
248
- def which(executable)
249
- if File.executable?(exec = File.join(Dir.pwd, 'bin', executable))
250
- exec
251
- else
252
- executable
253
- end
254
- end
255
-
256
- # Partition gems into system, local and missing gems
257
- def partition_dependencies(dependencies, gem_dir)
258
- system_specs, local_specs, missing_deps = [], [], []
259
- if gem_dir && File.directory?(gem_dir)
260
- gem_dir = File.expand_path(gem_dir)
261
- ::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
262
- ::Gem.source_index.refresh!
263
- dependencies.each do |dep|
264
- gemspecs = ::Gem.source_index.search(dep)
265
- local = gemspecs.reverse.find { |s| s.loaded_from.index(gem_dir) == 0 }
266
- if local
267
- local_specs << local
268
- elsif gemspecs.last
269
- system_specs << gemspecs.last
270
- else
271
- missing_deps << dep
272
- end
273
- end
274
- ::Gem.clear_paths
275
- else
276
- dependencies.each do |dep|
277
- gemspecs = ::Gem.source_index.search(dep)
278
- if gemspecs.last
279
- system_specs << gemspecs.last
280
- else
281
- missing_deps << dep
282
- end
283
- end
284
- end
285
- [system_specs, local_specs, missing_deps]
286
- end
287
-
288
- # Create a modified executable wrapper in the specified bin directory.
289
- def ensure_bin_wrapper_for(gem_dir, bin_dir, *gems)
290
- options = gems.last.is_a?(Hash) ? gems.last : {}
291
- options[:no_minigems] ||= []
292
- if bin_dir && File.directory?(bin_dir)
293
- gems.each do |gem|
294
- if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{gem}-*.gemspec")].last
295
- spec = Gem::Specification.load(gemspec_path)
296
- enable_minigems = !options[:no_minigems].include?(spec.name)
297
- spec.executables.each do |exec|
298
- executable = File.join(bin_dir, exec)
299
- message "Writing executable wrapper #{executable}"
300
- File.open(executable, 'w', 0755) do |f|
301
- f.write(executable_wrapper(spec, exec, enable_minigems))
302
- end
303
- end
304
- end
305
- end
306
- end
307
- end
308
-
309
- def ensure_bin_wrapper_for_installed_gems(gemspecs, options)
310
- if options[:install_dir] && options[:bin_dir]
311
- gems = gemspecs.map { |spec| spec.name }
312
- ensure_bin_wrapper_for(options[:install_dir], options[:bin_dir], *gems)
313
- end
314
- end
315
-
316
- private
317
-
318
- def executable_wrapper(spec, bin_file_name, minigems = true)
319
- requirements = ['minigems', 'rubygems']
320
- requirements.reverse! unless minigems
321
- try_req, then_req = requirements
322
- <<-TEXT
323
- #!/usr/bin/env ruby
324
- #
325
- # This file was generated by Merb's GemManagement
326
- #
327
- # The application '#{spec.name}' is installed as part of a gem, and
328
- # this file is here to facilitate running it.
329
-
330
- begin
331
- require '#{try_req}'
332
- rescue LoadError
333
- require '#{then_req}'
334
- end
335
-
336
- # use gems dir if ../gems exists - eg. only for ./bin/#{bin_file_name}
337
- if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems'))
338
- $BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)])
339
- ENV["PATH"] = "\#{File.dirname(__FILE__)}:\#{gems_dir}/bin:\#{ENV["PATH"]}"
340
- if (local_gem = Dir[File.join(gems_dir, "specifications", "#{spec.name}-*.gemspec")].last)
341
- version = File.basename(local_gem)[/-([\\.\\d]+)\\.gemspec$/, 1]
342
- end
343
- end
344
-
345
- version ||= "#{Gem::Requirement.default}"
346
-
347
- if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
348
- version = $1
349
- ARGV.shift
350
- end
351
-
352
- gem '#{spec.name}', version
353
- load '#{bin_file_name}'
354
- TEXT
355
- end
356
-
357
- def find_gem_in_cache(gem, version)
358
- spec = if version
359
- version = Gem::Requirement.new ["= #{version}"] unless version.is_a?(Gem::Requirement)
360
- Gem.source_index.find_name(gem, version).first
361
- else
362
- Gem.source_index.find_name(gem).sort_by { |g| g.version }.last
363
- end
364
- if spec && File.exists?(gem_file = "#{spec.installation_path}/cache/#{spec.full_name}.gem")
365
- gem_file
366
- end
367
- end
368
-
369
- def update_source_index(dir)
370
- Gem.source_index.load_gems_in(File.join(dir, 'specifications'))
371
- end
372
-
373
- end
374
-
375
- ##############################################################################
376
-
377
- class SourceManager
378
-
379
- include ColorfulMessages
380
-
381
- attr_accessor :source_dir
382
-
383
- def initialize(source_dir)
384
- self.source_dir = source_dir
385
- end
386
-
387
- def clone(name, url)
388
- FileUtils.cd(source_dir) do
389
- raise "destination directory already exists" if File.directory?(name)
390
- system("git clone --depth 1 #{url} #{name}")
391
- end
392
- rescue => e
393
- error "Unable to clone #{name} repository (#{e.message})"
394
- end
395
-
396
- def update(name, url)
397
- if File.directory?(repository_dir = File.join(source_dir, name))
398
- FileUtils.cd(repository_dir) do
399
- repos = existing_repos(name)
400
- fork_name = url[/.com\/+?(.+)\/.+\.git/u, 1]
401
- if url == repos["origin"]
402
- # Pull from the original repository - no branching needed
403
- info "Pulling from origin: #{url}"
404
- system "git fetch; git checkout master; git rebase origin/master"
405
- elsif repos.values.include?(url) && fork_name
406
- # Update and switch to a remote branch for a particular github fork
407
- info "Switching to remote branch: #{fork_name}"
408
- system "git checkout -b #{fork_name} #{fork_name}/master"
409
- system "git rebase #{fork_name}/master"
410
- elsif fork_name
411
- # Create a new remote branch for a particular github fork
412
- info "Adding a new remote branch: #{fork_name}"
413
- system "git remote add -f #{fork_name} #{url}"
414
- system "git checkout -b #{fork_name} #{fork_name}/master"
415
- else
416
- warning "No valid repository found for: #{name}"
417
- end
418
- end
419
- return true
420
- else
421
- warning "No valid repository found at: #{repository_dir}"
422
- end
423
- rescue => e
424
- error "Unable to update #{name} repository (#{e.message})"
425
- return false
426
- end
427
-
428
- def existing_repos(name)
429
- repos = []
430
- FileUtils.cd(File.join(source_dir, name)) do
431
- repos = %x[git remote -v].split("\n").map { |branch| branch.split(/\s+/) }
432
- end
433
- Hash[*repos.flatten]
434
- end
435
-
436
- end
437
-
438
- ##############################################################################
439
-
440
- module MerbThorHelper
441
-
442
- attr_accessor :force_gem_dir
443
-
444
- def self.included(base)
445
- base.send(:include, ColorfulMessages)
446
- base.extend ColorfulMessages
447
- end
448
-
449
- def use_edge_gem_server
450
- ::Gem.sources << 'http://edge.merbivore.com'
451
- end
452
-
453
- def source_manager
454
- @_source_manager ||= SourceManager.new(source_dir)
455
- end
456
-
457
- def extract_repositories(names)
458
- repos = []
459
- names.each do |name|
460
- if repo_url = Merb::Source.repo(name, options[:sources])
461
- # A repository entry for this dependency exists
462
- repo = [name, repo_url]
463
- repos << repo unless repos.include?(repo)
464
- elsif (repo_name = Merb::Stack.lookup_repository_name(name)) &&
465
- (repo_url = Merb::Source.repo(repo_name, options[:sources]))
466
- # A parent repository entry for this dependency exists
467
- repo = [repo_name, repo_url]
468
- unless repos.include?(repo)
469
- puts "Found #{repo_name}/#{name} at #{repo_url}"
470
- repos << repo
471
- end
472
- end
473
- end
474
- repos
475
- end
476
-
477
- def update_dependency_repositories(dependencies)
478
- repos = extract_repositories(dependencies.map { |d| d.name })
479
- update_repositories(repos)
480
- end
481
-
482
- def update_repositories(repos)
483
- repos.each do |(name, url)|
484
- if File.directory?(repository_dir = File.join(source_dir, name))
485
- message "Updating or branching #{name}..."
486
- source_manager.update(name, url)
487
- else
488
- message "Cloning #{name} repository from #{url}..."
489
- source_manager.clone(name, url)
490
- end
491
- end
492
- end
493
-
494
- def install_dependency(dependency, opts = {})
495
- version = dependency.version_requirements.to_s
496
- install_opts = default_install_options.merge(:version => version)
497
- Merb::Gem.install(dependency.name, install_opts.merge(opts))
498
- end
499
-
500
- def install_dependency_from_source(dependency, opts = {})
501
- matches = Dir[File.join(source_dir, "**", dependency.name, "{Rakefile,Thorfile}")]
502
- matches.reject! { |m| File.basename(m) == 'Thorfile' }
503
- if matches.length == 1 && matches[0]
504
- if File.directory?(gem_src_dir = File.dirname(matches[0]))
505
- begin
506
- Merb::Gem.install_gem_from_source(gem_src_dir, default_install_options.merge(opts))
507
- puts "Installed #{dependency.name}"
508
- return true
509
- rescue => e
510
- warning "Unable to install #{dependency.name} from source (#{e.message})"
511
- end
512
- else
513
- msg = "Unknown directory: #{gem_src_dir}"
514
- warning "Unable to install #{dependency.name} from source (#{msg})"
515
- end
516
- elsif matches.length > 1
517
- error "Ambigous source(s) for dependency: #{dependency.name}"
518
- matches.each { |m| puts "- #{m}" }
519
- end
520
- return false
521
- end
522
-
523
- def clobber_dependencies!
524
- if options[:force] && gem_dir && File.directory?(gem_dir)
525
- # Remove all existing local gems by clearing the gems directory
526
- if dry_run?
527
- note 'Clearing existing local gems...'
528
- else
529
- message 'Clearing existing local gems...'
530
- FileUtils.rm_rf(gem_dir) && FileUtils.mkdir_p(default_gem_dir)
531
- end
532
- elsif !local.empty?
533
- # Uninstall all local versions of the gems to install
534
- if dry_run?
535
- note 'Uninstalling existing local gems:'
536
- local.each { |gemspec| note "Uninstalled #{gemspec.name}" }
537
- else
538
- message 'Uninstalling existing local gems:' if local.size > 1
539
- local.each do |gemspec|
540
- Merb::Gem.uninstall(gemspec.name, default_uninstall_options)
541
- end
542
- end
543
- end
544
- end
545
-
546
- def display_gemspecs(gemspecs)
547
- if gemspecs.empty?
548
- puts "- none"
549
- else
550
- gemspecs.each do |spec|
551
- if hint = Dir[File.join(spec.full_gem_path, '*.strategy')][0]
552
- strategy = File.basename(hint, '.strategy')
553
- puts "- #{spec.full_name} (#{strategy})"
554
- else
555
- puts "~ #{spec.full_name}" # unknown strategy
556
- end
557
- end
558
- end
559
- end
560
-
561
- def display_dependencies(dependencies)
562
- if dependencies.empty?
563
- puts "- none"
564
- else
565
- dependencies.each { |d| puts "- #{d.name} (#{d.version_requirements})" }
566
- end
567
- end
568
-
569
- def default_install_options
570
- { :install_dir => gem_dir, :bin_dir => bin_dir, :ignore_dependencies => ignore_dependencies? }
571
- end
572
-
573
- def default_uninstall_options
574
- { :install_dir => gem_dir, :bin_dir => bin_dir, :ignore => true, :all => true, :executables => true }
575
- end
576
-
577
- def dry_run?
578
- options[:"dry-run"]
579
- end
580
-
581
- def ignore_dependencies?
582
- options[:"ignore-dependencies"]
583
- end
584
-
585
- # The current working directory, or Merb app root (--merb-root option).
586
- def working_dir
587
- @_working_dir ||= File.expand_path(options['merb-root'] || Dir.pwd)
588
- end
589
-
590
- # We should have a ./src dir for local and system-wide management.
591
- def source_dir
592
- @_source_dir ||= File.join(working_dir, 'src')
593
- create_if_missing(@_source_dir)
594
- @_source_dir
595
- end
596
-
597
- # If a local ./gems dir is found, return it.
598
- def gem_dir
599
- return force_gem_dir if force_gem_dir
600
- if File.directory?(dir = default_gem_dir)
601
- dir
602
- end
603
- end
604
-
605
- def default_gem_dir
606
- File.join(working_dir, 'gems')
607
- end
608
-
609
- # If we're in a Merb app, we can have a ./bin directory;
610
- # create it if it's not there.
611
- def bin_dir
612
- @_bin_dir ||= begin
613
- if gem_dir
614
- dir = File.join(working_dir, 'bin')
615
- create_if_missing(dir)
616
- dir
617
- end
618
- end
619
- end
620
-
621
- # Helper to create dir unless it exists.
622
- def create_if_missing(path)
623
- FileUtils.mkdir(path) unless File.exists?(path)
624
- end
625
-
626
- def sudo
627
- ENV['THOR_SUDO'] ||= "sudo"
628
- sudo = Gem.win_platform? ? "" : ENV['THOR_SUDO']
629
- end
630
-
631
- def local_gemspecs(directory = gem_dir)
632
- if File.directory?(specs_dir = File.join(directory, 'specifications'))
633
- Dir[File.join(specs_dir, '*.gemspec')].map do |gemspec_path|
634
- gemspec = Gem::Specification.load(gemspec_path)
635
- gemspec.loaded_from = gemspec_path
636
- gemspec
637
- end
638
- else
639
- []
640
- end
641
- end
642
-
643
- end
644
-
645
- ##############################################################################
646
-
647
- $SILENT = true # don't output all the mess some rake package tasks spit out
648
-
649
- module Merb
650
-
651
- class Gem < Thor
652
-
653
- include MerbThorHelper
654
- extend GemManagement
655
-
656
- attr_accessor :system, :local, :missing
657
-
658
- global_method_options = {
659
- "--merb-root" => :optional, # the directory to operate on
660
- "--version" => :optional, # gather specific version of gem
661
- "--ignore-dependencies" => :boolean # don't install sub-dependencies
662
- }
663
-
664
- method_options global_method_options
665
- def initialize(*args); super; end
666
-
667
- # List gems that match the specified criteria.
668
- #
669
- # By default all local gems are listed. When the first argument is 'all' the
670
- # list is partitioned into system an local gems; specify 'system' to show
671
- # only system gems. A second argument can be used to filter on a set of known
672
- # components, like all merb-more gems for example.
673
- #
674
- # Examples:
675
- #
676
- # merb:gem:list # list all local gems - the default
677
- # merb:gem:list all # list system and local gems
678
- # merb:gem:list system # list only system gems
679
- # merb:gem:list all merb-more # list only merb-more related gems
680
- # merb:gem:list --version 0.9.8 # list gems that match the version
681
-
682
- desc 'list [all|local|system] [comp]', 'Show installed gems'
683
- def list(filter = 'local', comp = nil)
684
- deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
685
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
686
- case filter
687
- when 'all'
688
- message 'Installed system gems:'
689
- display_gemspecs(system)
690
- message 'Installed local gems:'
691
- display_gemspecs(local)
692
- when 'system'
693
- message 'Installed system gems:'
694
- display_gemspecs(system)
695
- when 'local'
696
- message 'Installed local gems:'
697
- display_gemspecs(local)
698
- else
699
- warning "Invalid listing filter '#{filter}'"
700
- end
701
- end
702
-
703
- # Install the specified gems.
704
- #
705
- # All arguments should be names of gems to install.
706
- #
707
- # When :force => true then any existing versions of the gems to be installed
708
- # will be uninstalled first. It's important to note that so-called meta-gems
709
- # or gems that exactly match a set of Merb::Stack.components will have their
710
- # sub-gems uninstalled too. For example, uninstalling merb-more will install
711
- # all contained gems: merb-action-args, merb-assets, merb-gen, ...
712
- #
713
- # Examples:
714
- #
715
- # merb:gem:install merb-core merb-slices # install all specified gems
716
- # merb:gem:install merb-core --version 0.9.8 # install a specific version of a gem
717
- # merb:gem:install merb-core --force # uninstall then subsequently install the gem
718
- # merb:gem:install merb-core --cache # try to install locally from system gems
719
- # merb:gem:install merb --merb-edge # install from edge.merbivore.com
720
-
721
- desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from rubygems'
722
- method_options "--cache" => :boolean,
723
- "--dry-run" => :boolean,
724
- "--force" => :boolean,
725
- "--merb-edge" => :boolean
726
- def install(*names)
727
- opts = { :version => options[:version], :cache => options[:cache] }
728
- use_edge_gem_server if options[:"merb-edge"]
729
- current_gem = nil
730
-
731
- # uninstall existing gems of the ones we're going to install
732
- uninstall(*names) if options[:force]
733
-
734
- message "Installing #{names.length} #{names.length == 1 ? 'gem' : 'gems'}..."
735
- puts "This may take a while..."
736
-
737
- names.each do |gem_name|
738
- current_gem = gem_name
739
- if dry_run?
740
- note "Installing #{current_gem}..."
741
- else
742
- message "Installing #{current_gem}..."
743
- self.class.install(gem_name, default_install_options.merge(opts))
744
- end
745
- end
746
- rescue => e
747
- error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})"
748
- end
749
-
750
- # Uninstall the specified gems.
751
- #
752
- # By default all specified gems are uninstalled. It's important to note that
753
- # so-called meta-gems or gems that match a set of Merb::Stack.components will
754
- # have their sub-gems uninstalled too. For example, uninstalling merb-more
755
- # will install all contained gems: merb-action-args, merb-assets, ...
756
- #
757
- # Existing dependencies will be clobbered; when :force => true then all gems
758
- # will be cleared, otherwise only existing local dependencies of the
759
- # matching component set will be removed.
760
- #
761
- # Examples:
762
- #
763
- # merb:gem:uninstall merb-core merb-slices # uninstall all specified gems
764
- # merb:gem:uninstall merb-core --version 0.9.8 # uninstall a specific version of a gem
765
-
766
- desc 'uninstall GEM_NAME [GEM_NAME, ...]', 'Unstall a gem'
767
- method_options "--dry-run" => :boolean
768
- def uninstall(*names)
769
- opts = { :version => options[:version] }
770
- current_gem = nil
771
- if dry_run?
772
- note "Uninstalling any existing gems of: #{names.join(', ')}"
773
- else
774
- message "Uninstalling any existing gems of: #{names.join(', ')}"
775
- names.each do |gem_name|
776
- current_gem = gem_name
777
- Merb::Gem.uninstall(gem_name, default_uninstall_options) rescue nil
778
- # if this gem is a meta-gem or a component set name, remove sub-gems
779
- (Merb::Stack.components(gem_name) || []).each do |comp|
780
- Merb::Gem.uninstall(comp, default_uninstall_options) rescue nil
781
- end
782
- end
783
- end
784
- rescue => e
785
- error "Failed to uninstall #{current_gem ? current_gem : 'gem'} (#{e.message})"
786
- end
787
-
788
- # Recreate all gems from gems/cache on the current platform.
789
- #
790
- # This task should be executed as part of a deployment setup, where the
791
- # deployment system runs this after the app has been installed.
792
- # Usually triggered by Capistrano, God...
793
- #
794
- # It will regenerate gems from the bundled gems cache for any gem that has
795
- # C extensions - which need to be recompiled for the target deployment platform.
796
- #
797
- # Note: at least gems/cache and gems/specifications should be in your SCM.
798
-
799
- desc 'redeploy', 'Recreate all gems on the current platform'
800
- method_options "--dry-run" => :boolean, "--force" => :boolean
801
- def redeploy
802
- require 'tempfile' # for Dir::tmpdir access
803
- if gem_dir && File.directory?(cache_dir = File.join(gem_dir, 'cache'))
804
- specs = local_gemspecs
805
- message "Recreating #{specs.length} gems from cache..."
806
- puts "This may take a while..."
807
- specs.each do |gemspec|
808
- if File.exists?(gem_file = File.join(cache_dir, "#{gemspec.full_name}.gem"))
809
- gem_file_copy = File.join(Dir::tmpdir, File.basename(gem_file))
810
- if dry_run?
811
- note "Recreating #{gemspec.full_name}"
812
- else
813
- message "Recreating #{gemspec.full_name}"
814
- if options[:force] && File.directory?(gem = File.join(gem_dir, 'gems', gemspec.full_name))
815
- puts "Removing existing #{gemspec.full_name}"
816
- FileUtils.rm_rf(gem)
817
- end
818
- # Copy the gem to a temporary file, because otherwise RubyGems/FileUtils
819
- # will complain about copying identical files (same source/destination).
820
- FileUtils.cp(gem_file, gem_file_copy)
821
- Merb::Gem.install(gem_file_copy, :install_dir => gem_dir, :ignore_dependencies => true)
822
- File.delete(gem_file_copy)
823
- end
824
- end
825
- end
826
- else
827
- error "No application local gems directory found"
828
- end
829
- end
830
-
831
- private
832
-
833
- # Return dependencies for all installed gems; both system-wide and locally;
834
- # optionally filters on :version requirement.
835
- def dependencies
836
- version_req = if options[:version]
837
- ::Gem::Requirement.create(options[:version])
838
- else
839
- ::Gem::Requirement.default
840
- end
841
- if gem_dir
842
- ::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
843
- ::Gem.source_index.refresh!
844
- end
845
- deps = []
846
- ::Gem.source_index.each do |fullname, gemspec|
847
- if version_req.satisfied_by?(gemspec.version)
848
- deps << ::Gem::Dependency.new(gemspec.name, "= #{gemspec.version}")
849
- end
850
- end
851
- ::Gem.clear_paths if gem_dir
852
- deps.sort
853
- end
854
-
855
- public
856
-
857
- # Install gem with some default options.
858
- def self.install(name, options = {})
859
- defaults = {}
860
- defaults[:cache] = false unless opts[:install_dir]
861
- install_gem(name, defaults.merge(options))
862
- end
863
-
864
- # Uninstall gem with some default options.
865
- def self.uninstall(name, options = {})
866
- defaults = { :ignore => true, :executables => true }
867
- uninstall_gem(name, defaults.merge(options))
868
- end
869
-
870
- end
871
-
872
- class Tasks < Thor
873
-
874
- include MerbThorHelper
875
-
876
- # Show merb.thor version information
877
- #
878
- # merb:tasks:version # show the current version info
879
- # merb:tasks:version --info # show extended version info
880
-
881
- desc 'version', 'Show verion info'
882
- method_options "--info" => :boolean
883
- def version
884
- message "Currently installed merb.thor version: #{MERB_THOR_VERSION}"
885
- if options[:version]
886
- self.options = { :"dry-run" => true }
887
- self.update # run update task with dry-run enabled
888
- end
889
- end
890
-
891
- # Update merb.thor tasks from remotely available version
892
- #
893
- # merb:tasks:update # update merb.thor
894
- # merb:tasks:update --force # force-update merb.thor
895
- # merb:tasks:update --dry-run # show version info only
896
-
897
- desc 'update [URL]', 'Fetch the latest merb.thor and install it locally'
898
- method_options "--dry-run" => :boolean, "--force" => :boolean
899
- def update(url = 'http://merbivore.com/merb.thor')
900
- require 'open-uri'
901
- require 'rubygems/version'
902
- remote_file = open(url)
903
- code = remote_file.read
904
-
905
- # Extract version information from the source code
906
- if version = code[/^MERB_THOR_VERSION\s?=\s?('|")([\.\d]+)('|")/,2]
907
- # borrow version comparison from rubygems' Version class
908
- current_version = ::Gem::Version.new(MERB_THOR_VERSION)
909
- remote_version = ::Gem::Version.new(version)
910
-
911
- if current_version >= remote_version
912
- puts "currently installed: #{current_version}"
913
- if current_version != remote_version
914
- puts "available version: #{remote_version}"
915
- end
916
- info "No update of merb.thor necessary#{options[:force] ? ' (forced)' : ''}"
917
- proceed = options[:force]
918
- elsif current_version < remote_version
919
- puts "currently installed: #{current_version}"
920
- puts "available version: #{remote_version}"
921
- proceed = true
922
- end
923
-
924
- if proceed && !dry_run?
925
- File.open(File.join(__FILE__), 'w') do |f|
926
- f.write(code)
927
- end
928
- success "Installed the latest merb.thor (v#{version})"
929
- end
930
- else
931
- raise "invalid source-code data"
932
- end
933
- rescue OpenURI::HTTPError
934
- error "Error opening #{url}"
935
- rescue => e
936
- error "An error occurred (#{e.message})"
937
- end
938
-
939
- end
940
-
941
- #### MORE LOW-LEVEL TASKS ####
942
-
943
- class Source < Thor
944
-
945
- group 'core'
946
-
947
- include MerbThorHelper
948
- extend GemManagement
949
-
950
- attr_accessor :system, :local, :missing
951
-
952
- global_method_options = {
953
- "--merb-root" => :optional, # the directory to operate on
954
- "--ignore-dependencies" => :boolean, # don't install sub-dependencies
955
- "--sources" => :optional # a yml config to grab sources from
956
- }
957
-
958
- method_options global_method_options
959
- def initialize(*args); super; end
960
-
961
- # List source repositories, of either local or known sources.
962
- #
963
- # Examples:
964
- #
965
- # merb:source:list # list all local sources
966
- # merb:source:list available # list all known sources
967
-
968
- desc 'list [local|available]', 'Show git source repositories'
969
- def list(mode = 'local')
970
- if mode == 'available'
971
- message 'Available source repositories:'
972
- repos = self.class.repos(options[:sources])
973
- repos.keys.sort.each { |name| puts "- #{name}: #{repos[name]}" }
974
- elsif mode == 'local'
975
- message 'Current source repositories:'
976
- Dir[File.join(source_dir, '*')].each do |src|
977
- next unless File.directory?(src)
978
- src_name = File.basename(src)
979
- unless (repos = source_manager.existing_repos(src_name)).empty?
980
- puts "#{src_name}"
981
- repos.keys.sort.each { |b| puts "- #{b}: #{repos[b]}" }
982
- end
983
- end
984
- else
985
- error "Unknown listing: #{mode}"
986
- end
987
- end
988
-
989
- # Install the specified gems.
990
- #
991
- # All arguments should be names of gems to install.
992
- #
993
- # When :force => true then any existing versions of the gems to be installed
994
- # will be uninstalled first. It's important to note that so-called meta-gems
995
- # or gems that exactly match a set of Merb::Stack.components will have their
996
- # sub-gems uninstalled too. For example, uninstalling merb-more will install
997
- # all contained gems: merb-action-args, merb-assets, merb-gen, ...
998
- #
999
- # Examples:
1000
- #
1001
- # merb:source:install merb-core merb-slices # install all specified gems
1002
- # merb:source:install merb-core --force # uninstall then subsequently install the gem
1003
- # merb:source:install merb-core --wipe # clear repo then install the gem
1004
-
1005
- desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from git source/edge'
1006
- method_options "--dry-run" => :boolean,
1007
- "--force" => :boolean,
1008
- "--wipe" => :boolean
1009
- def install(*names)
1010
- use_edge_gem_server
1011
- # uninstall existing gems of the ones we're going to install
1012
- uninstall(*names) if options[:force] || options[:wipe]
1013
-
1014
- # We want dependencies instead of just names
1015
- deps = names.map { |n| ::Gem::Dependency.new(n, ::Gem::Requirement.default) }
1016
-
1017
- # Selectively update repositories for the matching dependencies
1018
- update_dependency_repositories(deps) unless dry_run?
1019
-
1020
- current_gem = nil
1021
- deps.each do |dependency|
1022
- current_gem = dependency.name
1023
- if dry_run?
1024
- note "Installing #{current_gem} from source..."
1025
- else
1026
- message "Installing #{current_gem} from source..."
1027
- puts "This may take a while..."
1028
- unless install_dependency_from_source(dependency)
1029
- raise "gem source not found"
1030
- end
1031
- end
1032
- end
1033
- rescue => e
1034
- error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})"
1035
- end
1036
-
1037
- # Uninstall the specified gems.
1038
- #
1039
- # By default all specified gems are uninstalled. It's important to note that
1040
- # so-called meta-gems or gems that match a set of Merb::Stack.components will
1041
- # have their sub-gems uninstalled too. For example, uninstalling merb-more
1042
- # will install all contained gems: merb-action-args, merb-assets, ...
1043
- #
1044
- # Existing dependencies will be clobbered; when :force => true then all gems
1045
- # will be cleared, otherwise only existing local dependencies of the
1046
- # matching component set will be removed. Additionally when :wipe => true,
1047
- # the matching git repositories will be removed from the source directory.
1048
- #
1049
- # Examples:
1050
- #
1051
- # merb:source:uninstall merb-core merb-slices # uninstall all specified gems
1052
- # merb:source:uninstall merb-core --wipe # force-uninstall a gem and clear repo
1053
-
1054
- desc 'uninstall GEM_NAME [GEM_NAME, ...]', 'Unstall a gem (specify --force to remove the repo)'
1055
- method_options "--version" => :optional, "--dry-run" => :boolean, "--wipe" => :boolean
1056
- def uninstall(*names)
1057
- # Remove the repos that contain the gem
1058
- if options[:wipe]
1059
- extract_repositories(names).each do |(name, url)|
1060
- if File.directory?(src = File.join(source_dir, name))
1061
- if dry_run?
1062
- note "Removing #{src}..."
1063
- else
1064
- info "Removing #{src}..."
1065
- FileUtils.rm_rf(src)
1066
- end
1067
- end
1068
- end
1069
- end
1070
-
1071
- # Use the Merb::Gem#uninstall task to handle this
1072
- gem_tasks = Merb::Gem.new
1073
- gem_tasks.options = options
1074
- gem_tasks.uninstall(*names)
1075
- end
1076
-
1077
- # Update the specified source repositories.
1078
- #
1079
- # The arguments can be actual repository names (from Merb::Source.repos)
1080
- # or names of known merb stack gems. If the repo doesn't exist already,
1081
- # it will be created and cloned.
1082
- #
1083
- # merb:source:pull merb-core # update source of specified gem
1084
- # merb:source:pull merb-slices # implicitly updates merb-more
1085
-
1086
- desc 'pull REPO_NAME [GEM_NAME, ...]', 'Update git source repository from edge'
1087
- def pull(*names)
1088
- repos = extract_repositories(names)
1089
- update_repositories(repos)
1090
- unless repos.empty?
1091
- message "Updated the following repositories:"
1092
- repos.each { |name, url| puts "- #{name}: #{url}" }
1093
- else
1094
- warning "No repositories found to update!"
1095
- end
1096
- end
1097
-
1098
- # Clone a git repository into ./src.
1099
-
1100
- # The repository can be a direct git url or a known -named- repository.
1101
- #
1102
- # Examples:
1103
- #
1104
- # merb:source:clone merb-core
1105
- # merb:source:clone dm-core awesome-repo
1106
- # merb:source:clone dm-core --sources ./path/to/sources.yml
1107
- # merb:source:clone git://github.com/sam/dm-core.git
1108
-
1109
- desc 'clone (REPO_NAME|URL) [DIR_NAME]', 'Clone git source repository by name or url'
1110
- def clone(repository, name = nil)
1111
- if repository =~ /^git:\/\//
1112
- repository_url = repository
1113
- repository_name = File.basename(repository_url, '.git')
1114
- elsif url = Merb::Source.repo(repository, options[:sources])
1115
- repository_url = url
1116
- repository_name = repository
1117
- end
1118
- source_manager.clone(name || repository_name, repository_url)
1119
- end
1120
-
1121
- # Git repository sources - pass source_config option to load a yaml
1122
- # configuration file - defaults to ./config/git-sources.yml and
1123
- # ~/.merb/git-sources.yml - which you need to create yourself.
1124
- #
1125
- # Example of contents:
1126
- #
1127
- # merb-core: git://github.com/myfork/merb-core.git
1128
- # merb-more: git://github.com/myfork/merb-more.git
1129
-
1130
- def self.repos(source_config = nil)
1131
- source_config ||= begin
1132
- local_config = File.join(Dir.pwd, 'config', 'git-sources.yml')
1133
- user_config = File.join(ENV["HOME"] || ENV["APPDATA"], '.merb', 'git-sources.yml')
1134
- File.exists?(local_config) ? local_config : user_config
1135
- end
1136
- if source_config && File.exists?(source_config)
1137
- default_repos.merge(YAML.load(File.read(source_config)))
1138
- else
1139
- default_repos
1140
- end
1141
- end
1142
-
1143
- def self.repo(name, source_config = nil)
1144
- self.repos(source_config)[name]
1145
- end
1146
-
1147
- # Default Git repositories
1148
- def self.default_repos
1149
- @_default_repos ||= {
1150
- 'merb' => "git://github.com/wycats/merb.git",
1151
- 'merb-plugins' => "git://github.com/wycats/merb-plugins.git",
1152
- 'extlib' => "git://github.com/sam/extlib.git",
1153
- 'dm-core' => "git://github.com/sam/dm-core.git",
1154
- 'dm-more' => "git://github.com/sam/dm-more.git",
1155
- 'sequel' => "git://github.com/wayneeseguin/sequel.git",
1156
- 'do' => "git://github.com/sam/do.git",
1157
- 'thor' => "git://github.com/wycats/thor.git",
1158
- 'rake' => "git://github.com/jimweirich/rake.git"
1159
- }
1160
- end
1161
-
1162
- end
1163
-
1164
- class Dependencies < Thor
1165
-
1166
- group 'core'
1167
-
1168
- # The Dependencies tasks will install dependencies based on actual application
1169
- # dependencies. For this, the application is queried for any dependencies.
1170
- # All operations will be performed within this context.
1171
-
1172
- attr_accessor :system, :local, :missing, :extract_dependencies
1173
-
1174
- include MerbThorHelper
1175
-
1176
- global_method_options = {
1177
- "--merb-root" => :optional, # the directory to operate on
1178
- "--ignore-dependencies" => :boolean, # ignore sub-dependencies
1179
- "--stack" => :boolean, # gather only stack dependencies
1180
- "--no-stack" => :boolean, # gather only non-stack dependencies
1181
- "--extract" => :boolean, # gather dependencies from the app itself
1182
- "--config-file" => :optional, # gather from the specified yaml config
1183
- "--version" => :optional # gather specific version of framework
1184
- }
1185
-
1186
- method_options global_method_options
1187
- def initialize(*args); super; end
1188
-
1189
- # List application dependencies.
1190
- #
1191
- # By default all dependencies are listed, partitioned into system, local and
1192
- # currently missing dependencies. The first argument allows you to filter
1193
- # on any of the partitionings. A second argument can be used to filter on
1194
- # a set of known components, like all merb-more gems for example.
1195
- #
1196
- # Examples:
1197
- #
1198
- # merb:dependencies:list # list all dependencies - the default
1199
- # merb:dependencies:list local # list only local gems
1200
- # merb:dependencies:list all merb-more # list only merb-more related dependencies
1201
- # merb:dependencies:list --stack # list framework dependencies
1202
- # merb:dependencies:list --no-stack # list 3rd party dependencies
1203
- # merb:dependencies:list --extract # list dependencies by extracting them
1204
- # merb:dependencies:list --config-file file.yml # list from the specified config file
1205
-
1206
- desc 'list [all|local|system|missing] [comp]', 'Show application dependencies'
1207
- def list(filter = 'all', comp = nil)
1208
- deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
1209
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1210
- case filter
1211
- when 'all'
1212
- message 'Installed system gem dependencies:'
1213
- display_gemspecs(system)
1214
- message 'Installed local gem dependencies:'
1215
- display_gemspecs(local)
1216
- unless missing.empty?
1217
- error 'Missing gem dependencies:'
1218
- display_dependencies(missing)
1219
- end
1220
- when 'system'
1221
- message 'Installed system gem dependencies:'
1222
- display_gemspecs(system)
1223
- when 'local'
1224
- message 'Installed local gem dependencies:'
1225
- display_gemspecs(local)
1226
- when 'missing'
1227
- error 'Missing gem dependencies:'
1228
- display_dependencies(missing)
1229
- else
1230
- warning "Invalid listing filter '#{filter}'"
1231
- end
1232
- if missing.size > 0
1233
- info "Some dependencies are currently missing!"
1234
- elsif local.size == deps.size
1235
- info "All dependencies have been bundled with the application."
1236
- elsif local.size > system.size
1237
- info "Most dependencies have been bundled with the application."
1238
- elsif system.size > 0 && local.size > 0
1239
- info "Some dependencies have been bundled with the application."
1240
- elsif local.empty? && system.size == deps.size
1241
- info "All dependencies are available on the system."
1242
- end
1243
- end
1244
-
1245
- # Install application dependencies.
1246
- #
1247
- # By default all required dependencies are installed. The first argument
1248
- # specifies which strategy to use: stable or edge. A second argument can be
1249
- # used to filter on a set of known components.
1250
- #
1251
- # Existing dependencies will be clobbered; when :force => true then all gems
1252
- # will be cleared first, otherwise only existing local dependencies of the
1253
- # gems to be installed will be removed.
1254
- #
1255
- # Examples:
1256
- #
1257
- # merb:dependencies:install # install all dependencies using stable strategy
1258
- # merb:dependencies:install stable --version 0.9.8 # install a specific version of the framework
1259
- # merb:dependencies:install stable missing # install currently missing gems locally
1260
- # merb:dependencies:install stable merb-more # install only merb-more related dependencies
1261
- # merb:dependencies:install stable --stack # install framework dependencies
1262
- # merb:dependencies:install stable --no-stack # install 3rd party dependencies
1263
- # merb:dependencies:install stable --extract # extract dependencies from the actual app
1264
- # merb:dependencies:install stable --config-file file.yml # read from the specified config file
1265
- #
1266
- # In addition to the options above, edge install uses the following:
1267
- #
1268
- # merb:dependencies:install edge # install all dependencies using edge strategy
1269
- # merb:dependencies:install edge --sources file.yml # install edge from the specified git sources config
1270
-
1271
- desc 'install [stable|edge] [comp]', 'Install application dependencies'
1272
- method_options "--sources" => :optional, # only for edge strategy
1273
- "--local" => :boolean, # force local install
1274
- "--dry-run" => :boolean,
1275
- "--force" => :boolean
1276
- def install(strategy = 'stable', comp = nil)
1277
- if strategy?(strategy)
1278
- # Force local dependencies by creating ./gems before proceeding
1279
- create_if_missing(default_gem_dir) if options[:local]
1280
-
1281
- where = gem_dir ? 'locally' : 'system-wide'
1282
-
1283
- # When comp == 'missing' then filter on missing dependencies
1284
- if only_missing = comp == 'missing'
1285
- message "Preparing to install missing gems #{where} using #{strategy} strategy..."
1286
- comp = nil
1287
- clobber = false
1288
- else
1289
- message "Preparing to install #{where} using #{strategy} strategy..."
1290
- clobber = true
1291
- end
1292
-
1293
- # If comp given, filter on known stack components
1294
- deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
1295
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1296
-
1297
- # Only install currently missing gems (for comp == missing)
1298
- if only_missing
1299
- deps.reject! { |dep| not missing.include?(dep) }
1300
- end
1301
-
1302
- if deps.empty?
1303
- warning "No dependencies to install..."
1304
- else
1305
- puts "#{deps.length} dependencies to install..."
1306
- puts "This may take a while..."
1307
- install_dependencies(strategy, deps, clobber)
1308
- end
1309
-
1310
- # Show current dependency info now that we're done
1311
- puts # Seperate output
1312
- list('local', comp)
1313
- else
1314
- warning "Invalid install strategy '#{strategy}'"
1315
- puts
1316
- message "Please choose one of the following installation strategies: stable or edge:"
1317
- puts "$ thor merb:dependencies:install stable"
1318
- puts "$ thor merb:dependencies:install edge"
1319
- end
1320
- end
1321
-
1322
- # Uninstall application dependencies.
1323
- #
1324
- # By default all required dependencies are installed. An optional argument
1325
- # can be used to filter on a set of known components.
1326
- #
1327
- # Existing dependencies will be clobbered; when :force => true then all gems
1328
- # will be cleared, otherwise only existing local dependencies of the
1329
- # matching component set will be removed.
1330
- #
1331
- # Examples:
1332
- #
1333
- # merb:dependencies:uninstall # uninstall all dependencies - the default
1334
- # merb:dependencies:uninstall merb-more # uninstall merb-more related gems locally
1335
-
1336
- desc 'uninstall [comp]', 'Uninstall application dependencies'
1337
- method_options "--dry-run" => :boolean, "--force" => :boolean
1338
- def uninstall(comp = nil)
1339
- # If comp given, filter on known stack components
1340
- deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
1341
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1342
- # Clobber existing local dependencies - based on self.local
1343
- clobber_dependencies!
1344
- end
1345
-
1346
- # Recreate all gems from gems/cache on the current platform.
1347
- #
1348
- # Note: use merb:gem:redeploy instead
1349
-
1350
- desc 'redeploy', 'Recreate all gems on the current platform'
1351
- method_options "--dry-run" => :boolean, "--force" => :boolean
1352
- def redeploy
1353
- warning 'Warning: merb:dependencies:redeploy has been deprecated - use merb:gem:redeploy instead'
1354
- gem = Merb::Gem.new
1355
- gem.options = options
1356
- gem.redeploy
1357
- end
1358
-
1359
- # Create a dependencies configuration file.
1360
- #
1361
- # A configuration yaml file will be created from the extracted application
1362
- # dependencies. The format of the configuration is as follows:
1363
- #
1364
- # ---
1365
- # - merb-core (= 0.9.8, runtime)
1366
- # - merb-slices (= 0.9.8, runtime)
1367
- #
1368
- # This format is exactly the same as Gem::Dependency#to_s returns.
1369
- #
1370
- # Examples:
1371
- #
1372
- # merb:dependencies:configure --force # overwrite the default config file
1373
- # merb:dependencies:configure --version 0.9.8 # configure specific framework version
1374
- # merb:dependencies:configure --config-file file.yml # write to the specified config file
1375
-
1376
- desc 'configure [comp]', 'Create a dependencies config file'
1377
- method_options "--dry-run" => :boolean, "--force" => :boolean, "--versions" => :boolean
1378
- def configure(comp = nil)
1379
- self.extract_dependencies = true # of course we need to consult the app itself
1380
- # If comp given, filter on known stack components
1381
- deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
1382
-
1383
- # If --versions is set, update the version_requirements with the actual version available
1384
- if options[:versions]
1385
- specs = local_gemspecs
1386
- deps.each do |dep|
1387
- if spec = specs.find { |s| s.name == dep.name }
1388
- dep.version_requirements = ::Gem::Requirement.create(spec.version)
1389
- end
1390
- end
1391
- end
1392
-
1393
- config = YAML.dump(deps.map { |d| d.to_s })
1394
- puts "#{config}\n"
1395
- if File.exists?(config_file) && !options[:force]
1396
- error "File already exists! Use --force to overwrite."
1397
- else
1398
- if dry_run?
1399
- note "Written #{config_file}"
1400
- else
1401
- FileUtils.mkdir_p(config_dir) unless File.directory?(config_dir)
1402
- File.open(config_file, 'w') { |f| f.write config }
1403
- success "Written #{config_file}"
1404
- end
1405
- end
1406
- rescue
1407
- error "Failed to write to #{config_file}"
1408
- end
1409
-
1410
- ### Helper Methods
1411
-
1412
- def strategy?(strategy)
1413
- if self.respond_to?(method = :"#{strategy}_strategy", true)
1414
- method
1415
- end
1416
- end
1417
-
1418
- def install_dependencies(strategy, deps, clobber = true)
1419
- if method = strategy?(strategy)
1420
- # Clobber existing local dependencies
1421
- clobber_dependencies! if clobber
1422
-
1423
- # Run the chosen strategy - collect files installed from stable gems
1424
- installed_from_stable = send(method, deps).map { |d| d.name }
1425
-
1426
- unless dry_run?
1427
- # Sleep a bit otherwise the following steps won't see the new files
1428
- sleep(deps.length) if deps.length > 0 && deps.length <= 10
1429
-
1430
- # Leave a file to denote the strategy that has been used for this dependency
1431
- self.local.each do |spec|
1432
- next unless File.directory?(spec.full_gem_path)
1433
- unless installed_from_stable.include?(spec.name)
1434
- FileUtils.touch(File.join(spec.full_gem_path, "#{strategy}.strategy"))
1435
- else
1436
- FileUtils.touch(File.join(spec.full_gem_path, "stable.strategy"))
1437
- end
1438
- end
1439
- end
1440
- return true
1441
- end
1442
- false
1443
- end
1444
-
1445
- def dependencies
1446
- if extract_dependencies?
1447
- # Extract dependencies from the current application
1448
- deps = Merb::Stack.core_dependencies(gem_dir, ignore_dependencies?)
1449
- deps += Merb::Dependencies.extract_dependencies(working_dir)
1450
- else
1451
- # Use preconfigured dependencies from yaml file
1452
- deps = config_dependencies
1453
- end
1454
-
1455
- stack_components = Merb::Stack.components
1456
-
1457
- if options[:stack]
1458
- # Limit to stack components only
1459
- deps.reject! { |dep| not stack_components.include?(dep.name) }
1460
- elsif options[:"no-stack"]
1461
- # Limit to non-stack components
1462
- deps.reject! { |dep| stack_components.include?(dep.name) }
1463
- end
1464
-
1465
- if options[:version]
1466
- version_req = ::Gem::Requirement.create("= #{options[:version]}")
1467
- elsif core = deps.find { |d| d.name == 'merb-core' }
1468
- version_req = core.version_requirements
1469
- end
1470
-
1471
- if version_req
1472
- # Handle specific version requirement for framework components
1473
- framework_components = Merb::Stack.framework_components
1474
- deps.each do |dep|
1475
- if framework_components.include?(dep.name)
1476
- dep.version_requirements = version_req
1477
- end
1478
- end
1479
- end
1480
-
1481
- deps
1482
- end
1483
-
1484
- def config_dependencies
1485
- if File.exists?(config_file)
1486
- self.class.parse_dependencies_yaml(File.read(config_file))
1487
- else
1488
- warning "No dependencies.yml file found at: #{config_file}"
1489
- []
1490
- end
1491
- end
1492
-
1493
- def extract_dependencies?
1494
- options[:extract] || extract_dependencies
1495
- end
1496
-
1497
- def config_file
1498
- @config_file ||= begin
1499
- options[:"config-file"] || File.join(working_dir, 'config', 'dependencies.yml')
1500
- end
1501
- end
1502
-
1503
- def config_dir
1504
- File.dirname(config_file)
1505
- end
1506
-
1507
- ### Strategy handlers
1508
-
1509
- private
1510
-
1511
- def stable_strategy(deps)
1512
- installed_from_rubygems = []
1513
- if core = deps.find { |d| d.name == 'merb-core' }
1514
- if dry_run?
1515
- note "Installing #{core.name}..."
1516
- else
1517
- if install_dependency(core)
1518
- installed_from_rubygems << core
1519
- else
1520
- msg = "Try specifying a lower version of merb-core with --version"
1521
- if version_no = core.version_requirements.to_s[/([\.\d]+)$/, 1]
1522
- num = "%03d" % (version_no.gsub('.', '').to_i - 1)
1523
- puts "The required version (#{version_no}) probably isn't available as a stable rubygem yet."
1524
- info "#{msg} #{num.split(//).join('.')}"
1525
- else
1526
- puts "The required version probably isn't available as a stable rubygem yet."
1527
- info msg
1528
- end
1529
- end
1530
- end
1531
- end
1532
-
1533
- deps.each do |dependency|
1534
- next if dependency.name == 'merb-core'
1535
- if dry_run?
1536
- note "Installing #{dependency.name}..."
1537
- else
1538
- install_dependency(dependency)
1539
- installed_from_rubygems << dependency
1540
- end
1541
- end
1542
- installed_from_rubygems
1543
- end
1544
-
1545
- def edge_strategy(deps)
1546
- use_edge_gem_server
1547
- installed_from_rubygems = []
1548
-
1549
- # Selectively update repositories for the matching dependencies
1550
- update_dependency_repositories(deps) unless dry_run?
1551
-
1552
- if core = deps.find { |d| d.name == 'merb-core' }
1553
- if dry_run?
1554
- note "Installing #{core.name}..."
1555
- else
1556
- if install_dependency_from_source(core)
1557
- elsif install_dependency(core)
1558
- info "Installed #{core.name} from rubygems..."
1559
- installed_from_rubygems << core
1560
- end
1561
- end
1562
- end
1563
-
1564
- deps.each do |dependency|
1565
- next if dependency.name == 'merb-core'
1566
- if dry_run?
1567
- note "Installing #{dependency.name}..."
1568
- else
1569
- if install_dependency_from_source(dependency)
1570
- elsif install_dependency(dependency)
1571
- info "Installed #{dependency.name} from rubygems..."
1572
- installed_from_rubygems << dependency
1573
- end
1574
- end
1575
- end
1576
-
1577
- installed_from_rubygems
1578
- end
1579
-
1580
- ### Class Methods
1581
-
1582
- public
1583
-
1584
- def self.list(filter = 'all', comp = nil, options = {})
1585
- instance = Merb::Dependencies.new
1586
- instance.options = options
1587
- instance.list(filter, comp)
1588
- end
1589
-
1590
- # Extract application dependencies by querying the app directly.
1591
- def self.extract_dependencies(merb_root)
1592
- require 'merb-core'
1593
- if !@_merb_loaded || Merb.root != merb_root
1594
- Merb.start_environment(
1595
- :log_level => :fatal,
1596
- :testing => true,
1597
- :adapter => 'runner',
1598
- :environment => ENV['MERB_ENV'] || 'development',
1599
- :merb_root => merb_root
1600
- )
1601
- @_merb_loaded = true
1602
- end
1603
- Merb::BootLoader::Dependencies.dependencies
1604
- rescue StandardError => e
1605
- error "Couldn't extract dependencies from application!"
1606
- error e.message
1607
- puts "Make sure you're executing the task from your app (--merb-root)"
1608
- return []
1609
- rescue SystemExit
1610
- error "Couldn't extract dependencies from application!"
1611
- error "application failed to run"
1612
- puts "Please check if your application runs using 'merb'; for example,"
1613
- puts "look for any gem version mismatches in dependencies.rb"
1614
- return []
1615
- end
1616
-
1617
- # Parse the basic YAML config data, and process Gem::Dependency output.
1618
- # Formatting example: merb_helpers (>= 0.9.8, runtime)
1619
- def self.parse_dependencies_yaml(yaml)
1620
- dependencies = []
1621
- entries = YAML.load(yaml) rescue []
1622
- entries.each do |entry|
1623
- if matches = entry.match(/^(\S+) \(([^,]+)?, ([^\)]+)\)/)
1624
- name, version_req, type = matches.captures
1625
- dependencies << ::Gem::Dependency.new(name, version_req, type.to_sym)
1626
- else
1627
- error "Invalid entry: #{entry}"
1628
- end
1629
- end
1630
- dependencies
1631
- end
1632
-
1633
- end
1634
-
1635
- class Stack < Thor
1636
-
1637
- group 'core'
1638
-
1639
- # The Stack tasks will install dependencies based on known sets of gems,
1640
- # regardless of actual application dependency settings.
1641
-
1642
- DM_STACK = %w[
1643
- extlib
1644
- data_objects
1645
- dm-core
1646
- dm-aggregates
1647
- dm-migrations
1648
- dm-timestamps
1649
- dm-types
1650
- dm-validations
1651
- merb_datamapper
1652
- ]
1653
-
1654
- MERB_STACK = %w[
1655
- extlib
1656
- merb-core
1657
- merb-action-args
1658
- merb-assets
1659
- merb-cache
1660
- merb-helpers
1661
- merb-mailer
1662
- merb-slices
1663
- merb-auth
1664
- merb-auth-core
1665
- merb-auth-more
1666
- merb-auth-slice-password
1667
- merb-param-protection
1668
- merb-exceptions
1669
- ] + DM_STACK
1670
-
1671
- MERB_BASICS = %w[
1672
- extlib
1673
- merb-core
1674
- merb-action-args
1675
- merb-assets
1676
- merb-cache
1677
- merb-helpers
1678
- merb-mailer
1679
- merb-slices
1680
- ]
1681
-
1682
- # The following sets are meant for repository lookup; unlike the sets above
1683
- # these correspond to specific git repository items.
1684
-
1685
- MERB_MORE = %w[
1686
- merb-action-args
1687
- merb-assets
1688
- merb-auth
1689
- merb-auth-core
1690
- merb-auth-more
1691
- merb-auth-slice-password
1692
- merb-cache
1693
- merb-exceptions
1694
- merb-gen
1695
- merb-haml
1696
- merb-helpers
1697
- merb-mailer
1698
- merb-param-protection
1699
- merb-slices
1700
- merb_datamapper
1701
- ]
1702
-
1703
- MERB_PLUGINS = %w[
1704
- merb_activerecord
1705
- merb_builder
1706
- merb_jquery
1707
- merb_laszlo
1708
- merb_parts
1709
- merb_screw_unit
1710
- merb_sequel
1711
- merb_stories
1712
- merb_test_unit
1713
- ]
1714
-
1715
- DM_MORE = %w[
1716
- dm-adjust
1717
- dm-aggregates
1718
- dm-ar-finders
1719
- dm-cli
1720
- dm-constraints
1721
- dm-is-example
1722
- dm-is-list
1723
- dm-is-nested_set
1724
- dm-is-remixable
1725
- dm-is-searchable
1726
- dm-is-state_machine
1727
- dm-is-tree
1728
- dm-is-versioned
1729
- dm-migrations
1730
- dm-observer
1731
- dm-querizer
1732
- dm-serializer
1733
- dm-shorthand
1734
- dm-sweatshop
1735
- dm-tags
1736
- dm-timestamps
1737
- dm-types
1738
- dm-validations
1739
-
1740
- dm-couchdb-adapter
1741
- dm-ferret-adapter
1742
- dm-rest-adapter
1743
- ]
1744
-
1745
- DATA_OBJECTS = %w[
1746
- data_objects
1747
- do_derby do_hsqldb
1748
- do_jdbc
1749
- do_mysql
1750
- do_postgres
1751
- do_sqlite3
1752
- ]
1753
-
1754
- attr_accessor :system, :local, :missing
1755
-
1756
- include MerbThorHelper
1757
-
1758
- global_method_options = {
1759
- "--merb-root" => :optional, # the directory to operate on
1760
- "--ignore-dependencies" => :boolean, # skip sub-dependencies
1761
- "--version" => :optional # gather specific version of framework
1762
- }
1763
-
1764
- method_options global_method_options
1765
- def initialize(*args); super; end
1766
-
1767
- # List components and their dependencies.
1768
- #
1769
- # Examples:
1770
- #
1771
- # merb:stack:list # list all standard stack components
1772
- # merb:stack:list all # list all component sets
1773
- # merb:stack:list merb-more # list all dependencies of merb-more
1774
-
1775
- desc 'list [all|comp]', 'List available components (optionally filtered, defaults to merb stack)'
1776
- def list(comp = 'stack')
1777
- if comp == 'all'
1778
- Merb::Stack.component_sets.keys.sort.each do |comp|
1779
- unless (components = Merb::Stack.component_sets[comp]).empty?
1780
- message "Dependencies for '#{comp}' set:"
1781
- components.each { |c| puts "- #{c}" }
1782
- end
1783
- end
1784
- else
1785
- message "Dependencies for '#{comp}' set:"
1786
- Merb::Stack.components(comp).each { |c| puts "- #{c}" }
1787
- end
1788
- end
1789
-
1790
- # Install stack components or individual gems - from stable rubygems by default.
1791
- #
1792
- # See also: Merb::Dependencies#install and Merb::Dependencies#install_dependencies
1793
- #
1794
- # Examples:
1795
- #
1796
- # merb:stack:install # install the default merb stack
1797
- # merb:stack:install basics # install a basic set of dependencies
1798
- # merb:stack:install merb-core # install merb-core from stable
1799
- # merb:stack:install merb-more --edge # install merb-core from edge
1800
- # merb:stack:install merb-core thor merb-slices # install the specified gems
1801
-
1802
- desc 'install [COMP, ...]', 'Install stack components'
1803
- method_options "--edge" => :boolean,
1804
- "--sources" => :optional,
1805
- "--force" => :boolean,
1806
- "--dry-run" => :boolean,
1807
- "--strategy" => :optional
1808
- def install(*comps)
1809
- use_edge_gem_server if options[:edge]
1810
- mngr = self.dependency_manager
1811
- deps = gather_dependencies(comps)
1812
- mngr.system, mngr.local, mngr.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1813
- mngr.install_dependencies(strategy, deps)
1814
- end
1815
-
1816
- # Uninstall stack components or individual gems.
1817
- #
1818
- # See also: Merb::Dependencies#uninstall
1819
- #
1820
- # Examples:
1821
- #
1822
- # merb:stack:uninstall # uninstall the default merb stack
1823
- # merb:stack:uninstall merb-more # uninstall merb-more
1824
- # merb:stack:uninstall merb-core thor merb-slices # uninstall the specified gems
1825
-
1826
- desc 'uninstall [COMP, ...]', 'Uninstall stack components'
1827
- method_options "--dry-run" => :boolean, "--force" => :boolean
1828
- def uninstall(*comps)
1829
- deps = gather_dependencies(comps)
1830
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1831
- # Clobber existing local dependencies - based on self.local
1832
- clobber_dependencies!
1833
- end
1834
-
1835
- # Install or uninstall minigems from the system.
1836
- #
1837
- # Due to the specific nature of MiniGems it can only be installed system-wide.
1838
- #
1839
- # Examples:
1840
- #
1841
- # merb:stack:minigems install # install minigems
1842
- # merb:stack:minigems uninstall # uninstall minigems
1843
-
1844
- desc 'minigems (install|uninstall)', 'Install or uninstall minigems (needs sudo privileges)'
1845
- def minigems(action)
1846
- case action
1847
- when 'install'
1848
- Kernel.system "#{sudo} thor merb:stack:install_minigems"
1849
- when 'uninstall'
1850
- Kernel.system "#{sudo} thor merb:stack:uninstall_minigems"
1851
- else
1852
- error "Invalid command: merb:stack:minigems #{action}"
1853
- end
1854
- end
1855
-
1856
- # hidden minigems install task
1857
- def install_minigems
1858
- message "Installing MiniGems"
1859
- mngr = self.dependency_manager
1860
- deps = gather_dependencies('minigems')
1861
- mngr.system, mngr.local, mngr.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1862
- mngr.force_gem_dir = ::Gem.dir
1863
- mngr.install_dependencies(strategy, deps)
1864
- Kernel.system "#{sudo} minigem install"
1865
- end
1866
-
1867
- # hidden minigems uninstall task
1868
- def uninstall_minigems
1869
- message "Uninstalling MiniGems"
1870
- Kernel.system "#{sudo} minigem uninstall"
1871
- deps = gather_dependencies('minigems')
1872
- self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
1873
- # Clobber existing local dependencies - based on self.local
1874
- clobber_dependencies!
1875
- end
1876
-
1877
- protected
1878
-
1879
- def gather_dependencies(comps = [])
1880
- if comps.empty?
1881
- gems = MERB_STACK
1882
- else
1883
- gems = comps.map { |c| Merb::Stack.components(c) }.flatten
1884
- end
1885
-
1886
- version_req = if options[:version]
1887
- ::Gem::Requirement.create(options[:version])
1888
- end
1889
-
1890
- framework_components = Merb::Stack.framework_components
1891
-
1892
- gems.map do |gem|
1893
- if version_req && framework_components.include?(gem)
1894
- ::Gem::Dependency.new(gem, version_req)
1895
- else
1896
- ::Gem::Dependency.new(gem, ::Gem::Requirement.default)
1897
- end
1898
- end
1899
- end
1900
-
1901
- def strategy
1902
- options[:strategy] || (options[:edge] ? 'edge' : 'stable')
1903
- end
1904
-
1905
- def dependency_manager
1906
- @_dependency_manager ||= begin
1907
- instance = Merb::Dependencies.new
1908
- instance.options = options
1909
- instance
1910
- end
1911
- end
1912
-
1913
- public
1914
-
1915
- def self.repository_sets
1916
- @_repository_sets ||= begin
1917
- # the component itself as a fallback
1918
- comps = Hash.new { |(hsh,c)| [c] }
1919
-
1920
- # git repository based component sets
1921
- comps["merb"] = ["merb-core"] + MERB_MORE
1922
- comps["merb-more"] = MERB_MORE.sort
1923
- comps["merb-plugins"] = MERB_PLUGINS.sort
1924
- comps["dm-more"] = DM_MORE.sort
1925
- comps["do"] = DATA_OBJECTS.sort
1926
-
1927
- comps
1928
- end
1929
- end
1930
-
1931
- def self.component_sets
1932
- @_component_sets ||= begin
1933
- # the component itself as a fallback
1934
- comps = Hash.new { |(hsh,c)| [c] }
1935
- comps.update(repository_sets)
1936
-
1937
- # specific set of dependencies
1938
- comps["stack"] = MERB_STACK.sort
1939
- comps["basics"] = MERB_BASICS.sort
1940
-
1941
- # orm dependencies
1942
- comps["datamapper"] = DM_STACK.sort
1943
- comps["sequel"] = ["merb_sequel", "sequel"]
1944
- comps["activerecord"] = ["merb_activerecord", "activerecord"]
1945
-
1946
- comps
1947
- end
1948
- end
1949
-
1950
- def self.framework_components
1951
- %w[merb-core merb-more].inject([]) do |all, comp|
1952
- all + components(comp)
1953
- end
1954
- end
1955
-
1956
- def self.components(comp = nil)
1957
- if comp
1958
- component_sets[comp]
1959
- else
1960
- comps = %w[merb-core merb-more merb-plugins dm-core dm-more]
1961
- comps.inject([]) do |all, grp|
1962
- all + (component_sets[grp] || [])
1963
- end
1964
- end
1965
- end
1966
-
1967
- def self.select_component_dependencies(dependencies, comp = nil)
1968
- comps = components(comp) || []
1969
- dependencies.select { |dep| comps.include?(dep.name) }
1970
- end
1971
-
1972
- def self.base_components
1973
- %w[thor rake extlib]
1974
- end
1975
-
1976
- def self.all_components
1977
- base_components + framework_components
1978
- end
1979
-
1980
- # Find the latest merb-core and gather its dependencies.
1981
- # We check for 0.9.8 as a minimum release version.
1982
- def self.core_dependencies(gem_dir = nil, ignore_deps = false)
1983
- @_core_dependencies ||= begin
1984
- if gem_dir # add local gems to index
1985
- orig_gem_path = ::Gem.path
1986
- ::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
1987
- end
1988
- deps = []
1989
- merb_core = ::Gem::Dependency.new('merb-core', '>= 0.9.8')
1990
- if gemspec = ::Gem.source_index.search(merb_core).last
1991
- deps << ::Gem::Dependency.new('merb-core', gemspec.version)
1992
- if ignore_deps
1993
- deps += gemspec.dependencies.select do |d|
1994
- base_components.include?(d.name)
1995
- end
1996
- else
1997
- deps += gemspec.dependencies
1998
- end
1999
- end
2000
- ::Gem.path.replace(orig_gem_path) if gem_dir # reset
2001
- deps
2002
- end
2003
- end
2004
-
2005
- def self.lookup_repository_name(item)
2006
- set_name = nil
2007
- # The merb repo contains -more as well, so it needs special attention
2008
- return 'merb' if self.repository_sets['merb'].include?(item)
2009
-
2010
- # Proceed with finding the item in a known component set
2011
- self.repository_sets.find do |set, items|
2012
- next if set == 'merb'
2013
- items.include?(item) ? (set_name = set) : nil
2014
- end
2015
- set_name
2016
- end
2017
-
2018
- end
2019
-
2020
- end