merb-gen 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/LICENSE +1 -1
  2. data/Rakefile +27 -9
  3. data/bin/merb-gen +21 -3
  4. data/lib/generators/merb/merb_flat.rb +83 -14
  5. data/lib/generators/merb/merb_full.rb +66 -20
  6. data/lib/generators/merb/merb_very_flat.rb +51 -10
  7. data/lib/generators/migration.rb +5 -2
  8. data/lib/generators/resource_controller.rb +2 -2
  9. data/lib/generators/templates/application/{merb → common}/Rakefile +15 -7
  10. data/lib/generators/templates/application/common/dotgitignore +18 -0
  11. data/lib/generators/templates/application/common/merb.thor +1221 -0
  12. data/lib/generators/templates/application/merb/app/views/exceptions/not_acceptable.html.erb +1 -1
  13. data/lib/generators/templates/application/merb/app/views/exceptions/not_found.html.erb +1 -1
  14. data/lib/generators/templates/application/merb/config/environments/development.rb +1 -0
  15. data/lib/generators/templates/application/merb/config/environments/staging.rb +7 -0
  16. data/lib/generators/templates/application/merb/config/environments/test.rb +2 -1
  17. data/lib/generators/templates/application/merb/config/init.rb +1 -4
  18. data/lib/generators/templates/application/merb/config/router.rb +13 -7
  19. data/lib/generators/templates/application/merb/public/favicon.ico +0 -0
  20. data/lib/generators/templates/application/merb/public/robots.txt +5 -0
  21. data/lib/generators/templates/application/merb_flat/{application.rb → application.rbt} +1 -1
  22. data/lib/generators/templates/application/merb_flat/config/init.rb +119 -2
  23. data/lib/generators/templates/application/merb_flat/test/test_helper.rb +19 -0
  24. data/lib/generators/templates/application/merb_plugin/Rakefile +17 -22
  25. data/lib/generators/templates/application/merb_plugin/spec/spec_helper.rb +0 -1
  26. data/lib/generators/templates/application/merb_plugin/test/test_helper.rb +0 -1
  27. data/lib/generators/templates/application/merb_very_flat/application.rbt +36 -2
  28. data/lib/generators/templates/application/merb_very_flat/test/test_helper.rb +19 -0
  29. data/spec/merb_flat_spec.rb +4 -4
  30. data/spec/spec_helper.rb +0 -1
  31. metadata +16 -7
  32. data/lib/generators/templates/application/merb/merb.thor +0 -822
