geminstaller 0.2.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.
Files changed (63) hide show
  1. data/COPYING +1 -0
  2. data/History.txt +4 -0
  3. data/LICENSE +21 -0
  4. data/Manifest.txt +62 -0
  5. data/README.txt +60 -0
  6. data/Rakefile +92 -0
  7. data/TODO.txt +88 -0
  8. data/bin/geminstaller +30 -0
  9. data/geminstaller.yml +34 -0
  10. data/lib/geminstaller/application.rb +105 -0
  11. data/lib/geminstaller/arg_parser.rb +162 -0
  12. data/lib/geminstaller/autogem.rb +43 -0
  13. data/lib/geminstaller/config.rb +69 -0
  14. data/lib/geminstaller/config_builder.rb +40 -0
  15. data/lib/geminstaller/dependency_injector.rb +129 -0
  16. data/lib/geminstaller/enhanced_stream_ui.rb +57 -0
  17. data/lib/geminstaller/exact_match_list_command.rb +16 -0
  18. data/lib/geminstaller/file_reader.rb +31 -0
  19. data/lib/geminstaller/gem_arg_processor.rb +44 -0
  20. data/lib/geminstaller/gem_command_line_proxy.rb +32 -0
  21. data/lib/geminstaller/gem_command_manager.rb +62 -0
  22. data/lib/geminstaller/gem_interaction_handler.rb +30 -0
  23. data/lib/geminstaller/gem_list_checker.rb +55 -0
  24. data/lib/geminstaller/gem_runner_proxy.rb +43 -0
  25. data/lib/geminstaller/gem_source_index_proxy.rb +21 -0
  26. data/lib/geminstaller/gem_spec_manager.rb +42 -0
  27. data/lib/geminstaller/geminstaller_error.rb +13 -0
  28. data/lib/geminstaller/hoe_extensions.rb +5 -0
  29. data/lib/geminstaller/install_processor.rb +56 -0
  30. data/lib/geminstaller/missing_dependency_finder.rb +41 -0
  31. data/lib/geminstaller/missing_file_error.rb +4 -0
  32. data/lib/geminstaller/noninteractive_chooser.rb +107 -0
  33. data/lib/geminstaller/output_filter.rb +49 -0
  34. data/lib/geminstaller/output_listener.rb +33 -0
  35. data/lib/geminstaller/output_observer.rb +32 -0
  36. data/lib/geminstaller/output_proxy.rb +36 -0
  37. data/lib/geminstaller/requires.rb +59 -0
  38. data/lib/geminstaller/rogue_gem_finder.rb +195 -0
  39. data/lib/geminstaller/ruby_gem.rb +44 -0
  40. data/lib/geminstaller/rubygems_exit.rb +5 -0
  41. data/lib/geminstaller/rubygems_extensions.rb +5 -0
  42. data/lib/geminstaller/unauthorized_dependency_prompt_error.rb +4 -0
  43. data/lib/geminstaller/unexpected_prompt_error.rb +4 -0
  44. data/lib/geminstaller/valid_platform_selector.rb +44 -0
  45. data/lib/geminstaller/version_specifier.rb +24 -0
  46. data/lib/geminstaller/yaml_loader.rb +22 -0
  47. data/lib/geminstaller.rb +102 -0
  48. data/start_local_gem_server.sh +1 -0
  49. data/test/test_all.rb +31 -0
  50. data/website/config.yaml +2 -0
  51. data/website/metainfo.yaml +72 -0
  52. data/website/src/code/index.page +25 -0
  53. data/website/src/community/index.page +14 -0
  54. data/website/src/community/links.page +9 -0
  55. data/website/src/default.css +168 -0
  56. data/website/src/default.template +41 -0
  57. data/website/src/documentation/documentation.page +417 -0
  58. data/website/src/documentation/index.page +88 -0
  59. data/website/src/documentation/tutorials.page +94 -0
  60. data/website/src/download.page +12 -0
  61. data/website/src/faq.page +7 -0
  62. data/website/src/index.page +38 -0
  63. metadata +107 -0
