geminstaller 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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