@@ -1,822 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'rubygems'
3
- require 'rubygems/dependency_installer'
4
- require 'rubygems/uninstaller'
5
- require 'thor'
6
- require 'fileutils'
7
- require 'yaml'
8
-
9
- module MerbThorHelper
10
-
11
- private
12
-
13
- # The current working directory, or Merb app root (--merb-root option).
14
- def working_dir
15
- @_working_dir ||= File.expand_path(options['merb-root'] || Dir.pwd)
16
- end
17
-
18
- # We should have a ./src dir for local and system-wide management.
19
- def source_dir
20
- @_source_dir ||= File.join(working_dir, 'src')
21
- create_if_missing(@_source_dir)
22
- @_source_dir
23
- end
24
-
25
- # If a local ./gems dir is found, it means we are in a Merb app.
26
- def application?
27
- gem_dir
28
- end
29
-
30
- # If a local ./gems dir is found, return it.
31
- def gem_dir
32
- if File.directory?(dir = File.join(working_dir, 'gems'))
33
- dir
34
- end
35
- end
36
-
37
- # If we're in a Merb app, we can have a ./bin directory;
38
- # create it if it's not there.
39
- def bin_dir
40
- @_bin_dir ||= begin
41
- if gem_dir
42
- dir = File.join(working_dir, 'bin')
43
- create_if_missing(dir)
44
- dir
45
- end
46
- end
47
- end
48
-
49
- # Helper to create dir unless it exists.
50
- def create_if_missing(path)
51
- FileUtils.mkdir(path) unless File.exists?(path)
52
- end
53
-
54
- # Create a modified executable wrapper in the app's ./bin directory.
55
- def ensure_local_bin_for(*gems)
56
- if bin_dir && File.directory?(bin_dir)
57
- gems.each do |gem|
58
- if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{gem}-*.gemspec")].last
59
- spec = Gem::Specification.load(gemspec_path)
60
- spec.executables.each do |exec|
61
- if File.exists?(executable = File.join(gem_dir, 'bin', exec))
62
- local_executable = File.join(bin_dir, exec)
63
- puts "Adding local executable #{local_executable}"
64
- File.open(local_executable, 'w', 0755) do |f|
65
- f.write(executable_wrapper(spec, exec))
66
- end
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
73
-
74
- def executable_wrapper(spec, bin_file_name)
75
- <<-TEXT
76
- #!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}
77
- #
78
- # This file was generated by merb.thor.
79
- #
80
- # The application '#{spec.name}' is installed as part of a gem, and
81
- # this file is here to facilitate running it.
82
- #
83
-
84
- require 'rubygems'
85
-
86
- if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems'))
87
- $BUNDLE = true; Gem.clear_paths; Gem.path.unshift(gems_dir)
88
- end
89
-
90
- version = "#{Gem::Requirement.default}"
91
-
92
- if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
93
- version = $1
94
- ARGV.shift
95
- end
96
-
97
- gem '#{spec.name}', version
98
- load '#{bin_file_name}'
99
- TEXT
100
- end
101
-
102
- end
103
-
104
- # TODO
105
- # - a task to figure out an app's dependencies
106
- # - pulling a specific UUID/Tag (gitspec hash) with clone/update
107
- # - a 'deploy' task (in addition to 'redeploy' ?)
108
- # - eventually take a --orm option for the 'merb-stack' type of tasks
109
-
110
- class Merb < Thor
111
-
112
- class SourcePathMissing < Exception
113
- end
114
-
115
- class GemPathMissing < Exception
116
- end
117
-
118
- class GemInstallError < Exception
119
- end
120
-
121
- class GemUninstallError < Exception
122
- end
123
-
124
- # Install a Merb stack from stable RubyForge gems. Optionally install a
125
- # suitable Rack adapter/server when setting --adapter to one of the
126
- # following: mongrel, emongrel, thin or ebb.
127
-
128
- desc 'stable', 'Install extlib, merb-core and merb-more from rubygems'
129
- method_options "--merb-root" => :optional,
130
- "--adapter" => :optional
131
- def stable
132
- adapters = %w[mongrel emongrel thin ebb]
133
- stable = Stable.new
134
- stable.options = options
135
- if stable.core && stable.more
136
- puts "Installed extlib, merb-core and merb-more"
137
- if options[:adapter] && adapters.include?(options[:adapter]) &&
138
- stable.refresh_from_gems(options[:adapter])
139
- puts "Installed #{options[:adapter]}"
140
- elsif options[:adapter]
141
- puts "Please specify one of the following adapters: #{adapters.join(' ')}"
142
- end
143
- end
144
- end
145
-
146
- class Stable < Thor
147
-
148
- # The Stable tasks deal with known -stable- gems; available
149
- # as shortcuts to Merb and DataMapper gems.
150
- #
151
- # These are pulled from rubyforge and installed into into the
152
- # desired gems dir (either system-wide or into the application's
153
- # gems directory).
154
-
155
- include MerbThorHelper
156
-
157
- # Gets latest gem versions from RubyForge and installs them.
158
- #
159
- # Examples:
160
- #
161
- # thor merb:edge:core
162
- # thor merb:edge:core --merb-root ./path/to/your/app
163
- # thor merb:edge:core --sources ./path/to/sources.yml
164
-
165
- desc 'core', 'Install extlib and merb-core from git HEAD'
166
- method_options "--merb-root" => :optional
167
- def core
168
- refresh_from_gems 'extlib', 'merb-core'
169
- ensure_local_bin_for('merb-core', 'rake', 'rspec', 'thor')
170
- end
171
-
172
- desc 'more', 'Install merb-more from rubygems'
173
- method_options "--merb-root" => :optional
174
- def more
175
- refresh_from_gems 'merb-more'
176
- ensure_local_bin_for('merb-gen')
177
- end
178
-
179
- desc 'plugins', 'Install merb-plugins from rubygems'
180
- method_options "--merb-root" => :optional
181
- def plugins
182
- refresh_from_gems 'merb-plugins'
183
- end
184
-
185
- desc 'dm_core', 'Install dm-core from rubygems'
186
- method_options "--merb-root" => :optional
187
- def dm_core
188
- refresh_from_gems 'extlib', 'dm-core'
189
- end
190
-
191
- desc 'dm_more', 'Install dm-more from rubygems'
192
- method_options "--merb-root" => :optional
193
- def dm_more
194
- refresh_from_gems 'extlib', 'dm-core', 'dm-more'
195
- end
196
-
197
- # Pull from RubyForge and install.
198
- def refresh_from_gems(*components)
199
- gems = Gems.new
200
- gems.options = options
201
- components.all? { |name| gems.install(name) }
202
- end
203
-
204
- end
205
-
206
- # Retrieve latest Merb versions from git and optionally install them.
207
- #
208
- # Note: the --sources option takes a path to a YAML file
209
- # with a regular Hash mapping gem names to git urls.
210
- #
211
- # Examples:
212
- #
213
- # thor merb:edge
214
- # thor merb:edge --install
215
- # thor merb:edge --merb-root ./path/to/your/app
216
- # thor merb:edge --sources ./path/to/sources.yml
217
-
218
- desc 'edge', 'Install extlib, merb-core and merb-more from git HEAD'
219
- method_options "--merb-root" => :optional,
220
- "--sources" => :optional,
221
- "--install" => :boolean
222
- def edge
223
- edge = Edge.new
224
- edge.options = options
225
- edge.core
226
- edge.more
227
- end
228
-
229
- class Edge < Thor
230
-
231
- # The Edge tasks deal with known gems from the bleeding edge; available
232
- # as shortcuts to Merb and DataMapper gems.
233
- #
234
- # These are pulled from git and optionally installed into into the
235
- # desired gems dir (either system-wide or into the application's
236
- # gems directory).
237
-
238
- include MerbThorHelper
239
-
240
- # Gets latest gem versions from git - optionally installs them.
241
- #
242
- # Note: the --sources option takes a path to a YAML file
243
- # with a regular Hash mapping gem names to git urls,
244
- # allowing pulling forks of the official repositories.
245
- #
246
- # Examples:
247
- #
248
- # thor merb:edge:core
249
- # thor merb:edge:core --install
250
- # thor merb:edge:core --merb-root ./path/to/your/app
251
- # thor merb:edge:core --sources ./path/to/sources.yml
252
-
253
- desc 'core', 'Update extlib and merb-core from git HEAD'
254
- method_options "--merb-root" => :optional,
255
- "--sources" => :optional,
256
- "--install" => :boolean
257
- def core
258
- refresh_from_source 'thor', 'extlib', 'merb-core'
259
- ensure_local_bin_for('merb-core', 'rake', 'rspec', 'thor')
260
- end
261
-
262
- desc 'more', 'Update merb-more from git HEAD'
263
- method_options "--merb-root" => :optional,
264
- "--sources" => :optional,
265
- "--install" => :boolean
266
- def more
267
- refresh_from_source 'merb-more'
268
- ensure_local_bin_for('merb-gen')
269
- end
270
-
271
- desc 'plugins', 'Update merb-plugins from git HEAD'
272
- method_options "--merb-root" => :optional,
273
- "--sources" => :optional,
274
- "--install" => :boolean
275
- def plugins
276
- refresh_from_source 'merb-plugins'
277
- end
278
-
279
- desc 'dm_core', 'Update dm-core from git HEAD'
280
- method_options "--merb-root" => :optional,
281
- "--sources" => :optional,
282
- "--install" => :boolean
283
- def dm_core
284
- refresh_from_source 'extlib', 'dm-core'
285
- end
286
-
287
- desc 'dm_more', 'Update dm-more from git HEAD'
288
- method_options "--merb-root" => :optional,
289
- "--sources" => :optional,
290
- "--install" => :boolean
291
- def dm_more
292
- refresh_from_source 'extlib', 'dm-core', 'dm-more'
293
- end
294
-
295
- private
296
-
297
- # Pull from git and optionally install the resulting gems.
298
- def refresh_from_source(*components)
299
- source = Source.new
300
- source.options = options
301
- components.each do |name|
302
- source.clone(name)
303
- source.install(name) if options[:install]
304
- end
305
- end
306
-
307
- end
308
-
309
- class Source < Thor
310
-
311
- # The Source tasks deal with gem source packages - mainly from github.
312
- # Any directory inside ./src is regarded as a gem that can be packaged
313
- # and installed from there into the desired gems dir (either system-wide
314
- # or into the application's gems directory).
315
-
316
- include MerbThorHelper
317
-
318
- # Install a particular gem from source.
319
- #
320
- # If a local ./gems dir is found, or --merb-root is given
321
- # the gems will be installed locally into that directory.
322
- #
323
- # Note that this task doesn't retrieve any (new) source from git;
324
- # To update and install you'd execute the following two tasks:
325
- #
326
- # thor merb:source:update merb-core
327
- # thor merb:source:install merb-core
328
- #
329
- # Alternatively, look at merb:edge and merb:edge:* with --install.
330
- #
331
- # Examples:
332
- #
333
- # thor merb:source:install merb-core
334
- # thor merb:source:install merb-more
335
- # thor merb:source:install merb-more/merb-slices
336
- # thor merb:source:install merb-plugins/merb_helpers
337
- # thor merb:source:install merb-core --merb-root ./path/to/your/app
338
-
339
- desc 'install GEM_NAME', 'Install a rubygem from (git) source'
340
- method_options "--merb-root" => :optional
341
- def install(name)
342
- puts "Installing #{name}..."
343
- gem_src_dir = File.join(source_dir, name)
344
- opts = {}
345
- opts[:install_dir] = gem_dir if gem_dir
346
- Merb.install_gem_from_src(gem_src_dir, opts)
347
- rescue Merb::SourcePathMissing
348
- puts "Missing rubygem source path: #{gem_src_dir}"
349
- rescue Merb::GemPathMissing
350
- puts "Missing rubygems path: #{gem_dir}"
351
- rescue => e
352
- puts "Failed to install #{name} (#{e.message})"
353
- end
354
-
355
- # Clone a git repository into ./src. The repository can be
356
- # a direct git url or a known -named- repository.
357
- #
358
- # Examples:
359
- #
360
- # thor merb:source:clone dm-core
361
- # thor merb:source:clone dm-core --sources ./path/to/sources.yml
362
- # thor merb:source:clone git://github.com/sam/dm-core.git
363
-
364
- desc 'clone REPOSITORY', 'Clone a git repository into ./src'
365
- method_options "--sources" => :optional
366
- def clone(repository)
367
- if repository =~ /^git:\/\//
368
- repository_url = repository
369
- elsif url = Merb.repos(options[:sources])[repository]
370
- repository_url = url
371
- end
372
-
373
- if repository_url
374
- repository_name = repository_url[/([\w+|-]+)\.git/u, 1]
375
- fork_name = repository_url[/.com\/+?(.+)\/.+\.git/u, 1]
376
- local_repo_path = "#{source_dir}/#{repository_name}"
377
-
378
- if File.directory?(local_repo_path)
379
- puts "\n#{repository_name} repository exists, updating or branching instead of cloning..."
380
- FileUtils.cd(local_repo_path) do
381
-
382
- # to avoid conflicts we need to set a remote branch for non official repos
383
- existing_repos = `git remote -v`.split("\n").map{|branch| branch.split(/\s+/)}
384
- origin_repo_url = existing_repos.detect{ |r| r.first == "origin" }.last
385
-
386
- # pull from the original repository - no branching needed
387
- if repository_url == origin_repo_url
388
- puts "Pulling from #{repository_url}"
389
- system %{
390
- git fetch
391
- git checkout master
392
- git rebase origin/master
393
- }
394
- # update and switch to a branch for a particular github fork
395
- elsif existing_repos.map{ |r| r.last }.include?(repository_url)
396
- puts "Switching to remote branch: #{fork_name}"
397
- `git checkout -b #{fork_name} #{fork_name}/master`
398
- `git rebase #{fork_name}/master`
399
- # create a new remote branch for a particular github fork
400
- else
401
- puts "Add a new remote branch: #{fork_name}"
402
- `git remote add -f #{fork_name} #{repository_url}`
403
- `git checkout -b#{fork_name} #{fork_name}/master`
404
- end
405
- end
406
- else
407
- FileUtils.cd(source_dir) do
408
- puts "\nCloning #{repository_name} repository from #{repository_url}..."
409
- system("git clone --depth=1 #{repository_url} ")
410
- end
411
- end
412
- else
413
- puts "No valid repository url given"
414
- end
415
- end
416
-
417
- # Update a specific gem source directory from git. See #clone.
418
-
419
- desc 'update REPOSITORY_URL', 'Update a git repository in ./src'
420
- alias :update :clone
421
-
422
- # Update all gem sources from git - based on the current branch.
423
-
424
- desc 'refresh', 'Pull fresh copies of all source gems'
425
- def refresh
426
- repos = Dir["#{source_dir}/*"]
427
- repos.each do |repo|
428
- next unless File.directory?(repo) && File.exists?(File.join(repo, '.git'))
429
- FileUtils.cd(repo) do
430
- puts "Refreshing #{File.basename(repo)}"
431
- branch = `git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1) /'`[/\* (.+)/, 1]
432
- system %{git rebase #{branch}}
433
- end
434
- end
435
- end
436
-
437
- end
438
-
439
- class Gems < Thor
440
-
441
- # The Gems tasks deal directly with rubygems, either through remotely
442
- # available sources (rubyforge for example) or by searching the
443
- # system-wide gem cache for matching gems. The gems are installed from
444
- # there into the desired gems dir (either system-wide or into the
445
- # application's gems directory).
446
-
447
- include MerbThorHelper
448
-
449
- # Install a gem and its dependencies.
450
- #
451
- # If a local ./gems dir is found, or --merb-root is given
452
- # the gems will be installed locally into that directory.
453
- #
454
- # The option --cache will look in the system's gem cache
455
- # for the latest version and install it in the apps' gems.
456
- # This is particularly handy for gems that aren't available
457
- # through rubyforge.org - like in-house merb slices etc.
458
- #
459
- # Examples:
460
- #
461
- # thor merb:gems:install merb-core
462
- # thor merb:gems:install merb-core --cache
463
- # thor merb:gems:install merb-core --version 0.9.7
464
- # thor merb:gems:install merb-core --merb-root ./path/to/your/app
465
-
466
- desc 'install GEM_NAME', 'Install a gem from rubygems'
467
- method_options "--version" => :optional,
468
- "--merb-root" => :optional,
469
- "--cache" => :boolean
470
- def install(name)
471
- puts "Installing #{name}..."
472
- opts = {}
473
- opts[:version] = options[:version]
474
- opts[:cache] = options[:cache] if gem_dir
475
- opts[:install_dir] = gem_dir if gem_dir
476
- Merb.install_gem(name, opts)
477
- rescue => e
478
- puts "Failed to install #{name} (#{e.message})"
479
- end
480
-
481
- # Update a gem and its dependencies.
482
- #
483
- # If a local ./gems dir is found, or --merb-root is given
484
- # the gems will be installed locally into that directory.
485
- #
486
- # The option --cache will look in the system's gem cache
487
- # for the latest version and install it in the apps' gems.
488
- # This is particularly handy for gems that aren't available
489
- # through rubyforge.org - like in-house merb slices etc.
490
- #
491
- # Examples:
492
- #
493
- # thor merb:gems:update merb-core
494
- # thor merb:gems:update merb-core --cache
495
- # thor merb:gems:update merb-core --merb-root ./path/to/your/app
496
-
497
- desc 'update GEM_NAME', 'Update a gem from rubygems'
498
- method_options "--merb-root" => :optional,
499
- "--cache" => :boolean
500
- def update(name)
501
- puts "Updating #{name}..."
502
- opts = {}
503
- if gem_dir
504
- if gemspec_path = Dir[File.join(gem_dir, 'specifications', "#{name}-*.gemspec")].last
505
- gemspec = Gem::Specification.load(gemspec_path)
506
- opts[:version] = Gem::Requirement.new [">#{gemspec.version}"]
507
- end
508
- opts[:install_dir] = gem_dir
509
- opts[:cache] = options[:cache]
510
- end
511
- Merb.install_gem(name, opts)
512
- rescue => e
513
- puts "Failed to update #{name} (#{e.message})"
514
- end
515
-
516
- # Uninstall a gem - ignores dependencies.
517
- #
518
- # If a local ./gems dir is found, or --merb-root is given
519
- # the gems will be uninstalled locally from that directory.
520
- #
521
- # Examples:
522
- #
523
- # thor merb:gems:uninstall merb-core
524
- # thor merb:gems:uninstall merb-core --all
525
- # thor merb:gems:uninstall merb-core --version 0.9.7
526
- # thor merb:gems:uninstall merb-core --merb-root ./path/to/your/app
527
-
528
- desc 'install GEM_NAME', 'Install a gem from rubygems'
529
- desc 'uninstall GEM_NAME', 'Uninstall a gem'
530
- method_options "--version" => :optional,
531
- "--merb-root" => :optional,
532
- "--all" => :boolean
533
- def uninstall(name)
534
- puts "Uninstalling #{name}..."
535
- opts = {}
536
- opts[:ignore] = true
537
- opts[:all] = options[:all]
538
- opts[:executables] = true
539
- opts[:version] = options[:version]
540
- opts[:install_dir] = gem_dir if gem_dir
541
- Merb.uninstall_gem(name, opts)
542
- rescue => e
543
- puts "Failed to uninstall #{name} (#{e.message})"
544
- end
545
-
546
- # Completely remove a gem and all its versions - ignores dependencies.
547
- #
548
- # If a local ./gems dir is found, or --merb-root is given
549
- # the gems will be uninstalled locally from that directory.
550
- #
551
- # Examples:
552
- #
553
- # thor merb:gems:wipe merb-core
554
- # thor merb:gems:wipe merb-core --merb-root ./path/to/your/app
555
-
556
- desc 'wipe GEM_NAME', 'Remove a gem completely'
557
- method_options "--merb-root" => :optional
558
- def wipe(name)
559
- puts "Wiping #{name}..."
560
- opts = {}
561
- opts[:ignore] = true
562
- opts[:all] = true
563
- opts[:executables] = true
564
- opts[:install_dir] = gem_dir if gem_dir
565
- Merb.uninstall_gem(name, opts)
566
- rescue => e
567
- puts "Failed to wipe #{name} (#{e.message})"
568
- end
569
-
570
- # This task should be executed as part of a deployment setup, where
571
- # the deployment system runs this after the app has been installed.
572
- # Usually triggered by Capistrano, God...
573
- #
574
- # It will regenerate gems from the bundled gems cache for any gem
575
- # that has C extensions - which need to be recompiled for the target
576
- # deployment platform.
577
-
578
- desc 'redeploy', 'Recreate any binary gems on the target deployment platform'
579
- def redeploy
580
- require 'tempfile' # for
581
- if File.directory?(specs_dir = File.join(gem_dir, 'specifications')) &&
582
- File.directory?(cache_dir = File.join(gem_dir, 'cache'))
583
- Dir[File.join(specs_dir, '*.gemspec')].each do |gemspec_path|
584
- unless (gemspec = Gem::Specification.load(gemspec_path)).extensions.empty?
585
- if File.exists?(gem_file = File.join(cache_dir, "#{gemspec.full_name}.gem"))
586
- gem_file_copy = File.join(Dir::tmpdir, File.basename(gem_file))
587
- # Copy the gem to a temporary file, because otherwise RubyGems/FileUtils
588
- # will complain about copying identical files (same source/destination).
589
- FileUtils.cp(gem_file, gem_file_copy)
590
- Merb.install_gem(gem_file_copy, :install_dir => gem_dir)
591
- File.delete(gem_file_copy)
592
- end
593
- end
594
- end
595
- else
596
- puts "No application local gems directory found"
597
- end
598
- end
599
-
600
- end
601
-
602
- class << self
603
-
604
- # Default Git repositories - pass source_config option
605
- # to load a yaml configuration file.
606
- def repos(source_config = nil)
607
- @_repos ||= begin
608
- repositories = {
609
- 'merb-core' => "git://github.com/wycats/merb-core.git",
610
- 'merb-more' => "git://github.com/wycats/merb-more.git",
611
- 'merb-plugins' => "git://github.com/wycats/merb-plugins.git",
612
- 'extlib' => "git://github.com/sam/extlib.git",
613
- 'dm-core' => "git://github.com/sam/dm-core.git",
614
- 'dm-more' => "git://github.com/sam/dm-more.git",
615
- 'thor' => "git://github.com/wycats/thor.git"
616
- }
617
- end
618
- if source_config && File.exists?(source_config)
619
- @_repos.merge(YAML.load(File.read(source_config)))
620
- else
621
- @_repos
622
- end
623
- end
624
-
625
- # Install a gem - looks remotely and local gem cache;
626
- # won't process rdoc or ri options.
627
- def install_gem(gem, options = {})
628
- from_cache = (options.key?(:cache) && options.delete(:cache))
629
- if from_cache
630
- install_gem_from_cache(gem, options)
631
- else
632
- version = options.delete(:version)
633
- Gem.configuration.update_sources = false
634
- installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
635
- exception = nil
636
- begin
637
- installer.install gem, version
638
- rescue Gem::InstallError => e
639
- exception = e
640
- rescue Gem::GemNotFoundException => e
641
- if from_cache && gem_file = find_gem_in_cache(gem, version)
642
- puts "Located #{gem} in gem cache..."
643
- installer.install gem_file
644
- else
645
- exception = e
646
- end
647
- rescue => e
648
- exception = e
649
- end
650
- if installer.installed_gems.empty? && exception
651
- puts "Failed to install gem '#{gem}' (#{exception.message})"
652
- end
653
- installer.installed_gems.each do |spec|
654
- puts "Successfully installed #{spec.full_name}"
655
- end
656
- end
657
- end
658
-
659
- # Install a gem - looks in the system's gem cache instead of remotely;
660
- # won't process rdoc or ri options.
661
- def install_gem_from_cache(gem, options = {})
662
- version = options.delete(:version)
663
- Gem.configuration.update_sources = false
664
- installer = Gem::DependencyInstaller.new(options.merge(:user_install => false))
665
- exception = nil
666
- begin
667
- if gem_file = find_gem_in_cache(gem, version)
668
- puts "Located #{gem} in gem cache..."
669
- installer.install gem_file
670
- else
671
- raise Gem::InstallError, "Unknown gem #{gem}"
672
- end
673
- rescue Gem::InstallError => e
674
- exception = e
675
- end
676
- if installer.installed_gems.empty? && exception
677
- puts "Failed to install gem '#{gem}' (#{e.message})"
678
- end
679
- installer.installed_gems.each do |spec|
680
- puts "Successfully installed #{spec.full_name}"
681
- end
682
- end
683
-
684
- # Install a gem from source - builds and packages it first then installs it.
685
- def install_gem_from_src(gem_src_dir, options = {})
686
- raise SourcePathMissing unless File.directory?(gem_src_dir)
687
- raise GemPathMissing if options[:install_dir] && !File.directory?(options[:install_dir])
688
-
689
- gem_name = File.basename(gem_src_dir)
690
- gem_pkg_dir = File.expand_path(File.join(gem_src_dir, 'pkg'))
691
-
692
- # We need to use local bin executables if available.
693
- thor = which('thor')
694
- rake = which('rake')
695
-
696
- # Handle pure Thor installation instead of Rake
697
- if File.exists?(File.join(gem_src_dir, 'Thorfile'))
698
- # Remove any existing packages.
699
- FileUtils.rm_rf(gem_pkg_dir) if File.directory?(gem_pkg_dir)
700
- # Create the package.
701
- FileUtils.cd(gem_src_dir) { system("#{thor} :package") }
702
- # Install the package using rubygems.
703
- if package = Dir[File.join(gem_pkg_dir, "#{gem_name}-*.gem")].last
704
- FileUtils.cd(File.dirname(package)) do
705
- install_gem(File.basename(package), options.dup)
706
- return
707
- end
708
- else
709
- raise Merb::GemInstallError, "No package found for #{gem_name}"
710
- end
711
- # Handle standard installation through Rake
712
- else
713
- # Clean and regenerate any subgems for meta gems.
714
- Dir[File.join(gem_src_dir, '*', 'Rakefile')].each do |rakefile|
715
- FileUtils.cd(File.dirname(rakefile)) { system("#{rake} clobber_package; #{rake} package") }
716
- end
717
-
718
- # Handle the main gem install.
719
- if File.exists?(File.join(gem_src_dir, 'Rakefile'))
720
- # Remove any existing packages.
721
- FileUtils.cd(gem_src_dir) { system("#{rake} clobber_package") }
722
- # Create the main gem pkg dir if it doesn't exist.
723
- FileUtils.mkdir_p(gem_pkg_dir) unless File.directory?(gem_pkg_dir)
724
- # Copy any subgems to the main gem pkg dir.
725
- Dir[File.join(gem_src_dir, '**', 'pkg', '*.gem')].each do |subgem_pkg|
726
- FileUtils.cp(subgem_pkg, gem_pkg_dir)
727
- end
728
-
729
- # Finally generate the main package and install it; subgems
730
- # (dependencies) are local to the main package.
731
- FileUtils.cd(gem_src_dir) do
732
- system("#{rake} package")
733
- if package = Dir[File.join(gem_pkg_dir, "#{gem_name}-*.gem")].last
734
- FileUtils.cd(File.dirname(package)) do
735
- install_gem(File.basename(package), options.dup)
736
- return
737
- end
738
- else
739
- raise Merb::GemInstallError, "No package found for #{gem_name}"
740
- end
741
- end
742
- end
743
- end
744
- raise Merb::GemInstallError, "No Rakefile found for #{gem_name}"
745
- end
746
-
747
- # Uninstall a gem.
748
- def uninstall_gem(gem, options = {})
749
- if options[:version] && !options[:version].is_a?(Gem::Requirement)
750
- options[:version] = Gem::Requirement.new ["= #{version}"]
751
- end
752
- begin
753
- Gem::Uninstaller.new(gem, options).uninstall
754
- rescue => e
755
- raise GemUninstallError, "Failed to uninstall #{gem}"
756
- end
757
- end
758
-
759
- # Will prepend sudo on a suitable platform.
760
- def sudo
761
- @_sudo ||= begin
762
- windows = PLATFORM =~ /win32|cygwin/ rescue nil
763
- windows ? "" : "sudo "
764
- end
765
- end
766
-
767
- # Use the local bin/* executables if available.
768
- def which(executable)
769
- if File.executable?(exec = File.join(Dir.pwd, 'bin', executable))
770
- exec
771
- else
772
- executable
773
- end
774
- end
775
-
776
- private
777
-
778
- def find_gem_in_cache(gem, version)
779
- spec = if version
780
- version = Gem::Requirement.new ["= #{version}"] unless version.is_a?(Gem::Requirement)
781
- Gem.source_index.find_name(gem, version).first
782
- else
783
- Gem.source_index.find_name(gem).sort_by { |g| g.version }.last
784
- end
785
- if spec && File.exists?(gem_file = "#{spec.installation_path}/cache/#{spec.full_name}.gem")
786
- gem_file
787
- end
788
- end
789
-
790
- end
791
-
792
- class Tasks < Thor
793
-
794
- include MerbThorHelper
795
-
796
- # Install Thor, Rake and RSpec into the local gems dir, by copying it from
797
- # the system-wide rubygems cache - which is OK since we needed it to run
798
- # this task already.
799
- #
800
- # After this we don't need the system-wide rubygems anymore, as all required
801
- # executables are available in the local ./bin directory.
802
- #
803
- # RSpec is needed here because source installs might fail when running
804
- # rake tasks where spec/rake/spectask has been required.
805
-
806
- desc 'setup', 'Install Thor, Rake and RSpec in the local gems dir'
807
- method_options "--merb-root" => :optional
808
- def setup
809
- if $0 =~ /^(\.\/)?bin\/thor$/
810
- puts "You cannot run the setup from #{$0} - try #{File.basename($0)} merb:tasks:setup instead"
811
- return
812
- end
813
- create_if_missing(File.join(working_dir, 'gems'))
814
- Merb.install_gem('thor', :cache => true, :install_dir => gem_dir)
815
- Merb.install_gem('rake', :cache => true, :install_dir => gem_dir)
816
- Merb.install_gem('rspec', :cache => true, :install_dir => gem_dir)
817
- ensure_local_bin_for('thor', 'rake', 'rspec')
818
- end
819
-
820
- end
821
-
822
- end