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,43 @@
1
+ module GemInstaller
2
+ class Autogem
3
+ attr_writer :gem_command_manager, :gem_spec_manager, :gem_source_index_proxy
4
+ def autogem(gems)
5
+ @gem_source_index_proxy.refresh!
6
+ reversed_gems = gems.reverse!
7
+ @completed_names = []
8
+ @completed_gems = []
9
+ reversed_gems.each do |gem|
10
+ process_gem(gem)
11
+ end
12
+ @completed_gems
13
+ end
14
+
15
+ def process_gem(gem)
16
+ unless @completed_names.index(gem.name) or gem.no_autogem
17
+ invoke_require_gem_command(gem.name, gem.version)
18
+ @completed_names << gem.name
19
+ @completed_gems << gem
20
+ end
21
+ process_gem_dependencies(gem)
22
+ end
23
+
24
+ def process_gem_dependencies(gem)
25
+ # TODO: this method is duplicated in rogue_gem_finder. Should abstract and take a block
26
+ matching_gems = @gem_spec_manager.local_matching_gems(gem)
27
+ matching_gems.each do |matching_gem|
28
+ dependency_gems = @gem_command_manager.dependency(matching_gem.name, matching_gem.version.to_s)
29
+ dependency_gems.each do |dependency_gem|
30
+ process_gem(dependency_gem)
31
+ end
32
+ end
33
+ end
34
+
35
+ def invoke_require_gem_command(name, version)
36
+ if Gem::RubyGemsVersion.index('0.8') == 0
37
+ require_gem(name, version)
38
+ else
39
+ gem(name, version)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ module GemInstaller
2
+ class Config
3
+ def initialize(yaml)
4
+ @yaml = yaml
5
+ @default_install_options_string = nil
6
+ end
7
+
8
+ def gems
9
+ parse_defaults
10
+ gem_defs = @yaml["gems"]
11
+ gems = []
12
+ gem_defs.each do |gem_def|
13
+ name = gem_def['name']
14
+ version = gem_def['version'].to_s
15
+ platform = gem_def['platform'].to_s
16
+ # get install_options for specific gem, if specified
17
+ install_options_string = gem_def['install_options'].to_s
18
+ # if no install_options were specified for specific gem, and default install_options were specified...
19
+ if install_options_string.empty? &&
20
+ !@default_install_options_string.nil? &&
21
+ !@default_install_options_string.empty? then
22
+ # then use the default install_options
23
+ install_options_string = @default_install_options_string
24
+ end
25
+ install_options_array = []
26
+ # if there was an install options string specified, default or gem-specific, parse it to an array
27
+ install_options_array = install_options_string.split(" ") unless install_options_string.empty?
28
+
29
+ check_for_upgrade = gem_def['check_for_upgrade']
30
+ if check_for_upgrade.nil? && defined? @default_check_for_upgrade then
31
+ check_for_upgrade = @default_check_for_upgrade
32
+ end
33
+
34
+ fix_dependencies = gem_def['fix_dependencies']
35
+ if fix_dependencies.nil? && defined? @default_fix_dependencies then
36
+ fix_dependencies = @default_fix_dependencies
37
+ end
38
+
39
+ no_autogem = gem_def['no_autogem']
40
+ if no_autogem.nil? && defined? @default_no_autogem then
41
+ no_autogem = @default_no_autogem
42
+ end
43
+
44
+ gem = GemInstaller::RubyGem.new(
45
+ name,
46
+ :version => version,
47
+ :platform => platform,
48
+ :install_options => install_options_array,
49
+ :check_for_upgrade => check_for_upgrade,
50
+ :no_autogem => no_autogem,
51
+ :fix_dependencies => fix_dependencies)
52
+ gems << gem
53
+ end
54
+ gems.sort!
55
+ return gems
56
+ end
57
+
58
+ protected
59
+
60
+ def parse_defaults
61
+ defaults = @yaml["defaults"]
62
+ return if defaults.nil?
63
+ @default_install_options_string = defaults['install_options']
64
+ @default_check_for_upgrade = defaults['check_for_upgrade']
65
+ @default_fix_dependencies = defaults['fix_dependencies']
66
+ @default_no_autogem = defaults['no_autogem']
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,40 @@
1
+ dir = File.dirname(__FILE__)
2
+ require File.expand_path("#{dir}/requires.rb")
3
+
4
+ module GemInstaller
5
+ class ConfigBuilder
6
+ attr_reader :config_file_paths_array
7
+ attr_writer :file_reader
8
+ attr_writer :yaml_loader
9
+ attr_writer :config_file_paths
10
+
11
+ def self.default_config_file_path
12
+ 'geminstaller.yml'
13
+ end
14
+
15
+ def build_config
16
+ @config_file_paths ||= GemInstaller::ConfigBuilder.default_config_file_path
17
+ @config_file_paths_array = @config_file_paths.split(",")
18
+ merged_defaults = {}
19
+ merged_gems = {}
20
+ @config_file_paths_array.each do |path|
21
+ file_contents = @file_reader.read(path)
22
+ next unless file_contents
23
+ next if file_contents.empty?
24
+ file_contents_erb = ERB.new(%{#{file_contents}})
25
+ yaml = @yaml_loader.load(file_contents_erb.result)
26
+ merged_defaults.merge!(yaml['defaults']) unless yaml['defaults'].nil?
27
+ next unless yaml['gems']
28
+ yaml['gems'].each do |gem|
29
+ gem_key = [gem['name'],gem['version'],gem['platform']].join('-')
30
+ merged_gems[gem_key] = gem
31
+ end
32
+ end
33
+ merged_yaml = {}
34
+ merged_yaml['defaults'] = merged_defaults
35
+ merged_yaml['gems'] = merged_gems.values
36
+ config = GemInstaller::Config.new(merged_yaml)
37
+ config
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,129 @@
1
+ module GemInstaller
2
+ class DependencyInjector
3
+ def registry
4
+ @registry ||= create_registry
5
+ end
6
+
7
+ def create_registry
8
+ # define the service registry
9
+ @registry = GemInstaller::Registry.new
10
+ end
11
+ end
12
+
13
+ class Registry
14
+ attr_accessor :file_reader, :yaml_loader, :output_proxy, :config_builder, :gem_source_index, :gem_runner_proxy
15
+ attr_accessor :gem_runner, :gem_command_manager, :gem_list_checker, :app, :arg_parser, :options, :noninteractive_chooser
16
+ attr_accessor :gem_interaction_handler, :install_processor, :missing_dependency_finder, :valid_platform_selector
17
+ attr_accessor :output_listener, :outs_output_observer, :errs_output_observer, :output_filter, :autogem, :rogue_gem_finder
18
+ attr_accessor :gem_spec_manager
19
+
20
+ def initialize
21
+ @options = {}
22
+ @arg_parser = GemInstaller::ArgParser.new
23
+ @arg_parser.options = @options
24
+
25
+ @file_reader = GemInstaller::FileReader.new
26
+ @yaml_loader = GemInstaller::YamlLoader.new
27
+ @gem_arg_processor = GemInstaller::GemArgProcessor.new
28
+ @version_specifier = GemInstaller::VersionSpecifier.new
29
+ @output_proxy = GemInstaller::OutputProxy.new
30
+ @output_proxy.options = @options
31
+ @output_filter = GemInstaller::OutputFilter.new
32
+ @output_filter.options = @options
33
+ @output_filter.output_proxy = @output_proxy
34
+
35
+
36
+ @output_listener = GemInstaller::OutputListener.new
37
+ @output_listener.output_filter = @output_filter
38
+
39
+ @valid_platform_selector = GemInstaller::ValidPlatformSelector.new
40
+ @valid_platform_selector.output_filter = @output_filter
41
+ @valid_platform_selector.options = @options
42
+
43
+ @config_builder = GemInstaller::ConfigBuilder.new
44
+ @config_builder.file_reader = @file_reader
45
+ @config_builder.yaml_loader = @yaml_loader
46
+
47
+ @gem_source_index = Gem::SourceIndex.new
48
+ @gem_source_index_proxy = GemInstaller::GemSourceIndexProxy.new
49
+ @gem_source_index_proxy.gem_source_index = @gem_source_index
50
+
51
+ @gem_interaction_handler = GemInstaller::GemInteractionHandler.new
52
+ @noninteractive_chooser_class = GemInstaller::NoninteractiveChooser
53
+ @gem_interaction_handler.noninteractive_chooser_class = @noninteractive_chooser_class
54
+ @gem_interaction_handler.valid_platform_selector = @valid_platform_selector
55
+
56
+ @outs_output_observer = GemInstaller::OutputObserver.new
57
+ @outs_output_observer.stream = :stdout
58
+ @outs_output_observer.register(@output_listener)
59
+ @errs_output_observer = GemInstaller::OutputObserver.new
60
+ @errs_output_observer.stream = :stderr
61
+ @errs_output_observer.register(@output_listener)
62
+
63
+ @enhanced_stream_ui = GemInstaller::EnhancedStreamUI.new
64
+ @enhanced_stream_ui.outs = @outs_output_observer
65
+ @enhanced_stream_ui.errs = @errs_output_observer
66
+ @enhanced_stream_ui.gem_interaction_handler = @gem_interaction_handler
67
+
68
+ @gem_runner_class = Gem::GemRunner
69
+ @gem_cmd_manager_class = Gem::CommandManager
70
+ @exact_match_list_command = GemInstaller::ExactMatchListCommand.new
71
+ @gem_runner_proxy = GemInstaller::GemRunnerProxy.new
72
+ @gem_runner_proxy.gem_runner_class = @gem_runner_class
73
+ @gem_runner_proxy.gem_cmd_manager_class = @gem_cmd_manager_class
74
+ @gem_runner_proxy.output_listener = @output_listener
75
+ @gem_runner_proxy.enhanced_stream_ui = @enhanced_stream_ui
76
+ @gem_runner_proxy.options = @options
77
+ @gem_runner_proxy.output_filter = @output_filter
78
+ @gem_runner_proxy.exact_match_list_command = @exact_match_list_command
79
+
80
+ @gem_spec_manager = GemInstaller::GemSpecManager.new
81
+ @gem_spec_manager.valid_platform_selector = @valid_platform_selector
82
+ @gem_spec_manager.gem_source_index_proxy = @gem_source_index_proxy
83
+ @gem_spec_manager.output_filter = @output_filter
84
+
85
+ @gem_command_manager = GemInstaller::GemCommandManager.new
86
+ @gem_command_manager.gem_spec_manager = @gem_spec_manager
87
+ @gem_command_manager.gem_runner_proxy = @gem_runner_proxy
88
+ @gem_command_manager.gem_interaction_handler = @gem_interaction_handler
89
+
90
+ @rogue_gem_finder = GemInstaller::RogueGemFinder.new
91
+ @rogue_gem_finder.gem_command_manager = @gem_command_manager
92
+ @rogue_gem_finder.gem_spec_manager = @gem_spec_manager
93
+ @rogue_gem_finder.output_proxy = @output_proxy
94
+
95
+ @autogem = GemInstaller::Autogem.new
96
+ @autogem.gem_command_manager = @gem_command_manager
97
+ @autogem.gem_source_index_proxy = @gem_source_index_proxy
98
+ @autogem.gem_spec_manager = @gem_spec_manager
99
+
100
+ @gem_list_checker = GemInstaller::GemListChecker.new
101
+ @gem_list_checker.gem_command_manager = @gem_command_manager
102
+ @gem_list_checker.gem_arg_processor = @gem_arg_processor
103
+ @gem_list_checker.version_specifier = @version_specifier
104
+
105
+ @missing_dependency_finder = GemInstaller::MissingDependencyFinder.new
106
+ @missing_dependency_finder.gem_command_manager = @gem_command_manager
107
+ @missing_dependency_finder.gem_spec_manager = @gem_spec_manager
108
+ @missing_dependency_finder.gem_arg_processor = @gem_arg_processor
109
+ @missing_dependency_finder.output_filter = @output_filter
110
+
111
+ @install_processor = GemInstaller::InstallProcessor.new
112
+ @install_processor.options = @options
113
+ @install_processor.gem_list_checker = @gem_list_checker
114
+ @install_processor.gem_command_manager = @gem_command_manager
115
+ @install_processor.gem_spec_manager = @gem_spec_manager
116
+ @install_processor.missing_dependency_finder = @missing_dependency_finder
117
+ @install_processor.output_filter = @output_filter
118
+
119
+ @app = GemInstaller::Application.new
120
+ @app.autogem = @autogem
121
+ @app.rogue_gem_finder = @rogue_gem_finder
122
+ @app.options = @options
123
+ @app.arg_parser = @arg_parser
124
+ @app.config_builder = @config_builder
125
+ @app.install_processor = @install_processor
126
+ @app.output_filter = @output_filter
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,57 @@
1
+ module GemInstaller
2
+ class EnhancedStreamUI < Gem::StreamUI
3
+ attr_writer :gem_interaction_handler, :outs, :errs
4
+
5
+ def initialize()
6
+ # override default constructor to have no args
7
+ end
8
+
9
+ def ask_yes_no(question, default=nil)
10
+ begin
11
+ @gem_interaction_handler.handle_ask_yes_no(question)
12
+ rescue Exception => e
13
+ @outs.print(question)
14
+ @outs.flush
15
+ raise e
16
+ end
17
+ raise_unexpected_prompt_error(question)
18
+ end
19
+
20
+ def ask(question)
21
+ raise_unexpected_prompt_error(question)
22
+ end
23
+
24
+ def choose_from_list(question, list)
25
+ @gem_interaction_handler.handle_choose_from_list(question, list)
26
+ end
27
+
28
+ def terminate_interaction!(status=-1)
29
+ raise_error(status)
30
+ end
31
+
32
+ def terminate_interaction(status=0)
33
+ raise_error(status) unless status == 0
34
+ raise GemInstaller::RubyGemsExit.new(status)
35
+ end
36
+
37
+ def alert_error(statement, question=nil)
38
+ # if alert_error got called due to a GemInstaller::UnexpectedPromptError, re-throw it
39
+ last_exception = $!
40
+ if last_exception.class == GemInstaller::UnauthorizedDependencyPromptError || last_exception.class == GemInstaller::RubyGemsExit
41
+ raise last_exception
42
+ end
43
+ # otherwise let alert_error continue normally...
44
+ super(statement, question)
45
+ end
46
+
47
+ protected
48
+ def raise_error(status)
49
+ raise GemInstaller::GemInstallerError.new("RubyGems exited abnormally. Status: #{status}\n")
50
+ end
51
+
52
+ def raise_unexpected_prompt_error(question)
53
+ raise GemInstaller::UnexpectedPromptError.new("GemInstaller Internal Error - Unexpected prompt received from RubyGems: '#{question}'.")
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,16 @@
1
+ module GemInstaller
2
+ class ExactMatchListCommand < Gem::ListCommand
3
+ def execute
4
+ string = get_one_optional_argument || ''
5
+ # This overrides the default RubyGems ListCommand behavior of doing a wildcard match. This caused problems
6
+ # when some gems (ActiveRecord-JDBC) caused exceptions during a remote list, causing a remote list
7
+ # of other gems (activerecord) to fail as well
8
+ options[:name] = /^#{string}$/i
9
+ # Do a little metaprogramming magic to avoid calling the problematic execute method on the ListCommand
10
+ # superclass, and instead directly call the method on the QueryCommand grandparent 'supersuperclass'
11
+ unbound_execute_method = Gem::QueryCommand.instance_method(:execute)
12
+ bound_execute_method = unbound_execute_method.bind(self)
13
+ bound_execute_method.call
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ module GemInstaller
2
+ class FileReader
3
+ def read(file_path)
4
+ file_contents = nil
5
+ if !File.exist?(file_path) then
6
+ raise GemInstaller::MissingFileError.new("#{file_path}")
7
+ end
8
+
9
+ file = nil
10
+ begin
11
+ file = do_open(file_path)
12
+ rescue
13
+ raise GemInstaller::GemInstallerError.new("Error: Unable open file #{file_path}. Please ensure that this file can be opened.\n")
14
+ end
15
+
16
+ begin
17
+ do_read(file)
18
+ rescue
19
+ raise GemInstaller::GemInstallerError.new("Error: Unable read file #{file_path}. Please ensure that this file can be read.\n")
20
+ end
21
+ end
22
+
23
+ def do_open(file_path)
24
+ File.open(file_path)
25
+ end
26
+
27
+ def do_read(file)
28
+ file.read
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+ module GemInstaller
2
+ class GemArgProcessor
3
+ #Common Options:
4
+ # --source URL Use URL as the remote source for gems
5
+ # -p, --[no-]http-proxy [URL] Use HTTP proxy for remote operations
6
+ # -h, --help Get help on this command
7
+ # -v, --verbose Set the verbose level of output
8
+ # --config-file FILE Use this config file instead of default
9
+ # --backtrace Show stack backtrace on errors
10
+ # --debug Turn on Ruby debugging
11
+ GEM_COMMON_OPTIONS_WITHOUT_ARG = ['--no-http-proxy','-v','--verbose','--backtrace','--debug']
12
+ GEM_COMMON_OPTIONS_WITH_ARG = ['--source','-p','--http_proxy','--config-file']
13
+
14
+ # take an array of args, and strip all args that are not common gem command args
15
+ def strip_non_common_gem_args(args)
16
+ # I can't figure out a way to elegantly do this, so I hardcoded the options. Here's how you print them
17
+ # Gem::Command.common_options.each do |option|
18
+ # p option[0]
19
+ # end
20
+
21
+ common_args = []
22
+ i = 0
23
+ loop do
24
+ break if i == args.size
25
+ arg = args[i]
26
+ if GEM_COMMON_OPTIONS_WITHOUT_ARG.include?(arg)
27
+ common_args << arg
28
+ else
29
+ GEM_COMMON_OPTIONS_WITH_ARG.each do |option|
30
+ if arg.include?(option)
31
+ common_args << arg
32
+ unless arg.include?('=')
33
+ i += 1
34
+ common_args << args[i]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ i += 1
40
+ end
41
+ common_args
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ module GemInstaller
2
+ class GemCommandLineProxy
3
+ GEM_ERROR_REGEXP = /^ERROR.*/
4
+ def run(args)
5
+ args_string = args.join(" ")
6
+ output = `gem #{args_string} 2>&1`
7
+ return_value = $?
8
+ lines = output.split("\n")
9
+ # return value is always zero on windows (from gem.bat), so we have to resort to parsing the output
10
+ error_in_output = false
11
+ lines.each do |line|
12
+ if line.match(GemInstaller::GemCommandLineProxy::GEM_ERROR_REGEXP)
13
+ error_in_output = true
14
+ break
15
+ end
16
+ end
17
+ if (return_value != 0 or error_in_output)
18
+ error_message = "Error: gem command failed. Command was 'gem #{args_string}', return value was '#{return_value}'. Output was:\n"
19
+ lines.each do |line|
20
+ error_message += ' ' + line + '\n'
21
+ end
22
+ raise GemInstaller::GemInstallerError.new(error_message)
23
+ end
24
+ return lines
25
+ end
26
+ end
27
+ end
28
+
29
+
30
+
31
+
32
+
@@ -0,0 +1,62 @@
1
+ module GemInstaller
2
+ class GemCommandManager
3
+ attr_writer :gem_spec_manager, :gem_runner_proxy, :gem_interaction_handler
4
+
5
+ def list_remote_gem(gem, additional_options)
6
+ run_args = ["list",gem.name,"--remote"]
7
+ run_args += additional_options
8
+ @gem_runner_proxy.run(run_args)
9
+ end
10
+
11
+ def uninstall_gem(gem)
12
+ return if !@gem_spec_manager.is_gem_installed?(gem)
13
+ @gem_interaction_handler.dependent_gem = gem
14
+ run_gem_command('uninstall',gem)
15
+ end
16
+
17
+ def install_gem(gem)
18
+ return if @gem_spec_manager.is_gem_installed?(gem)
19
+ @gem_interaction_handler.dependent_gem = gem
20
+ run_gem_command('install',gem)
21
+ end
22
+
23
+ def dependency(name, version, additional_options = [])
24
+ # it would be great to use the dependency --pipe option, but unfortunately, rubygems has a bug
25
+ # up to at least 0.9.2 where the pipe options uses 'puts', instead of 'say', so we can't capture it
26
+ # with enhanced_stream_ui. Patch submitted:
27
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=9020&group_id=126&atid=577
28
+ run_args = ["dependency",/^#{name}$/,"--version",version]
29
+ run_args += additional_options
30
+ output_lines = @gem_runner_proxy.run(run_args)
31
+ # dependency output has all lines in the first element
32
+ output_array = output_lines[0].split("\n")
33
+ # drop the first line which just echoes the dependent gem
34
+ output_array.shift
35
+ # drop the line containing 'requires' (rubygems < 0.9.0)
36
+ if output_array[0] == ' Requires'
37
+ output_array.shift
38
+ end
39
+ # drop all empty lines
40
+ output_array.reject! { |line| line == "" }
41
+ # strip leading space
42
+ output_array.each { |line| line.strip! }
43
+ # convert into gems
44
+ output_gems = output_array.collect do |line|
45
+ name = line.split(' ')[0]
46
+ version_spec = line.split(/[()]/)[1]
47
+ GemInstaller::RubyGem.new(name, :version => version_spec)
48
+ end
49
+ end
50
+
51
+ def run_gem_command(gem_command,gem)
52
+ run_args = [gem_command,gem.name,"--version", "#{gem.version}"]
53
+ run_args += gem.install_options
54
+ @gem_runner_proxy.run(run_args)
55
+ end
56
+ end
57
+ end
58
+
59
+
60
+
61
+
62
+
@@ -0,0 +1,30 @@
1
+ module GemInstaller
2
+ class GemInteractionHandler
3
+ attr_writer :dependent_gem, :noninteractive_chooser_class, :valid_platform_selector
4
+ DEPENDENCY_PROMPT = 'Install required dependency'
5
+
6
+ def handle_ask_yes_no(question)
7
+ return unless question.index(DEPENDENCY_PROMPT)
8
+ message = "Error: RubyGems is prompting to install a required dependency, and you have not " +
9
+ "specified the '--install-dependencies' option for the current gem. You must modify your " +
10
+ "geminstaller config file to either specify the '--install-depencencies' (-y) " +
11
+ "option, or explicitly add an entry for the dependency gem earlier in the file.\n"
12
+ raise GemInstaller::UnauthorizedDependencyPromptError.new(message)
13
+ end
14
+
15
+ def handle_choose_from_list(question, list, noninteractive_chooser = nil)
16
+ noninteractive_chooser ||= @noninteractive_chooser_class.new
17
+ valid_platforms = nil
18
+ if dependent_gem_with_platform_specified?(list, noninteractive_chooser) or noninteractive_chooser.uninstall_list_type?(question)
19
+ valid_platforms = [@dependent_gem.platform]
20
+ else
21
+ valid_platforms = @valid_platform_selector.select(@dependent_gem.platform)
22
+ end
23
+ noninteractive_chooser.choose(question, list, @dependent_gem.name, @dependent_gem.version, valid_platforms)
24
+ end
25
+
26
+ def dependent_gem_with_platform_specified?(list, noninteractive_chooser)
27
+ noninteractive_chooser.dependent_gem?(@dependent_gem.name, list) and @dependent_gem.platform
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,55 @@
1
+ module GemInstaller
2
+ class GemListChecker
3
+ attr_writer :gem_command_manager, :gem_arg_processor, :version_specifier
4
+
5
+ def find_remote_matching_gem(gem)
6
+ gem_list_match_regexp = /^#{gem.regexp_escaped_name} \(.*/
7
+ common_args = @gem_arg_processor.strip_non_common_gem_args(gem.install_options)
8
+ remote_list = @gem_command_manager.list_remote_gem(gem, common_args)
9
+
10
+ matched_lines = []
11
+ remote_list.each do |line|
12
+ if line.match(gem_list_match_regexp)
13
+ matched_lines << line
14
+ end
15
+ end
16
+
17
+ if matched_lines.size > 1
18
+ error_message = "Error: more than one remote gem matches (this should not happen and is probably a bug in geminstaller). Gem name = '#{gem.name}', install options = '#{gem.install_options}'. Matching remote gems: \n"
19
+ matched_lines.each do |line|
20
+ error_message += line + "\n"
21
+ end
22
+ raise GemInstaller::GemInstallerError.new(error_message)
23
+ end
24
+
25
+ if matched_lines.size == 0
26
+ error_message = "Error: Could not find remote gem to install. Gem name = '#{gem.name}', install options = '#{gem.install_options}'"
27
+ raise GemInstaller::GemInstallerError.new(error_message)
28
+ end
29
+
30
+ return matched_lines[0]
31
+ end
32
+
33
+ def verify_and_specify_remote_gem!(gem)
34
+ # TODO: this seems like it is a hack, but we must have a non-ambiguous version on the gem in order for
35
+ # noninteractive_chooser to be able to parse the gem list for multi-platform gems. This will not be necessary
36
+ # if a future RubyGems release allows specification/searching of the platform, because then we won't need noninteractive_chooser
37
+
38
+ version_list = available_versions(gem)
39
+ specified_version = @version_specifier.specify(gem.version, version_list, gem.name)
40
+ gem.version = specified_version
41
+ end
42
+
43
+ def available_versions(gem)
44
+ remote_match_line = find_remote_matching_gem(gem)
45
+ version_list = parse_out_version_list(remote_match_line)
46
+ end
47
+
48
+ def parse_out_version_list(line)
49
+ # return everything between first set of parenthesis
50
+ version_list = line.split(/[()]/)[1]
51
+ version_list
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,43 @@
1
+ module GemInstaller
2
+ class GemRunnerProxy
3
+ attr_writer :gem_runner_class, :gem_cmd_manager_class, :output_listener, :exact_match_list_command
4
+ attr_writer :options, :enhanced_stream_ui, :output_filter
5
+
6
+ def run(args = [], stdin = [])
7
+ @output_filter.geminstaller_output(:commandecho,"'gem #{args.join(' ')}'\n")
8
+ gem_runner = create_gem_runner
9
+ # We have to manually initialize the configuration here, or else the GemCommandManager singleton
10
+ # will initialize with the (incorrect) default args when we call GemRunner.run.
11
+ gem_runner.do_configuration(args)
12
+ gem_cmd_manager = @gem_cmd_manager_class.instance
13
+ gem_cmd_manager.ui = @enhanced_stream_ui
14
+ gem_cmd_manager.register_command @exact_match_list_command
15
+
16
+ exit_status = nil
17
+ begin
18
+ gem_runner.run(args)
19
+ rescue GemInstaller::RubyGemsExit => normal_exit
20
+ exit_status = normal_exit.message
21
+ rescue GemInstaller::GemInstallerError => exit_error
22
+ raise_error_with_output(exit_error, args, @output_listener)
23
+ end
24
+ output_lines = @output_listener.read!
25
+ output_lines.push(exit_status) if exit_status
26
+ return output_lines
27
+ end
28
+
29
+ def create_gem_runner
30
+ rubygems_version = Gem::RubyGemsVersion
31
+ if rubygems_version.index('0.8') == 0
32
+ @gem_runner_class.new()
33
+ else
34
+ @gem_runner_class.new(:command_manager => @gem_cmd_manager_class)
35
+ end
36
+ end
37
+
38
+ def raise_error_with_output(exit_error, args, listener)
39
+ descriptive_exit_message = exit_error.descriptive_exit_message(exit_error.message, 'gem', args, listener)
40
+ raise exit_error.class.new(descriptive_exit_message)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ module GemInstaller
2
+ class GemSourceIndexProxy
3
+ attr_writer :gem_source_index
4
+
5
+ def refresh!
6
+ @gem_source_index.refresh!
7
+ end
8
+
9
+ # NOTE: We will require an exact version requirement, rather than the standard default Gem version_requirement of ">= 0"
10
+ # GemInstaller has it's own default defined elsewhere
11
+ def search(gem_pattern, version_requirement)
12
+ # Returns an array of Gem::Specification objects
13
+ @gem_source_index.search(gem_pattern, version_requirement)
14
+ end
15
+ end
16
+ end
17
+
18
+
19
+
20
+
21
+