merb-gen 0.9.13 → 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/generators/controller.rb +4 -4
- data/lib/generators/templates/application/common/merb.thor +1107 -1072
- data/lib/generators/templates/application/merb_stack/autotest/discover.rb +2 -1
- data/lib/generators/templates/application/merb_stack/autotest/merb.rb +5 -2
- data/lib/generators/templates/application/merb_stack/autotest/merb_rspec.rb +2 -2
- data/lib/generators/templates/component/controller/spec/requests/%file_name%_spec.rb +7 -0
- data/lib/generators/templates/component/controller/test/{controllers → requests}/%file_name%_test.rb +1 -2
- data/lib/generators/templates/component/resource_controller/app/views/%file_name%/edit.html.erb +1 -1
- data/lib/generators/templates/component/resource_controller/app/views/%file_name%/index.html.erb +1 -1
- data/lib/generators/templates/component/resource_controller/app/views/%file_name%/new.html.erb +1 -1
- data/lib/generators/templates/component/resource_controller/app/views/%file_name%/show.html.erb +1 -1
- data/lib/generators/templates/component/resource_controller/spec/requests/%file_name%_spec.rb +1 -1
- data/spec/controller_spec.rb +2 -2
- metadata +7 -7
- data/lib/generators/templates/component/controller/spec/controllers/%file_name%_spec.rb +0 -7
@@ -5,7 +5,7 @@ require 'fileutils'
|
|
5
5
|
require 'yaml'
|
6
6
|
|
7
7
|
# Important - don't change this line or its position
|
8
|
-
MERB_THOR_VERSION = '0.1
|
8
|
+
MERB_THOR_VERSION = '0.2.1'
|
9
9
|
|
10
10
|
##############################################################################
|
11
11
|
|
@@ -335,7 +335,7 @@ end
|
|
335
335
|
|
336
336
|
# use gems dir if ../gems exists - eg. only for ./bin/#{bin_file_name}
|
337
337
|
if File.directory?(gems_dir = File.join(File.dirname(__FILE__), '..', 'gems'))
|
338
|
-
$BUNDLE = true; Gem.clear_paths; Gem.path.replace([gems_dir])
|
338
|
+
$BUNDLE = true; Gem.clear_paths; Gem.path.replace([File.expand_path(gems_dir)])
|
339
339
|
ENV["PATH"] = "\#{File.dirname(__FILE__)}:\#{gems_dir}/bin:\#{ENV["PATH"]}"
|
340
340
|
if (local_gem = Dir[File.join(gems_dir, "specifications", "#{spec.name}-*.gemspec")].last)
|
341
341
|
version = File.basename(local_gem)[/-([\\.\\d]+)\\.gemspec$/, 1]
|
@@ -446,6 +446,10 @@ module MerbThorHelper
|
|
446
446
|
base.extend ColorfulMessages
|
447
447
|
end
|
448
448
|
|
449
|
+
def use_edge_gem_server
|
450
|
+
::Gem.sources << 'http://edge.merbivore.com'
|
451
|
+
end
|
452
|
+
|
449
453
|
def source_manager
|
450
454
|
@_source_manager ||= SourceManager.new(source_dir)
|
451
455
|
end
|
@@ -643,166 +647,112 @@ end
|
|
643
647
|
$SILENT = true # don't output all the mess some rake package tasks spit out
|
644
648
|
|
645
649
|
module Merb
|
650
|
+
|
651
|
+
class Gem < Thor
|
646
652
|
|
647
|
-
|
648
|
-
|
649
|
-
# The Dependencies tasks will install dependencies based on actual application
|
650
|
-
# dependencies. For this, the application is queried for any dependencies.
|
651
|
-
# All operations will be performed within this context.
|
653
|
+
include MerbThorHelper
|
654
|
+
extend GemManagement
|
652
655
|
|
653
656
|
attr_accessor :system, :local, :missing
|
654
657
|
|
655
|
-
include MerbThorHelper
|
656
|
-
|
657
658
|
global_method_options = {
|
658
659
|
"--merb-root" => :optional, # the directory to operate on
|
659
|
-
"--
|
660
|
-
"--
|
661
|
-
"--no-stack" => :boolean, # gather only non-stack dependencies
|
662
|
-
"--config" => :boolean, # gather dependencies from yaml config
|
663
|
-
"--config-file" => :optional, # gather from the specified yaml config
|
664
|
-
"--version" => :optional # gather specific version of framework
|
660
|
+
"--version" => :optional, # gather specific version of gem
|
661
|
+
"--ignore-dependencies" => :boolean # don't install sub-dependencies
|
665
662
|
}
|
666
663
|
|
667
664
|
method_options global_method_options
|
668
665
|
def initialize(*args); super; end
|
669
666
|
|
670
|
-
# List
|
667
|
+
# List gems that match the specified criteria.
|
671
668
|
#
|
672
|
-
# By default all
|
673
|
-
#
|
674
|
-
#
|
675
|
-
#
|
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.
|
676
673
|
#
|
677
674
|
# Examples:
|
678
675
|
#
|
679
|
-
# merb:
|
680
|
-
# merb:
|
681
|
-
# merb:
|
682
|
-
# merb:
|
683
|
-
# merb:
|
684
|
-
# merb:dependencies:list --config # list dependencies from the default config
|
685
|
-
# merb:dependencies:list --config-file file.yml # list from the specified config file
|
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
|
686
681
|
|
687
|
-
desc 'list [all|local|system
|
688
|
-
def list(filter = '
|
682
|
+
desc 'list [all|local|system] [comp]', 'Show installed gems'
|
683
|
+
def list(filter = 'local', comp = nil)
|
689
684
|
deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
|
690
685
|
self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
|
691
686
|
case filter
|
692
687
|
when 'all'
|
693
|
-
message 'Installed system
|
688
|
+
message 'Installed system gems:'
|
694
689
|
display_gemspecs(system)
|
695
|
-
message 'Installed local
|
690
|
+
message 'Installed local gems:'
|
696
691
|
display_gemspecs(local)
|
697
|
-
unless missing.empty?
|
698
|
-
error 'Missing gem dependencies:'
|
699
|
-
display_dependencies(missing)
|
700
|
-
end
|
701
692
|
when 'system'
|
702
|
-
message 'Installed system
|
693
|
+
message 'Installed system gems:'
|
703
694
|
display_gemspecs(system)
|
704
695
|
when 'local'
|
705
|
-
message 'Installed local
|
696
|
+
message 'Installed local gems:'
|
706
697
|
display_gemspecs(local)
|
707
|
-
when 'missing'
|
708
|
-
error 'Missing gem dependencies:'
|
709
|
-
display_dependencies(missing)
|
710
698
|
else
|
711
699
|
warning "Invalid listing filter '#{filter}'"
|
712
700
|
end
|
713
|
-
if missing.size > 0
|
714
|
-
info "Some dependencies are currently missing!"
|
715
|
-
elsif local.size == deps.size
|
716
|
-
info "All dependencies have been bundled with the application."
|
717
|
-
elsif local.size > system.size
|
718
|
-
info "Most dependencies have been bundled with the application."
|
719
|
-
elsif system.size > 0 && local.size > 0
|
720
|
-
info "Some dependencies have been bundled with the application."
|
721
|
-
elsif local.empty? && system.size == deps.size
|
722
|
-
info "All dependencies are available on the system."
|
723
|
-
end
|
724
701
|
end
|
725
702
|
|
726
|
-
# Install
|
703
|
+
# Install the specified gems.
|
727
704
|
#
|
728
|
-
#
|
729
|
-
# specifies which strategy to use: stable or edge. A second argument can be
|
730
|
-
# used to filter on a set of known components.
|
705
|
+
# All arguments should be names of gems to install.
|
731
706
|
#
|
732
|
-
#
|
733
|
-
# will be
|
734
|
-
# gems
|
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, ...
|
735
712
|
#
|
736
713
|
# Examples:
|
737
714
|
#
|
738
|
-
# merb:
|
739
|
-
# merb:
|
740
|
-
# merb:
|
741
|
-
# merb:
|
742
|
-
# merb:
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
# When comp == 'missing' then filter on missing dependencies
|
765
|
-
if only_missing = comp == 'missing'
|
766
|
-
message "Preparing to install missing gems #{where} using #{strategy} strategy..."
|
767
|
-
comp = nil
|
768
|
-
clobber = false
|
769
|
-
else
|
770
|
-
message "Preparing to install #{where} using #{strategy} strategy..."
|
771
|
-
clobber = true
|
772
|
-
end
|
773
|
-
|
774
|
-
# If comp given, filter on known stack components
|
775
|
-
deps = comp ? Merb::Stack.select_component_dependencies(dependencies, comp) : dependencies
|
776
|
-
self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
|
777
|
-
|
778
|
-
# Only install currently missing gems (for comp == missing)
|
779
|
-
if only_missing
|
780
|
-
deps.reject! { |dep| not missing.include?(dep) }
|
781
|
-
end
|
782
|
-
|
783
|
-
if deps.empty?
|
784
|
-
warning "No dependencies to install..."
|
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}..."
|
785
741
|
else
|
786
|
-
|
787
|
-
|
742
|
+
message "Installing #{current_gem}..."
|
743
|
+
self.class.install(gem_name, default_install_options.merge(opts))
|
788
744
|
end
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
list('local', comp)
|
793
|
-
else
|
794
|
-
warning "Invalid install strategy '#{strategy}'"
|
795
|
-
puts
|
796
|
-
message "Please choose one of the following installation strategies: stable or edge:"
|
797
|
-
puts "$ thor merb:dependencies:install stable"
|
798
|
-
puts "$ thor merb:dependencies:install edge"
|
799
|
-
end
|
745
|
+
end
|
746
|
+
rescue => e
|
747
|
+
error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})"
|
800
748
|
end
|
801
749
|
|
802
|
-
# Uninstall
|
750
|
+
# Uninstall the specified gems.
|
803
751
|
#
|
804
|
-
# By default all
|
805
|
-
#
|
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, ...
|
806
756
|
#
|
807
757
|
# Existing dependencies will be clobbered; when :force => true then all gems
|
808
758
|
# will be cleared, otherwise only existing local dependencies of the
|
@@ -810,21 +760,32 @@ module Merb
|
|
810
760
|
#
|
811
761
|
# Examples:
|
812
762
|
#
|
813
|
-
# merb:
|
814
|
-
# merb:
|
815
|
-
# merb:dependencies:uninstall --config # read dependencies from the default config
|
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
|
816
765
|
|
817
|
-
desc 'uninstall [
|
818
|
-
method_options "--dry-run" => :boolean
|
819
|
-
def uninstall(
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
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})"
|
825
786
|
end
|
826
787
|
|
827
|
-
# Recreate
|
788
|
+
# Recreate all gems from gems/cache on the current platform.
|
828
789
|
#
|
829
790
|
# This task should be executed as part of a deployment setup, where the
|
830
791
|
# deployment system runs this after the app has been installed.
|
@@ -833,27 +794,32 @@ module Merb
|
|
833
794
|
# It will regenerate gems from the bundled gems cache for any gem that has
|
834
795
|
# C extensions - which need to be recompiled for the target deployment platform.
|
835
796
|
#
|
836
|
-
# Note: gems/cache should be in your SCM
|
797
|
+
# Note: at least gems/cache and gems/specifications should be in your SCM.
|
837
798
|
|
838
|
-
desc 'redeploy', 'Recreate
|
839
|
-
method_options "--dry-run" => :boolean
|
799
|
+
desc 'redeploy', 'Recreate all gems on the current platform'
|
800
|
+
method_options "--dry-run" => :boolean, "--force" => :boolean
|
840
801
|
def redeploy
|
841
802
|
require 'tempfile' # for Dir::tmpdir access
|
842
803
|
if gem_dir && File.directory?(cache_dir = File.join(gem_dir, 'cache'))
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
end
|
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)
|
857
823
|
end
|
858
824
|
end
|
859
825
|
end
|
@@ -862,1124 +828,1193 @@ module Merb
|
|
862
828
|
end
|
863
829
|
end
|
864
830
|
|
865
|
-
|
866
|
-
#
|
867
|
-
# A configuration yaml file will be created from the extracted application
|
868
|
-
# dependencies. The format of the configuration is as follows:
|
869
|
-
#
|
870
|
-
# ---
|
871
|
-
# - merb-core (= 0.9.8, runtime)
|
872
|
-
# - merb-slices (= 0.9.8, runtime)
|
873
|
-
#
|
874
|
-
# This format is exactly the same as Gem::Dependency#to_s returns.
|
875
|
-
#
|
876
|
-
# Examples:
|
877
|
-
#
|
878
|
-
# merb:dependencies:configure --force # overwrite the default config file
|
879
|
-
# merb:dependencies:configure --version 0.9.8 # configure specific framework version
|
880
|
-
# merb:dependencies:configure --config-file file.yml # write to the specified config file
|
831
|
+
private
|
881
832
|
|
882
|
-
|
883
|
-
|
884
|
-
def
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
# If --versions is set, update the version_requirements with the actual version available
|
889
|
-
if options[:versions]
|
890
|
-
specs = local_gemspecs
|
891
|
-
deps.each do |dep|
|
892
|
-
if spec = specs.find { |s| s.name == dep.name }
|
893
|
-
dep.version_requirements = ::Gem::Requirement.create(spec.version)
|
894
|
-
end
|
895
|
-
end
|
896
|
-
end
|
897
|
-
|
898
|
-
config = YAML.dump(deps.map { |d| d.to_s })
|
899
|
-
puts "#{config}\n"
|
900
|
-
if File.exists?(config_file) && !options[:force]
|
901
|
-
error "File already exists! Use --force to overwrite."
|
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])
|
902
838
|
else
|
903
|
-
|
904
|
-
note "Written #{config_file}"
|
905
|
-
else
|
906
|
-
FileUtils.mkdir_p(config_dir) unless File.directory?(config_dir)
|
907
|
-
File.open(config_file, 'w') { |f| f.write config }
|
908
|
-
success "Written #{config_file}"
|
909
|
-
end
|
910
|
-
end
|
911
|
-
rescue
|
912
|
-
error "Failed to write to #{config_file}"
|
913
|
-
end
|
914
|
-
|
915
|
-
### Helper Methods
|
916
|
-
|
917
|
-
def strategy?(strategy)
|
918
|
-
if self.respond_to?(method = :"#{strategy}_strategy", true)
|
919
|
-
method
|
920
|
-
end
|
921
|
-
end
|
922
|
-
|
923
|
-
def install_dependencies(strategy, deps, clobber = true)
|
924
|
-
if method = strategy?(strategy)
|
925
|
-
# Clobber existing local dependencies
|
926
|
-
clobber_dependencies! if clobber
|
927
|
-
|
928
|
-
# Run the chosen strategy - collect files installed from stable gems
|
929
|
-
installed_from_stable = send(method, deps).map { |d| d.name }
|
930
|
-
|
931
|
-
unless dry_run?
|
932
|
-
# Sleep a bit otherwise the following steps won't see the new files
|
933
|
-
sleep(deps.length) if deps.length > 0 && deps.length <= 10
|
934
|
-
|
935
|
-
# Leave a file to denote the strategy that has been used for this dependency
|
936
|
-
self.local.each do |spec|
|
937
|
-
next unless File.directory?(spec.full_gem_path)
|
938
|
-
unless installed_from_stable.include?(spec.name)
|
939
|
-
FileUtils.touch(File.join(spec.full_gem_path, "#{strategy}.strategy"))
|
940
|
-
else
|
941
|
-
FileUtils.touch(File.join(spec.full_gem_path, "stable.strategy"))
|
942
|
-
end
|
943
|
-
end
|
944
|
-
end
|
945
|
-
return true
|
946
|
-
end
|
947
|
-
false
|
948
|
-
end
|
949
|
-
|
950
|
-
def dependencies
|
951
|
-
if use_config?
|
952
|
-
# Use preconfigured dependencies from yaml file
|
953
|
-
deps = config_dependencies
|
954
|
-
else
|
955
|
-
# Extract dependencies from the current application
|
956
|
-
deps = Merb::Stack.core_dependencies(gem_dir, ignore_dependencies?)
|
957
|
-
deps += Merb::Dependencies.extract_dependencies(working_dir)
|
958
|
-
end
|
959
|
-
|
960
|
-
stack_components = Merb::Stack.components
|
961
|
-
|
962
|
-
if options[:stack]
|
963
|
-
# Limit to stack components only
|
964
|
-
deps.reject! { |dep| not stack_components.include?(dep.name) }
|
965
|
-
elsif options[:"no-stack"]
|
966
|
-
# Limit to non-stack components
|
967
|
-
deps.reject! { |dep| stack_components.include?(dep.name) }
|
839
|
+
::Gem::Requirement.default
|
968
840
|
end
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
elsif core = deps.find { |d| d.name == 'merb-core' }
|
973
|
-
version_req = core.version_requirements
|
841
|
+
if gem_dir
|
842
|
+
::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
|
843
|
+
::Gem.source_index.refresh!
|
974
844
|
end
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
deps.each do |dep|
|
980
|
-
if framework_components.include?(dep.name)
|
981
|
-
dep.version_requirements = version_req
|
982
|
-
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}")
|
983
849
|
end
|
984
850
|
end
|
985
|
-
|
986
|
-
deps
|
851
|
+
::Gem.clear_paths if gem_dir
|
852
|
+
deps.sort
|
987
853
|
end
|
988
854
|
|
989
|
-
|
990
|
-
if File.exists?(config_file)
|
991
|
-
self.class.parse_dependencies_yaml(File.read(config_file))
|
992
|
-
else
|
993
|
-
[]
|
994
|
-
end
|
995
|
-
end
|
855
|
+
public
|
996
856
|
|
997
|
-
|
998
|
-
|
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))
|
999
862
|
end
|
1000
863
|
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
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))
|
1005
868
|
end
|
1006
869
|
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
870
|
+
end
|
871
|
+
|
872
|
+
class Tasks < Thor
|
1010
873
|
|
1011
|
-
|
874
|
+
include MerbThorHelper
|
1012
875
|
|
1013
|
-
|
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
|
1014
880
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
installed_from_rubygems << core
|
1023
|
-
else
|
1024
|
-
msg = "Try specifying a lower version of merb-core with --version"
|
1025
|
-
if version_no = core.version_requirements.to_s[/([\.\d]+)$/, 1]
|
1026
|
-
num = "%03d" % (version_no.gsub('.', '').to_i - 1)
|
1027
|
-
puts "The required version (#{version_no}) probably isn't available as a stable rubygem yet."
|
1028
|
-
info "#{msg} #{num.split(//).join('.')}"
|
1029
|
-
else
|
1030
|
-
puts "The required version probably isn't available as a stable rubygem yet."
|
1031
|
-
info msg
|
1032
|
-
end
|
1033
|
-
end
|
1034
|
-
end
|
1035
|
-
end
|
1036
|
-
|
1037
|
-
deps.each do |dependency|
|
1038
|
-
next if dependency.name == 'merb-core'
|
1039
|
-
if dry_run?
|
1040
|
-
note "Installing #{dependency.name}..."
|
1041
|
-
else
|
1042
|
-
install_dependency(dependency)
|
1043
|
-
installed_from_rubygems << dependency
|
1044
|
-
end
|
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
|
1045
888
|
end
|
1046
|
-
installed_from_rubygems
|
1047
889
|
end
|
1048
890
|
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
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
|
1054
904
|
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
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}"
|
1063
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
|
1064
922
|
end
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
if dry_run?
|
1070
|
-
note "Installing #{dependency.name}..."
|
1071
|
-
else
|
1072
|
-
if install_dependency_from_source(dependency)
|
1073
|
-
elsif install_dependency(dependency)
|
1074
|
-
info "Installed #{dependency.name} from rubygems..."
|
1075
|
-
installed_from_rubygems << dependency
|
923
|
+
|
924
|
+
if proceed && !dry_run?
|
925
|
+
File.open(File.join(__FILE__), 'w') do |f|
|
926
|
+
f.write(code)
|
1076
927
|
end
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
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})"
|
1081
937
|
end
|
1082
938
|
|
1083
|
-
|
939
|
+
end
|
940
|
+
|
941
|
+
#### MORE LOW-LEVEL TASKS ####
|
942
|
+
|
943
|
+
class Source < Thor
|
1084
944
|
|
1085
|
-
|
945
|
+
group 'core'
|
946
|
+
|
947
|
+
include MerbThorHelper
|
948
|
+
extend GemManagement
|
1086
949
|
|
1087
|
-
|
1088
|
-
instance = Merb::Dependencies.new
|
1089
|
-
instance.options = options
|
1090
|
-
instance.list(filter, comp)
|
1091
|
-
end
|
950
|
+
attr_accessor :system, :local, :missing
|
1092
951
|
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
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}"
|
1105
986
|
end
|
1106
|
-
Merb::BootLoader::Dependencies.dependencies
|
1107
|
-
rescue StandardError => e
|
1108
|
-
error "Couldn't extract dependencies from application!"
|
1109
|
-
error e.message
|
1110
|
-
puts "Make sure you're executing the task from your app (--merb-root), or"
|
1111
|
-
puts "specify a config option (--config or --config-file=YAML_FILE)"
|
1112
|
-
return []
|
1113
|
-
rescue SystemExit
|
1114
|
-
error "Couldn't extract dependencies from application!"
|
1115
|
-
error "application failed to run"
|
1116
|
-
puts "Please check if your application runs using 'merb'; for example,"
|
1117
|
-
puts "look for any gem version mismatches in dependencies.rb"
|
1118
|
-
return []
|
1119
987
|
end
|
1120
|
-
|
1121
|
-
#
|
1122
|
-
#
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
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..."
|
1130
1025
|
else
|
1131
|
-
|
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
|
1132
1031
|
end
|
1133
1032
|
end
|
1134
|
-
|
1033
|
+
rescue => e
|
1034
|
+
error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})"
|
1135
1035
|
end
|
1136
1036
|
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
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
|
1140
1053
|
|
1141
|
-
|
1142
|
-
|
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
|
1143
1076
|
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
dm-validations
|
1153
|
-
merb_datamapper
|
1154
|
-
]
|
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
|
1155
1085
|
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
merb-auth-more
|
1168
|
-
merb-auth-slice-password
|
1169
|
-
merb-param-protection
|
1170
|
-
merb-exceptions
|
1171
|
-
] + DM_STACK
|
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
|
1172
1097
|
|
1173
|
-
|
1174
|
-
extlib
|
1175
|
-
merb-core
|
1176
|
-
merb-action-args
|
1177
|
-
merb-assets
|
1178
|
-
merb-cache
|
1179
|
-
merb-helpers
|
1180
|
-
merb-mailer
|
1181
|
-
merb-slices
|
1182
|
-
]
|
1098
|
+
# Clone a git repository into ./src.
|
1183
1099
|
|
1184
|
-
# The
|
1185
|
-
#
|
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
|
1186
1108
|
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
merb-helpers
|
1199
|
-
merb-mailer
|
1200
|
-
merb-param-protection
|
1201
|
-
merb-slices
|
1202
|
-
merb_datamapper
|
1203
|
-
]
|
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
|
1204
1120
|
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
merb_stories
|
1214
|
-
merb_test_unit
|
1215
|
-
]
|
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
|
1216
1129
|
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
dm-querizer
|
1234
|
-
dm-serializer
|
1235
|
-
dm-shorthand
|
1236
|
-
dm-sweatshop
|
1237
|
-
dm-tags
|
1238
|
-
dm-timestamps
|
1239
|
-
dm-types
|
1240
|
-
dm-validations
|
1241
|
-
|
1242
|
-
dm-couchdb-adapter
|
1243
|
-
dm-ferret-adapter
|
1244
|
-
dm-rest-adapter
|
1245
|
-
]
|
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
|
1246
1146
|
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
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'
|
1255
1167
|
|
1256
|
-
|
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
|
1257
1173
|
|
1258
1174
|
include MerbThorHelper
|
1259
1175
|
|
1260
1176
|
global_method_options = {
|
1261
1177
|
"--merb-root" => :optional, # the directory to operate on
|
1262
|
-
"--ignore-dependencies" => :boolean, #
|
1263
|
-
"--
|
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
|
1264
1184
|
}
|
1265
1185
|
|
1266
1186
|
method_options global_method_options
|
1267
1187
|
def initialize(*args); super; end
|
1268
1188
|
|
1269
|
-
# List
|
1189
|
+
# List application dependencies.
|
1270
1190
|
#
|
1271
|
-
#
|
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.
|
1272
1195
|
#
|
1273
|
-
#
|
1274
|
-
#
|
1275
|
-
# merb:
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
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)
|
1285
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)
|
1286
1229
|
else
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
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
|
1290
1243
|
end
|
1291
1244
|
|
1292
|
-
# Install
|
1245
|
+
# Install application dependencies.
|
1293
1246
|
#
|
1294
|
-
#
|
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.
|
1295
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
|
+
#
|
1296
1255
|
# Examples:
|
1297
1256
|
#
|
1298
|
-
# merb:
|
1299
|
-
# merb:
|
1300
|
-
# merb:
|
1301
|
-
# merb:
|
1302
|
-
# merb:
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
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]
|
1316
1280
|
|
1317
|
-
|
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.
|
1318
1323
|
#
|
1319
|
-
#
|
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.
|
1320
1330
|
#
|
1321
1331
|
# Examples:
|
1322
1332
|
#
|
1323
|
-
# merb:
|
1324
|
-
# merb:
|
1325
|
-
# merb:stack:uninstall merb-core thor merb-slices # uninstall the specified gems
|
1333
|
+
# merb:dependencies:uninstall # uninstall all dependencies - the default
|
1334
|
+
# merb:dependencies:uninstall merb-more # uninstall merb-more related gems locally
|
1326
1335
|
|
1327
|
-
desc 'uninstall [
|
1336
|
+
desc 'uninstall [comp]', 'Uninstall application dependencies'
|
1328
1337
|
method_options "--dry-run" => :boolean, "--force" => :boolean
|
1329
|
-
def uninstall(
|
1330
|
-
|
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
|
1331
1341
|
self.system, self.local, self.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
|
1332
1342
|
# Clobber existing local dependencies - based on self.local
|
1333
1343
|
clobber_dependencies!
|
1334
1344
|
end
|
1335
1345
|
|
1336
|
-
#
|
1337
|
-
#
|
1338
|
-
# Due to the specific nature of MiniGems it can only be installed system-wide.
|
1339
|
-
#
|
1340
|
-
# Examples:
|
1346
|
+
# Recreate all gems from gems/cache on the current platform.
|
1341
1347
|
#
|
1342
|
-
# merb:
|
1343
|
-
# merb:stack:minigems uninstall # uninstall minigems
|
1344
|
-
|
1345
|
-
desc 'minigems (install|uninstall)', 'Install or uninstall minigems (needs sudo privileges)'
|
1346
|
-
def minigems(action)
|
1347
|
-
case action
|
1348
|
-
when 'install'
|
1349
|
-
Kernel.system "#{sudo} thor merb:stack:install_minigems"
|
1350
|
-
when 'uninstall'
|
1351
|
-
Kernel.system "#{sudo} thor merb:stack:uninstall_minigems"
|
1352
|
-
else
|
1353
|
-
error "Invalid command: merb:stack:minigems #{action}"
|
1354
|
-
end
|
1355
|
-
end
|
1356
|
-
|
1357
|
-
# hidden minigems install task
|
1358
|
-
def install_minigems
|
1359
|
-
message "Installing MiniGems"
|
1360
|
-
mngr = self.dependency_manager
|
1361
|
-
deps = gather_dependencies('minigems')
|
1362
|
-
mngr.system, mngr.local, mngr.missing = Merb::Gem.partition_dependencies(deps, gem_dir)
|
1363
|
-
mngr.force_gem_dir = ::Gem.dir
|
1364
|
-
mngr.install_dependencies(strategy, deps)
|
1365
|
-
Kernel.system "#{sudo} minigem install"
|
1366
|
-
end
|
1348
|
+
# Note: use merb:gem:redeploy instead
|
1367
1349
|
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
clobber_dependencies!
|
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
|
1376
1357
|
end
|
1377
1358
|
|
1378
|
-
|
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
|
1379
1375
|
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
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
|
1386
1382
|
|
1387
|
-
|
1388
|
-
|
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
|
1389
1391
|
end
|
1390
1392
|
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
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}"
|
1396
1400
|
else
|
1397
|
-
|
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}"
|
1398
1404
|
end
|
1399
1405
|
end
|
1400
|
-
|
1406
|
+
rescue
|
1407
|
+
error "Failed to write to #{config_file}"
|
1408
|
+
end
|
1401
1409
|
|
1402
|
-
|
1403
|
-
options[:strategy] || (options[:edge] ? 'edge' : 'stable')
|
1404
|
-
end
|
1410
|
+
### Helper Methods
|
1405
1411
|
|
1406
|
-
def
|
1407
|
-
|
1408
|
-
|
1409
|
-
instance.options = options
|
1410
|
-
instance
|
1412
|
+
def strategy?(strategy)
|
1413
|
+
if self.respond_to?(method = :"#{strategy}_strategy", true)
|
1414
|
+
method
|
1411
1415
|
end
|
1412
1416
|
end
|
1413
1417
|
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
# the component itself as a fallback
|
1419
|
-
comps = Hash.new { |(hsh,c)| [c] }
|
1420
|
-
|
1421
|
-
# git repository based component sets
|
1422
|
-
comps["merb"] = ["merb-core"] + MERB_MORE
|
1423
|
-
comps["merb-more"] = MERB_MORE.sort
|
1424
|
-
comps["merb-plugins"] = MERB_PLUGINS.sort
|
1425
|
-
comps["dm-more"] = DM_MORE.sort
|
1426
|
-
comps["do"] = DATA_OBJECTS.sort
|
1427
|
-
|
1428
|
-
comps
|
1429
|
-
end
|
1430
|
-
end
|
1431
|
-
|
1432
|
-
def self.component_sets
|
1433
|
-
@_component_sets ||= begin
|
1434
|
-
# the component itself as a fallback
|
1435
|
-
comps = Hash.new { |(hsh,c)| [c] }
|
1436
|
-
comps.update(repository_sets)
|
1437
|
-
|
1438
|
-
# specific set of dependencies
|
1439
|
-
comps["stack"] = MERB_STACK.sort
|
1440
|
-
comps["basics"] = MERB_BASICS.sort
|
1441
|
-
|
1442
|
-
# orm dependencies
|
1443
|
-
comps["datamapper"] = DM_STACK.sort
|
1444
|
-
comps["sequel"] = ["merb_sequel", "sequel"]
|
1445
|
-
comps["activerecord"] = ["merb_activerecord", "activerecord"]
|
1418
|
+
def install_dependencies(strategy, deps, clobber = true)
|
1419
|
+
if method = strategy?(strategy)
|
1420
|
+
# Clobber existing local dependencies
|
1421
|
+
clobber_dependencies! if clobber
|
1446
1422
|
|
1447
|
-
|
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
|
1448
1441
|
end
|
1442
|
+
false
|
1449
1443
|
end
|
1450
1444
|
|
1451
|
-
def
|
1452
|
-
|
1453
|
-
|
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
|
1454
1479
|
end
|
1480
|
+
|
1481
|
+
deps
|
1455
1482
|
end
|
1456
1483
|
|
1457
|
-
def
|
1458
|
-
if
|
1459
|
-
|
1484
|
+
def config_dependencies
|
1485
|
+
if File.exists?(config_file)
|
1486
|
+
self.class.parse_dependencies_yaml(File.read(config_file))
|
1460
1487
|
else
|
1461
|
-
|
1462
|
-
|
1463
|
-
all + (component_sets[grp] || [])
|
1464
|
-
end
|
1488
|
+
warning "No dependencies.yml file found at: #{config_file}"
|
1489
|
+
[]
|
1465
1490
|
end
|
1466
1491
|
end
|
1467
1492
|
|
1468
|
-
def
|
1469
|
-
|
1470
|
-
dependencies.select { |dep| comps.include?(dep.name) }
|
1493
|
+
def extract_dependencies?
|
1494
|
+
options[:extract] || extract_dependencies
|
1471
1495
|
end
|
1472
1496
|
|
1473
|
-
def
|
1474
|
-
|
1497
|
+
def config_file
|
1498
|
+
@config_file ||= begin
|
1499
|
+
options[:"config-file"] || File.join(working_dir, 'config', 'dependencies.yml')
|
1500
|
+
end
|
1475
1501
|
end
|
1476
1502
|
|
1477
|
-
def
|
1478
|
-
|
1503
|
+
def config_dir
|
1504
|
+
File.dirname(config_file)
|
1479
1505
|
end
|
1480
1506
|
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
if ignore_deps
|
1494
|
-
deps += gemspec.dependencies.select do |d|
|
1495
|
-
base_components.include?(d.name)
|
1496
|
-
end
|
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
|
1497
1519
|
else
|
1498
|
-
|
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
|
1499
1560
|
end
|
1500
1561
|
end
|
1501
|
-
::Gem.path.replace(orig_gem_path) if gem_dir # reset
|
1502
|
-
deps
|
1503
1562
|
end
|
1504
|
-
end
|
1505
|
-
|
1506
|
-
def self.lookup_repository_name(item)
|
1507
|
-
set_name = nil
|
1508
|
-
# The merb repo contains -more as well, so it needs special attention
|
1509
|
-
return 'merb' if self.repository_sets['merb'].include?(item)
|
1510
1563
|
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
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
|
1515
1575
|
end
|
1516
|
-
|
1576
|
+
|
1577
|
+
installed_from_rubygems
|
1517
1578
|
end
|
1518
1579
|
|
1519
|
-
|
1520
|
-
|
1521
|
-
class Tasks < Thor
|
1580
|
+
### Class Methods
|
1522
1581
|
|
1523
|
-
|
1582
|
+
public
|
1524
1583
|
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
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
|
1529
1589
|
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
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
|
1537
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 []
|
1538
1615
|
end
|
1539
|
-
|
1540
|
-
# Update merb.thor tasks from remotely available version
|
1541
|
-
#
|
1542
|
-
# merb:tasks:update # update merb.thor
|
1543
|
-
# merb:tasks:update --force # force-update merb.thor
|
1544
|
-
# merb:tasks:update --dry-run # show version info only
|
1545
|
-
|
1546
|
-
desc 'update [URL]', 'Fetch the latest merb.thor and install it locally'
|
1547
|
-
method_options "--dry-run" => :boolean, "--force" => :boolean
|
1548
|
-
def update(url = 'http://merbivore.com/merb.thor')
|
1549
|
-
require 'open-uri'
|
1550
|
-
require 'rubygems/version'
|
1551
|
-
remote_file = open(url)
|
1552
|
-
code = remote_file.read
|
1553
|
-
|
1554
|
-
# Extract version information from the source code
|
1555
|
-
if version = code[/^MERB_THOR_VERSION\s?=\s?('|")([\.\d]+)('|")/,2]
|
1556
|
-
# borrow version comparison from rubygems' Version class
|
1557
|
-
current_version = ::Gem::Version.new(MERB_THOR_VERSION)
|
1558
|
-
remote_version = ::Gem::Version.new(version)
|
1559
1616
|
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
end
|
1572
|
-
|
1573
|
-
if proceed && !dry_run?
|
1574
|
-
File.open(File.join(__FILE__), 'w') do |f|
|
1575
|
-
f.write(code)
|
1576
|
-
end
|
1577
|
-
success "Installed the latest merb.thor (v#{version})"
|
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}"
|
1578
1628
|
end
|
1579
|
-
|
1580
|
-
|
1581
|
-
end
|
1582
|
-
rescue OpenURI::HTTPError
|
1583
|
-
error "Error opening #{url}"
|
1584
|
-
rescue => e
|
1585
|
-
error "An error occurred (#{e.message})"
|
1629
|
+
end
|
1630
|
+
dependencies
|
1586
1631
|
end
|
1587
1632
|
|
1588
1633
|
end
|
1589
1634
|
|
1590
|
-
|
1591
|
-
|
1592
|
-
class Gem < Thor
|
1635
|
+
class Stack < Thor
|
1593
1636
|
|
1594
1637
|
group 'core'
|
1595
1638
|
|
1596
|
-
|
1597
|
-
|
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
|
+
]
|
1598
1753
|
|
1599
1754
|
attr_accessor :system, :local, :missing
|
1600
1755
|
|
1756
|
+
include MerbThorHelper
|
1757
|
+
|
1601
1758
|
global_method_options = {
|
1602
1759
|
"--merb-root" => :optional, # the directory to operate on
|
1603
|
-
"--
|
1604
|
-
"--
|
1760
|
+
"--ignore-dependencies" => :boolean, # skip sub-dependencies
|
1761
|
+
"--version" => :optional # gather specific version of framework
|
1605
1762
|
}
|
1606
1763
|
|
1607
1764
|
method_options global_method_options
|
1608
1765
|
def initialize(*args); super; end
|
1609
1766
|
|
1610
|
-
# List
|
1767
|
+
# List components and their dependencies.
|
1611
1768
|
#
|
1612
|
-
# By default all local gems are listed. When the first argument is 'all' the
|
1613
|
-
# list is partitioned into system an local gems; specify 'system' to show
|
1614
|
-
# only system gems. A second argument can be used to filter on a set of known
|
1615
|
-
# components, like all merb-more gems for example.
|
1616
|
-
#
|
1617
1769
|
# Examples:
|
1618
|
-
#
|
1619
|
-
# merb:
|
1620
|
-
# merb:
|
1621
|
-
# merb:
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
display_gemspecs(system)
|
1633
|
-
message 'Installed local gems:'
|
1634
|
-
display_gemspecs(local)
|
1635
|
-
when 'system'
|
1636
|
-
message 'Installed system gems:'
|
1637
|
-
display_gemspecs(system)
|
1638
|
-
when 'local'
|
1639
|
-
message 'Installed local gems:'
|
1640
|
-
display_gemspecs(local)
|
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
|
1641
1784
|
else
|
1642
|
-
|
1643
|
-
|
1785
|
+
message "Dependencies for '#{comp}' set:"
|
1786
|
+
Merb::Stack.components(comp).each { |c| puts "- #{c}" }
|
1787
|
+
end
|
1644
1788
|
end
|
1645
1789
|
|
1646
|
-
# Install
|
1790
|
+
# Install stack components or individual gems - from stable rubygems by default.
|
1647
1791
|
#
|
1648
|
-
#
|
1792
|
+
# See also: Merb::Dependencies#install and Merb::Dependencies#install_dependencies
|
1649
1793
|
#
|
1650
|
-
# When :force => true then any existing versions of the gems to be installed
|
1651
|
-
# will be uninstalled first. It's important to note that so-called meta-gems
|
1652
|
-
# or gems that exactly match a set of Merb::Stack.components will have their
|
1653
|
-
# sub-gems uninstalled too. For example, uninstalling merb-more will install
|
1654
|
-
# all contained gems: merb-action-args, merb-assets, merb-gen, ...
|
1655
|
-
#
|
1656
1794
|
# Examples:
|
1657
1795
|
#
|
1658
|
-
# merb:
|
1659
|
-
# merb:
|
1660
|
-
# merb:
|
1661
|
-
# merb:
|
1662
|
-
|
1663
|
-
desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from rubygems'
|
1664
|
-
method_options "--cache" => :boolean,
|
1665
|
-
"--dry-run" => :boolean,
|
1666
|
-
"--force" => :boolean
|
1667
|
-
def install(*names)
|
1668
|
-
opts = { :version => options[:version], :cache => options[:cache] }
|
1669
|
-
current_gem = nil
|
1670
|
-
|
1671
|
-
# uninstall existing gems of the ones we're going to install
|
1672
|
-
uninstall(*names) if options[:force]
|
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
|
1673
1801
|
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
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)
|
1685
1814
|
end
|
1686
|
-
|
1687
|
-
# Uninstall
|
1688
|
-
#
|
1689
|
-
# By default all specified gems are uninstalled. It's important to note that
|
1690
|
-
# so-called meta-gems or gems that match a set of Merb::Stack.components will
|
1691
|
-
# have their sub-gems uninstalled too. For example, uninstalling merb-more
|
1692
|
-
# will install all contained gems: merb-action-args, merb-assets, ...
|
1815
|
+
|
1816
|
+
# Uninstall stack components or individual gems.
|
1693
1817
|
#
|
1694
|
-
#
|
1695
|
-
# will be cleared, otherwise only existing local dependencies of the
|
1696
|
-
# matching component set will be removed.
|
1818
|
+
# See also: Merb::Dependencies#uninstall
|
1697
1819
|
#
|
1698
1820
|
# Examples:
|
1699
1821
|
#
|
1700
|
-
# merb:
|
1701
|
-
# merb:
|
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
|
1702
1825
|
|
1703
|
-
desc 'uninstall
|
1704
|
-
method_options "--dry-run" => :boolean
|
1705
|
-
def uninstall(*
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
else
|
1711
|
-
message "Uninstalling any existing gems of: #{names.join(', ')}"
|
1712
|
-
names.each do |gem_name|
|
1713
|
-
current_gem = gem_name
|
1714
|
-
Merb::Gem.uninstall(gem_name, default_uninstall_options) rescue nil
|
1715
|
-
# if this gem is a meta-gem or a component set name, remove sub-gems
|
1716
|
-
(Merb::Stack.components(gem_name) || []).each do |comp|
|
1717
|
-
Merb::Gem.uninstall(comp, default_uninstall_options) rescue nil
|
1718
|
-
end
|
1719
|
-
end
|
1720
|
-
end
|
1721
|
-
rescue => e
|
1722
|
-
error "Failed to uninstall #{current_gem ? current_gem : 'gem'} (#{e.message})"
|
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!
|
1723
1833
|
end
|
1724
1834
|
|
1725
|
-
|
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
|
1726
1843
|
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
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"
|
1732
1851
|
else
|
1733
|
-
|
1734
|
-
end
|
1735
|
-
if gem_dir
|
1736
|
-
::Gem.clear_paths; ::Gem.path.unshift(gem_dir)
|
1737
|
-
::Gem.source_index.refresh!
|
1738
|
-
end
|
1739
|
-
deps = []
|
1740
|
-
::Gem.source_index.each do |fullname, gemspec|
|
1741
|
-
if version_req.satisfied_by?(gemspec.version)
|
1742
|
-
deps << ::Gem::Dependency.new(gemspec.name, "= #{gemspec.version}")
|
1743
|
-
end
|
1852
|
+
error "Invalid command: merb:stack:minigems #{action}"
|
1744
1853
|
end
|
1745
|
-
|
1746
|
-
deps.sort
|
1747
|
-
end
|
1748
|
-
|
1749
|
-
public
|
1854
|
+
end
|
1750
1855
|
|
1751
|
-
#
|
1752
|
-
def
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
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"
|
1756
1865
|
end
|
1757
1866
|
|
1758
|
-
#
|
1759
|
-
def
|
1760
|
-
|
1761
|
-
|
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!
|
1762
1875
|
end
|
1763
1876
|
|
1764
|
-
|
1765
|
-
|
1766
|
-
class Source < Thor
|
1767
|
-
|
1768
|
-
group 'core'
|
1769
|
-
|
1770
|
-
include MerbThorHelper
|
1771
|
-
extend GemManagement
|
1772
|
-
|
1773
|
-
attr_accessor :system, :local, :missing
|
1774
|
-
|
1775
|
-
global_method_options = {
|
1776
|
-
"--merb-root" => :optional, # the directory to operate on
|
1777
|
-
"--ignore-dependencies" => :boolean, # don't install sub-dependencies
|
1778
|
-
"--sources" => :optional # a yml config to grab sources from
|
1779
|
-
}
|
1780
|
-
|
1781
|
-
method_options global_method_options
|
1782
|
-
def initialize(*args); super; end
|
1783
|
-
|
1784
|
-
# List source repositories, of either local or known sources.
|
1785
|
-
#
|
1786
|
-
# Examples:
|
1787
|
-
#
|
1788
|
-
# merb:source:list # list all local sources
|
1789
|
-
# merb:source:list available # list all known sources
|
1877
|
+
protected
|
1790
1878
|
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
message 'Available source repositories:'
|
1795
|
-
repos = self.class.repos(options[:sources])
|
1796
|
-
repos.keys.sort.each { |name| puts "- #{name}: #{repos[name]}" }
|
1797
|
-
elsif mode == 'local'
|
1798
|
-
message 'Current source repositories:'
|
1799
|
-
Dir[File.join(source_dir, '*')].each do |src|
|
1800
|
-
next unless File.directory?(src)
|
1801
|
-
src_name = File.basename(src)
|
1802
|
-
unless (repos = source_manager.existing_repos(src_name)).empty?
|
1803
|
-
puts "#{src_name}"
|
1804
|
-
repos.keys.sort.each { |b| puts "- #{b}: #{repos[b]}" }
|
1805
|
-
end
|
1806
|
-
end
|
1879
|
+
def gather_dependencies(comps = [])
|
1880
|
+
if comps.empty?
|
1881
|
+
gems = MERB_STACK
|
1807
1882
|
else
|
1808
|
-
|
1883
|
+
gems = comps.map { |c| Merb::Stack.components(c) }.flatten
|
1809
1884
|
end
|
1810
|
-
end
|
1811
|
-
|
1812
|
-
# Install the specified gems.
|
1813
|
-
#
|
1814
|
-
# All arguments should be names of gems to install.
|
1815
|
-
#
|
1816
|
-
# When :force => true then any existing versions of the gems to be installed
|
1817
|
-
# will be uninstalled first. It's important to note that so-called meta-gems
|
1818
|
-
# or gems that exactly match a set of Merb::Stack.components will have their
|
1819
|
-
# sub-gems uninstalled too. For example, uninstalling merb-more will install
|
1820
|
-
# all contained gems: merb-action-args, merb-assets, merb-gen, ...
|
1821
|
-
#
|
1822
|
-
# Examples:
|
1823
|
-
#
|
1824
|
-
# merb:source:install merb-core merb-slices # install all specified gems
|
1825
|
-
# merb:source:install merb-core --force # uninstall then subsequently install the gem
|
1826
|
-
# merb:source:install merb-core --wipe # clear repo then install the gem
|
1827
|
-
|
1828
|
-
desc 'install GEM_NAME [GEM_NAME, ...]', 'Install a gem from git source/edge'
|
1829
|
-
method_options "--dry-run" => :boolean,
|
1830
|
-
"--force" => :boolean,
|
1831
|
-
"--wipe" => :boolean
|
1832
|
-
def install(*names)
|
1833
|
-
# uninstall existing gems of the ones we're going to install
|
1834
|
-
uninstall(*names) if options[:force] || options[:wipe]
|
1835
1885
|
|
1836
|
-
|
1837
|
-
|
1886
|
+
version_req = if options[:version]
|
1887
|
+
::Gem::Requirement.create(options[:version])
|
1888
|
+
end
|
1838
1889
|
|
1839
|
-
|
1840
|
-
update_dependency_repositories(deps) unless dry_run?
|
1890
|
+
framework_components = Merb::Stack.framework_components
|
1841
1891
|
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
if dry_run?
|
1846
|
-
note "Installing #{current_gem} from source..."
|
1892
|
+
gems.map do |gem|
|
1893
|
+
if version_req && framework_components.include?(gem)
|
1894
|
+
::Gem::Dependency.new(gem, version_req)
|
1847
1895
|
else
|
1848
|
-
|
1849
|
-
unless install_dependency_from_source(dependency)
|
1850
|
-
raise "gem source not found"
|
1851
|
-
end
|
1896
|
+
::Gem::Dependency.new(gem, ::Gem::Requirement.default)
|
1852
1897
|
end
|
1853
1898
|
end
|
1854
|
-
rescue => e
|
1855
|
-
error "Failed to install #{current_gem ? current_gem : 'gem'} (#{e.message})"
|
1856
1899
|
end
|
1857
1900
|
|
1858
|
-
|
1859
|
-
|
1860
|
-
# By default all specified gems are uninstalled. It's important to note that
|
1861
|
-
# so-called meta-gems or gems that match a set of Merb::Stack.components will
|
1862
|
-
# have their sub-gems uninstalled too. For example, uninstalling merb-more
|
1863
|
-
# will install all contained gems: merb-action-args, merb-assets, ...
|
1864
|
-
#
|
1865
|
-
# Existing dependencies will be clobbered; when :force => true then all gems
|
1866
|
-
# will be cleared, otherwise only existing local dependencies of the
|
1867
|
-
# matching component set will be removed. Additionally when :wipe => true,
|
1868
|
-
# the matching git repositories will be removed from the source directory.
|
1869
|
-
#
|
1870
|
-
# Examples:
|
1871
|
-
#
|
1872
|
-
# merb:source:uninstall merb-core merb-slices # uninstall all specified gems
|
1873
|
-
# merb:source:uninstall merb-core --wipe # force-uninstall a gem and clear repo
|
1874
|
-
|
1875
|
-
desc 'uninstall GEM_NAME [GEM_NAME, ...]', 'Unstall a gem (specify --force to remove the repo)'
|
1876
|
-
method_options "--version" => :optional, "--dry-run" => :boolean, "--wipe" => :boolean
|
1877
|
-
def uninstall(*names)
|
1878
|
-
# Remove the repos that contain the gem
|
1879
|
-
if options[:wipe]
|
1880
|
-
extract_repositories(names).each do |(name, url)|
|
1881
|
-
if File.directory?(src = File.join(source_dir, name))
|
1882
|
-
if dry_run?
|
1883
|
-
note "Removing #{src}..."
|
1884
|
-
else
|
1885
|
-
info "Removing #{src}..."
|
1886
|
-
FileUtils.rm_rf(src)
|
1887
|
-
end
|
1888
|
-
end
|
1889
|
-
end
|
1890
|
-
end
|
1891
|
-
|
1892
|
-
# Use the Merb::Gem#uninstall task to handle this
|
1893
|
-
gem_tasks = Merb::Gem.new
|
1894
|
-
gem_tasks.options = options
|
1895
|
-
gem_tasks.uninstall(*names)
|
1901
|
+
def strategy
|
1902
|
+
options[:strategy] || (options[:edge] ? 'edge' : 'stable')
|
1896
1903
|
end
|
1897
1904
|
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
#
|
1904
|
-
# merb:source:pull merb-core # update source of specified gem
|
1905
|
-
# merb:source:pull merb-slices # implicitly updates merb-more
|
1906
|
-
|
1907
|
-
desc 'pull REPO_NAME [GEM_NAME, ...]', 'Update git source repository from edge'
|
1908
|
-
def pull(*names)
|
1909
|
-
repos = extract_repositories(names)
|
1910
|
-
update_repositories(repos)
|
1911
|
-
unless repos.empty?
|
1912
|
-
message "Updated the following repositories:"
|
1913
|
-
repos.each { |name, url| puts "- #{name}: #{url}" }
|
1914
|
-
else
|
1915
|
-
warning "No repositories found to update!"
|
1905
|
+
def dependency_manager
|
1906
|
+
@_dependency_manager ||= begin
|
1907
|
+
instance = Merb::Dependencies.new
|
1908
|
+
instance.options = options
|
1909
|
+
instance
|
1916
1910
|
end
|
1917
|
-
end
|
1911
|
+
end
|
1918
1912
|
|
1919
|
-
|
1913
|
+
public
|
1920
1914
|
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
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
|
1929
1930
|
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
|
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
|
1938
1947
|
end
|
1939
|
-
source_manager.clone(name || repository_name, repository_url)
|
1940
1948
|
end
|
1941
1949
|
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
#
|
1946
|
-
# Example of contents:
|
1947
|
-
#
|
1948
|
-
# merb-core: git://github.com/myfork/merb-core.git
|
1949
|
-
# merb-more: git://github.com/myfork/merb-more.git
|
1950
|
-
|
1951
|
-
def self.repos(source_config = nil)
|
1952
|
-
source_config ||= begin
|
1953
|
-
local_config = File.join(Dir.pwd, 'config', 'git-sources.yml')
|
1954
|
-
user_config = File.join(ENV["HOME"] || ENV["APPDATA"], '.merb', 'git-sources.yml')
|
1955
|
-
File.exists?(local_config) ? local_config : user_config
|
1950
|
+
def self.framework_components
|
1951
|
+
%w[merb-core merb-more].inject([]) do |all, comp|
|
1952
|
+
all + components(comp)
|
1956
1953
|
end
|
1957
|
-
|
1958
|
-
|
1954
|
+
end
|
1955
|
+
|
1956
|
+
def self.components(comp = nil)
|
1957
|
+
if comp
|
1958
|
+
component_sets[comp]
|
1959
1959
|
else
|
1960
|
-
|
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
|
1961
1964
|
end
|
1962
1965
|
end
|
1963
1966
|
|
1964
|
-
def self.
|
1965
|
-
|
1967
|
+
def self.select_component_dependencies(dependencies, comp = nil)
|
1968
|
+
comps = components(comp) || []
|
1969
|
+
dependencies.select { |dep| comps.include?(dep.name) }
|
1966
1970
|
end
|
1967
1971
|
|
1968
|
-
|
1969
|
-
|
1970
|
-
@_default_repos ||= {
|
1971
|
-
'merb' => "git://github.com/wycats/merb.git",
|
1972
|
-
'merb-plugins' => "git://github.com/wycats/merb-plugins.git",
|
1973
|
-
'extlib' => "git://github.com/sam/extlib.git",
|
1974
|
-
'dm-core' => "git://github.com/sam/dm-core.git",
|
1975
|
-
'dm-more' => "git://github.com/sam/dm-more.git",
|
1976
|
-
'sequel' => "git://github.com/wayneeseguin/sequel.git",
|
1977
|
-
'do' => "git://github.com/sam/do.git",
|
1978
|
-
'thor' => "git://github.com/wycats/thor.git",
|
1979
|
-
'rake' => "git://github.com/jimweirich/rake.git"
|
1980
|
-
}
|
1972
|
+
def self.base_components
|
1973
|
+
%w[thor rake extlib]
|
1981
1974
|
end
|
1982
|
-
|
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
|
+
|
1983
2018
|
end
|
1984
2019
|
|
1985
2020
|
end
|