@@ -0,0 +1,42 @@
1
+ module GemInstaller
2
+ class GemSpecManager
3
+ attr_writer :gem_source_index_proxy, :valid_platform_selector, :output_filter
4
+
5
+ def search(gem_pattern, version_requirement)
6
+ @gem_source_index_proxy.refresh!
7
+ @gem_source_index_proxy.search(gem_pattern, version_requirement)
8
+ end
9
+
10
+ def is_gem_installed?(gem)
11
+ return local_matching_gems(gem).size > 0
12
+ end
13
+
14
+ def all_local_gems
15
+ all_local_specs = search('',GemInstaller::RubyGem.default_version)
16
+ return [] unless all_local_specs
17
+ all_local_gems = all_local_specs.collect do |spec|
18
+ gem = GemInstaller::RubyGem.new(spec.name, :version => spec.version.version)
19
+ end
20
+ return all_local_gems
21
+ end
22
+
23
+ def local_matching_gems(gem, exact_platform_match = true)
24
+ gem_name_regexp = /^#{gem.regexp_escaped_name}$/
25
+ found_gem_specs = search(gem_name_regexp,gem.version)
26
+ return [] unless found_gem_specs
27
+ matching_gem_specs = found_gem_specs.select do |gem_spec|
28
+ valid_platforms = @valid_platform_selector.select(gem.platform, exact_platform_match)
29
+ valid_platforms.include?(gem_spec.platform)
30
+ end
31
+ matching_gems = matching_gem_specs.map do |gem_spec|
32
+ GemInstaller::RubyGem.new(gem_spec.name, {:version => gem_spec.version.version, :platform => gem_spec.platform })
33
+ end
34
+ return matching_gems
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+
41
+
42
+
@@ -0,0 +1,13 @@
1
+ module GemInstaller
2
+ class GemInstallerError < RuntimeError
3
+ def descriptive_exit_message(message, command, args, listener)
4
+ args_string = args.join(" ")
5
+ descriptive_exit_message = "\n=========================================================\n"
6
+ descriptive_exit_message += "#{message}\n"
7
+ descriptive_exit_message += "Gem command was:\n #{command} #{args_string}\n\n"
8
+ descriptive_exit_message += "Gem command output was:\n"
9
+ descriptive_exit_message += listener.read!.join("\n")
10
+ descriptive_exit_message += "\n=========================================================\n\n"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class IndependentHoe < Hoe
2
+ def extra_deps
3
+ []
4
+ end
5
+ end
@@ -0,0 +1,56 @@
1
+ module GemInstaller
2
+ class InstallProcessor
3
+ attr_writer :gem_list_checker, :gem_command_manager, :gem_spec_manager, :missing_dependency_finder, :options, :output_filter
4
+ def process(gems)
5
+ gems.each do |gem|
6
+ install_gem(gem)
7
+ end
8
+ end
9
+
10
+ def install_gem(gem)
11
+ already_specified = false
12
+ if gem.check_for_upgrade
13
+ @gem_list_checker.verify_and_specify_remote_gem!(gem)
14
+ already_specified = true
15
+ end
16
+ gem_is_installed = @gem_spec_manager.is_gem_installed?(gem)
17
+ if gem_is_installed
18
+ @output_filter.geminstaller_output(:debug,"Gem #{gem.name}, version #{gem.version} is already installed.\n")
19
+ else
20
+ @gem_list_checker.verify_and_specify_remote_gem!(gem) unless already_specified
21
+ @output_filter.geminstaller_output(:install,"Invoking gem install for #{gem.name}, version #{gem.version}.\n")
22
+ output_lines = @gem_command_manager.install_gem(gem)
23
+ print_dependency_install_messages(gem, output_lines) unless @options[:silent]
24
+ end
25
+ if gem.fix_dependencies
26
+ fix_dependencies(gem)
27
+ end
28
+ end
29
+
30
+ def print_dependency_install_messages(gem, output_lines)
31
+ output_lines.each do |line|
32
+ line =~ /Successfully installed /
33
+ match = $'
34
+ next unless match
35
+ next if match =~ /#{gem.name}-/
36
+ @output_filter.geminstaller_output(:install,"Rubygems automatically installed dependency gem #{match}\n")
37
+ end
38
+ end
39
+
40
+ def fix_dependencies(gem)
41
+ missing_dependencies = @missing_dependency_finder.find(gem)
42
+ while (missing_dependencies.size > 0)
43
+ missing_dependencies.each do |missing_dependency|
44
+ @output_filter.geminstaller_output(:install,"Installing #{missing_dependency.name} (#{missing_dependency.version})\n")
45
+ # recursively call install_gem to install the missing dependency. Since fix_dependencies
46
+ # should never be set on an auto-created missing dependency gem, there is no risk of an
47
+ # endless loop or stack overflow.
48
+ install_gem(missing_dependency)
49
+ end
50
+ # continue to look for and install missing dependencies until none are found
51
+ missing_dependencies = @missing_dependency_finder.find(gem)
52
+ end
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,41 @@
1
+ module GemInstaller
2
+ class MissingDependencyFinder
3
+ attr_writer :gem_command_manager, :gem_spec_manager, :gem_arg_processor, :output_filter
4
+ def find(dependent_gem)
5
+ # NOTE: this doesn't resolve platforms, there's currently no way to know what
6
+ # platform should be selected for a dependency gem. Best-effort handling
7
+ # of ambiguous platforms on dependency gems will be handled elsewhere
8
+ matching_dependent_gems = @gem_spec_manager.local_matching_gems(dependent_gem)
9
+ missing_dependencies = []
10
+ install_options = dependent_gem.install_options
11
+ add_include_dependency_option(install_options)
12
+ common_args = @gem_arg_processor.strip_non_common_gem_args(install_options)
13
+ matching_dependent_gems.each do |matching_dependent_gem|
14
+ message_already_printed = false
15
+ dependency_gems = @gem_command_manager.dependency(matching_dependent_gem.name, matching_dependent_gem.version.to_s, common_args)
16
+ dependency_gems.each do |dependency_gem|
17
+ dependency_gem.install_options = install_options
18
+ local_matching_dependency_gems = @gem_spec_manager.local_matching_gems(dependency_gem, false)
19
+ unless local_matching_dependency_gems.size > 0
20
+ unless message_already_printed
21
+ @output_filter.geminstaller_output(:info, "Missing dependencies found for #{matching_dependent_gem.name} (#{matching_dependent_gem.version}):\n")
22
+ message_already_printed = true
23
+ end
24
+ # TODO: print install options too?
25
+ @output_filter.geminstaller_output(:info, " #{dependency_gem.name} (#{dependency_gem.version})\n")
26
+ missing_dependencies << dependency_gem
27
+ end
28
+ # recurse to find any missing dependencies in the tree
29
+ sub_dependencies = find(dependency_gem)
30
+ missing_dependencies += sub_dependencies if sub_dependencies.size > 0
31
+ end
32
+ end
33
+ return missing_dependencies
34
+ end
35
+
36
+ def add_include_dependency_option(install_options)
37
+ return if install_options.index('-y') or install_options.index('--include-dependencies')
38
+ install_options << '--include-dependencies'
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,4 @@
1
+ module GemInstaller
2
+ class MissingFileError < GemInstaller::GemInstallerError
3
+ end
4
+ end
@@ -0,0 +1,107 @@
1
+ module GemInstaller
2
+ # Format for "install" prompt list: "#{spec.name} #{spec.version} (#{spec.platform})"
3
+ # Format for "uninstall" prompt list: "#{spec.name}-#{spec.version}" for ruby, "#{spec.name}-#{spec.version}-#{spec.platform}" (gem.full_name) for binary
4
+ class NoninteractiveChooser
5
+ def initialize
6
+ @question = nil
7
+ end
8
+
9
+ def choose(question, list, dependent_gem_name, dependent_gem_version, valid_platforms)
10
+ @question = question
11
+ @list = list
12
+ @dependent_gem_name = dependent_gem_name
13
+ @dependent_gem_version = dependent_gem_version
14
+ @valid_platforms = valid_platforms
15
+ raise GemInstaller::GemInstallerError.new("Internal GemInstaller Error, unexpected choice prompt question: '#{question}'") unless
16
+ install_list_type? or uninstall_list_type?
17
+
18
+ raise GemInstaller::GemInstallerError.new("valid_platforms must be passed as an array.") unless
19
+ valid_platforms.respond_to? :shift
20
+
21
+ raise GemInstaller::GemInstallerError.new("Internal GemInstaller Error, multiple platforms cannot be specified for an uninstall prompt") if
22
+ uninstall_list_type? and valid_platforms.size > 1
23
+
24
+ index = nil
25
+ valid_platforms.each do |platform|
26
+ index = find_matching_line(platform)
27
+ break if index
28
+ end
29
+
30
+ return @list[index], index if index
31
+
32
+ # if we didn't find a match, raise a descriptive error
33
+ action = install_list_type? ? 'install' : 'uninstall'
34
+ name = @dependent_gem_name ? "#{@dependent_gem_name}" : "'any name'"
35
+ version = @dependent_gem_version ? "#{@dependent_gem_version}" : "'any version'"
36
+ platform = @valid_platforms ? " (#{@valid_platforms.join(' or ')})" : ''
37
+ error_message = "Error: Unable to select gem from list: \"#{name} #{version}#{platform}\". Available gems are:\n"
38
+ list.each do |item|
39
+ # skip last 'cancel' list entry, it's not a real gem
40
+ next if item == list.last
41
+ error_message += " " + item + "\n"
42
+ end
43
+ raise GemInstaller::GemInstallerError.new(error_message)
44
+ end
45
+
46
+ def find_matching_line(platform)
47
+ required_list_item_regexp = required_name_and_version_regexp + required_platform_regexp(platform)
48
+ line_selector = /^#{required_list_item_regexp}$/
49
+ @list.each_with_index do |item, index|
50
+ if item =~ line_selector
51
+ return index
52
+ end
53
+ end
54
+ return nil
55
+ end
56
+
57
+ def required_name_and_version_regexp
58
+ required_name_regexp = ".*?"
59
+ required_version_regexp = ".*?"
60
+ if uninstall_list_type? or dependent_gem?
61
+ # match the exact name and version if it's an uninstall prompt or a dependent gem
62
+ required_name_regexp = Regexp.escape(@dependent_gem_name) if @dependent_gem_name
63
+ required_version_regexp = Regexp.escape(@dependent_gem_version) if @dependent_gem_version
64
+ end
65
+ "#{required_name_regexp}[\s-]{0,1}#{required_version_regexp}"
66
+ end
67
+
68
+ def required_platform_regexp(platform_to_match)
69
+ return "" unless platform_to_match
70
+ required_platform = ""
71
+ escaped_platform_to_match = Regexp.escape(platform_to_match)
72
+ platform_regex = nil
73
+ if dependent_gem?
74
+ # do an exact match on the platform if this is the dependent gem
75
+ platform_regex = "#{escaped_platform_to_match}"
76
+ else
77
+ # do a wildcard match on the platform if it's not the dependent gem
78
+ platform_regex = ".*?#{escaped_platform_to_match}.*?"
79
+ end
80
+ # install list types always have the platform for each gem in parenthesis, even if it is ruby
81
+ if (install_list_type?)
82
+ required_platform = " \\(#{platform_regex}\\)"
83
+ end
84
+ # uninstall list types have the gem full_name, which is the platform for each gem appended after a dash, but only if it is not ruby
85
+ if (uninstall_list_type? && platform_to_match.to_s != GemInstaller::RubyGem.default_platform)
86
+ required_platform = "-.*?#{platform_regex}.*?"
87
+ end
88
+ required_platform
89
+ end
90
+
91
+ def install_list_type?(question = @question)
92
+ question =~ /to install/
93
+ end
94
+
95
+ def uninstall_list_type?(question = @question)
96
+ question =~ /to uninstall/
97
+ end
98
+
99
+ def dependent_gem?(dependent_gem_name = @dependent_gem_name, list = @list)
100
+ # return true if it's an install prompt, and the list contains the gem for which the original install request
101
+ # was made (in other words, it's a dependent gem, not a dependency gem)
102
+ install_format_exact_name_match_regexp = /^#{dependent_gem_name}\s.*/
103
+ install_list_type? and list[0] =~ install_format_exact_name_match_regexp
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,49 @@
1
+ module GemInstaller
2
+ class OutputFilter
3
+ attr_writer :output_proxy, :options
4
+
5
+ def rubygems_output(type, message)
6
+ return if @options[:silent]
7
+ return unless rubygems_output_type_matches?(type)
8
+ output(:rubygems, type, message)
9
+ end
10
+
11
+ def geminstaller_output(type, message)
12
+ return if @options[:silent]
13
+ return unless geminstaller_output_type_matches?(type)
14
+ output(:geminstaller, type, message)
15
+ end
16
+
17
+ def output(source, type, message)
18
+ message = format_rubygems_message(type,message) if source == :rubygems
19
+ if (source == :geminstaller and type == :error)
20
+ @output_proxy.syserr(message)
21
+
22
+ else
23
+ @output_proxy.sysout(message)
24
+ end
25
+ end
26
+
27
+ def format_rubygems_message(type, message)
28
+ prefix = case type
29
+ when :stdout : "[RubyGems:stdout] "
30
+ when :stderr : "[RubyGems:stderr] "
31
+ end
32
+ "#{prefix}#{message}"
33
+ end
34
+
35
+ def rubygems_output_type_matches?(type)
36
+ return false unless @options[:rubygems_output]
37
+ return true if @options[:rubygems_output].include?(:all)
38
+ return true if @options[:rubygems_output].include?(type)
39
+ return false
40
+ end
41
+
42
+ def geminstaller_output_type_matches?(type)
43
+ return false unless @options[:geminstaller_output]
44
+ return true if @options[:geminstaller_output].include?(:all)
45
+ return true if @options[:geminstaller_output].include?(type)
46
+ return false
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ dir = File.dirname(__FILE__)
2
+ require File.expand_path("#{dir}/requires.rb")
3
+
4
+ module GemInstaller
5
+ class OutputListener
6
+ attr_writer :output_filter
7
+
8
+ def initialize
9
+ @messages = []
10
+ @output_filter = nil
11
+ end
12
+
13
+ def notify(msg, stream = :stdout)
14
+ @messages.push(msg)
15
+ return unless @output_filter
16
+ if stream == :stdout or stream == :stderr
17
+ @output_filter.rubygems_output(stream, msg)
18
+ else
19
+ raise GemInstaller::GemInstallerError.new("Invalid stream specified: #{@stream}")
20
+ end
21
+ end
22
+
23
+ def read
24
+ @messages.dup
25
+ end
26
+
27
+ def read!
28
+ messages = @messages.dup
29
+ @messages.clear
30
+ messages
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module GemInstaller
2
+ class OutputObserver
3
+ attr_writer :stream
4
+ # TODO: GemRunnerProxy should raise exception if listener still has any leftover output when run is invoked.
5
+ def initialize
6
+ @stream = :stdout
7
+ @listeners = []
8
+ end
9
+
10
+ def register(listener)
11
+ listener = [listener] unless listener.is_a?(Array)
12
+ @listeners += listener
13
+ end
14
+
15
+ def unregister(listener)
16
+ @listeners.delete(listener)
17
+ end
18
+
19
+ def print(output)
20
+ @listeners.each do |listener|
21
+ listener.notify(output, @stream)
22
+ end
23
+ end
24
+
25
+ def puts(output)
26
+ print("#{output}\n")
27
+ end
28
+
29
+ def flush
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ module GemInstaller
2
+ class OutputProxy
3
+ attr_writer :options
4
+ def default_stream=(stream)
5
+ raise GemInstaller::GemInstallerError.new("Invalid default stream: #{stream}") unless stream == :stderr or stream == :stdout
6
+ @default_stream = stream
7
+ end
8
+
9
+ def sysout(out)
10
+ return if silent?
11
+ $stdout.print out
12
+ end
13
+
14
+ def syserr(err)
15
+ return if silent?
16
+ if @options[:redirect_stderr_to_stdout]
17
+ $stdout.print err
18
+ else
19
+ $stderr.print err
20
+ end
21
+ end
22
+
23
+ # TODO: should remove this, make callers explicitly choose.
24
+ def output(output)
25
+ if @default_stream == :stdout
26
+ sysout(output)
27
+ else
28
+ syserr(output)
29
+ end
30
+ end
31
+
32
+ def silent?
33
+ @options && @options[:silent]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,59 @@
1
+ dir = File.dirname(__FILE__)
2
+
3
+ # requires for rubygems
4
+ require 'rubygems'
5
+ require 'rubygems/doc_manager'
6
+ require 'rubygems/config_file'
7
+ require 'rubygems/cmd_manager'
8
+ require 'rubygems/gem_runner'
9
+ require 'rubygems/remote_installer'
10
+ require 'rubygems/installer'
11
+ require 'rubygems/validator'
12
+
13
+ # third party libs
14
+ require 'erb'
15
+ require 'optparse'
16
+ require 'yaml'
17
+ require 'fileutils'
18
+ require 'tempfile'
19
+
20
+ # third party lib extensions
21
+ require File.expand_path("#{dir}/rubygems_extensions")
22
+
23
+ # internal files
24
+ require File.expand_path("#{dir}/../geminstaller")
25
+ require File.expand_path("#{dir}/application")
26
+ require File.expand_path("#{dir}/arg_parser")
27
+ require File.expand_path("#{dir}/autogem")
28
+ require File.expand_path("#{dir}/config")
29
+ require File.expand_path("#{dir}/config_builder")
30
+ require File.expand_path("#{dir}/dependency_injector")
31
+ require File.expand_path("#{dir}/enhanced_stream_ui")
32
+ require File.expand_path("#{dir}/exact_match_list_command")
33
+ require File.expand_path("#{dir}/file_reader")
34
+ require File.expand_path("#{dir}/gem_arg_processor")
35
+ require File.expand_path("#{dir}/gem_command_line_proxy")
36
+ require File.expand_path("#{dir}/gem_command_manager")
37
+ require File.expand_path("#{dir}/gem_interaction_handler")
38
+ require File.expand_path("#{dir}/gem_list_checker")
39
+ require File.expand_path("#{dir}/gem_runner_proxy")
40
+ require File.expand_path("#{dir}/gem_source_index_proxy")
41
+ require File.expand_path("#{dir}/gem_spec_manager")
42
+ require File.expand_path("#{dir}/geminstaller_error")
43
+ require File.expand_path("#{dir}/install_processor")
44
+ require File.expand_path("#{dir}/missing_dependency_finder")
45
+ require File.expand_path("#{dir}/missing_file_error")
46
+ require File.expand_path("#{dir}/noninteractive_chooser")
47
+ require File.expand_path("#{dir}/output_filter")
48
+ require File.expand_path("#{dir}/output_listener")
49
+ require File.expand_path("#{dir}/output_observer")
50
+ require File.expand_path("#{dir}/output_proxy")
51
+ require File.expand_path("#{dir}/rogue_gem_finder")
52
+ require File.expand_path("#{dir}/rubygems_exit")
53
+ require File.expand_path("#{dir}/ruby_gem")
54
+ require File.expand_path("#{dir}/unexpected_prompt_error")
55
+ require File.expand_path("#{dir}/unauthorized_dependency_prompt_error")
56
+ require File.expand_path("#{dir}/valid_platform_selector")
57
+ require File.expand_path("#{dir}/version_specifier")
58
+ require File.expand_path("#{dir}/yaml_loader")
59
+
@@ -0,0 +1,195 @@
1
+ module GemInstaller
2
+ class RogueGemFinder
3
+ attr_writer :output_proxy, :gem_command_manager, :gem_spec_manager, :boilerplate_lines, :preinstalled_gem_names, :preinstalled_comment
4
+
5
+ def print_rogue_gems(config_gems, config_file_paths)
6
+ @boilerplate_lines ||= default_boilerplate_lines(config_gems, config_file_paths)
7
+ @preinstalled_gem_names ||= default_preinstalled_gem_names
8
+ @preinstalled_comment ||= default_preinstalled_comment
9
+ @config_gems_with_dependencies = []
10
+ config_gems.each do |config_gem|
11
+ process_gem(config_gem)
12
+ end
13
+ all_local_gems = @gem_spec_manager.all_local_gems
14
+ rogue_gems = []
15
+ all_local_gems.each do |local_gem|
16
+ config_match_found_for_local = false
17
+ @config_gems_with_dependencies.each do |config_gem|
18
+ name_matches = config_gem.name == local_gem.name
19
+ config_gem_version_requirement = Gem::Version::Requirement.new [config_gem.version]
20
+ local_gem_version = Gem::Version.new(local_gem.version)
21
+ version_matches = config_gem_version_requirement.satisfied_by?(local_gem_version)
22
+ if (name_matches and version_matches)
23
+ config_match_found_for_local = true
24
+ break
25
+ end
26
+ end
27
+ rogue_gems << local_gem unless config_match_found_for_local
28
+ end
29
+ yaml = format_to_yaml(rogue_gems)
30
+
31
+ handle_output(yaml)
32
+ end
33
+
34
+ def default_boilerplate_lines(config_gems, config_file_paths)
35
+ boilerplate = []
36
+ boilerplate << [
37
+ "#",
38
+ "# This is a GemInstaller config file (http://geminstaller.rubyforge.org)",
39
+ "# It was generated using the 'geminstaller --print-rogue-gems' option on #{Time.now}",
40
+ "#",
41
+ "# You can bootstrap your config by piping the output to a file: ",
42
+ "# 'geminstaller --print-rogue-gems > geminstaller.yml'",
43
+ "#",
44
+ "# You can then install these gems on another system by running geminstaller with this file.",
45
+ "#"
46
+ ]
47
+
48
+ if config_file_paths.size == 0
49
+ boilerplate << "# Since there was no config file specified, the 'gems:' section below lists all gems on your system."
50
+ else
51
+ boilerplate << "# The following config file(s) and gems were already specified:"
52
+ boilerplate << "# Files:"
53
+ config_file_paths.each do |config_file_path|
54
+ boilerplate << "# * " + config_file_path
55
+ end
56
+ boilerplate << "# Gems:"
57
+ if config_gems.size > 0
58
+ config_gems.each do |config_gem|
59
+ boilerplate << "# * #{config_gem.name} #{config_gem.version}"
60
+ end
61
+ else
62
+ boilerplate << "# No Gems"
63
+ end
64
+ end
65
+ boilerplate << "#"
66
+ boilerplate << "defaults:"
67
+ boilerplate << " install_options: --include-dependencies"
68
+ return boilerplate
69
+ end
70
+
71
+ def default_preinstalled_gem_names
72
+ # This is the list of preinstalled gems from the Ruby windows 1-click installer, v186-25
73
+ #
74
+ # fxri (0.3.6)
75
+ # Graphical interface to the RI documentation, with search engine.
76
+ #
77
+ # fxruby (1.6.6)
78
+ # FXRuby is the Ruby binding to the FOX GUI toolkit.
79
+ #
80
+ # hpricot (0.4)
81
+ # a swift, liberal HTML parser with a fantastic library
82
+ #
83
+ # log4r (1.0.5)
84
+ # Log4r is a comprehensive and flexible logging library for Ruby.
85
+ #
86
+ # rake (0.7.2)
87
+ # Ruby based make-like utility.
88
+ #
89
+ # sources (0.0.1)
90
+ # This package provides download sources for remote gem installation
91
+ #
92
+ # win32-clipboard (0.4.1)
93
+ # A package for interacting with the Windows clipboard
94
+ #
95
+ # win32-dir (0.3.1)
96
+ # Extra constants and methods for the Dir class on Windows.
97
+ #
98
+ # win32-eventlog (0.4.3)
99
+ # Interface for the MS Windows Event Log.
100
+ #
101
+ # win32-file (0.5.3)
102
+ # Extra or redefined methods for the File class on Windows.
103
+ #
104
+ # win32-file-stat (1.2.3)
105
+ # A File::Stat class tailored to MS Windows
106
+ #
107
+ # win32-process (0.5.1)
108
+ # Adds fork, wait, wait2, waitpid, waitpid2 and a special kill method
109
+ #
110
+ # win32-sapi (0.1.3)
111
+ # An interface to the MS SAPI (Sound API) library.
112
+ #
113
+ # win32-sound (0.4.0)
114
+ # A package for playing with sound on Windows.
115
+ #
116
+ # windows-pr (0.6.2)
117
+ # Windows functions and constants predefined via Win32API
118
+
119
+ if RUBY_PLATFORM =~ /mswin/
120
+ return [
121
+ 'fxri',
122
+ 'fxruby',
123
+ 'hpricot',
124
+ 'log4r',
125
+ 'rake',
126
+ 'sources',
127
+ 'win32-clipboard',
128
+ 'win32-dir',
129
+ 'win32-eventlog',
130
+ 'win32-file',
131
+ 'win32-file-stat',
132
+ 'win32-process',
133
+ 'win32-sapi',
134
+ 'win32-sound',
135
+ 'windows-pr'
136
+ ]
137
+ end
138
+ return ['sources']
139
+ end
140
+
141
+ def default_preinstalled_comment
142
+ "# NOTE: This gem may have been automatially installed with Ruby, and not actually be used by your app(s)."
143
+ end
144
+
145
+ def handle_output(yaml)
146
+ yaml_lines = yaml.split("\n")
147
+ yaml_doc_separator = yaml_lines.delete_at(0)
148
+
149
+ output = []
150
+ output.push(yaml_doc_separator)
151
+
152
+ output << @boilerplate_lines
153
+
154
+ yaml_lines.each do |yaml_line|
155
+ name_parser_regexp = /- name: (.*)/
156
+ yaml_line =~ name_parser_regexp
157
+ gem_name = $1
158
+ preinstalled_comment = ''
159
+ if @preinstalled_gem_names.include?(gem_name)
160
+ preinstalled_comment = " " + @preinstalled_comment
161
+ end
162
+ output.push yaml_line + preinstalled_comment
163
+ end
164
+
165
+ output_string = output.join("\n")
166
+ @output_proxy.sysout output_string
167
+ output_string
168
+ end
169
+
170
+ def process_gem(gem)
171
+ @config_gems_with_dependencies << gem
172
+ process_gem_dependencies(gem)
173
+ end
174
+
175
+ def process_gem_dependencies(gem)
176
+ # TODO: this method is duplicated in autogem Should abstract and take a block
177
+ matching_gems = @gem_spec_manager.local_matching_gems(gem)
178
+ matching_gems.each do |matching_gem|
179
+ dependency_gems = @gem_command_manager.dependency(matching_gem.name, matching_gem.version.to_s)
180
+ dependency_gems.each do |dependency_gem|
181
+ process_gem(dependency_gem)
182
+ end
183
+ end
184
+ end
185
+
186
+ def format_to_yaml(gems)
187
+ names_and_versions = []
188
+ gems.each do |gem|
189
+ names_and_versions << {'name' => gem.name, 'version' => gem.version}
190
+ end
191
+ hash_for_yaml = {'gems' => names_and_versions}
192
+ YAML.dump(hash_for_yaml)
193
+ end
194
+ end
195
+ end