jwhitmire-geminstaller 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/COPYING +1 -0
  2. data/History.txt +82 -0
  3. data/LICENSE +21 -0
  4. data/Manifest.txt +78 -0
  5. data/README.txt +77 -0
  6. data/Rakefile +210 -0
  7. data/TODO.txt +138 -0
  8. data/authors +2 -0
  9. data/bin/geminstaller +30 -0
  10. data/cruise_config.rb +23 -0
  11. data/focused_spec.sh +2 -0
  12. data/focused_spec_debug.sh +2 -0
  13. data/geminstaller.yml +47 -0
  14. data/lib/geminstaller/application.rb +112 -0
  15. data/lib/geminstaller/arg_parser.rb +177 -0
  16. data/lib/geminstaller/autogem.rb +48 -0
  17. data/lib/geminstaller/backward_compatibility.rb +17 -0
  18. data/lib/geminstaller/bundler_exporter.rb +19 -0
  19. data/lib/geminstaller/config.rb +68 -0
  20. data/lib/geminstaller/config_builder.rb +65 -0
  21. data/lib/geminstaller/enhanced_stream_ui.rb +71 -0
  22. data/lib/geminstaller/exact_match_list_command.rb +16 -0
  23. data/lib/geminstaller/file_reader.rb +31 -0
  24. data/lib/geminstaller/gem_arg_processor.rb +44 -0
  25. data/lib/geminstaller/gem_command_manager.rb +71 -0
  26. data/lib/geminstaller/gem_interaction_handler.rb +41 -0
  27. data/lib/geminstaller/gem_list_checker.rb +55 -0
  28. data/lib/geminstaller/gem_runner_proxy.rb +65 -0
  29. data/lib/geminstaller/gem_source_index_proxy.rb +21 -0
  30. data/lib/geminstaller/gem_spec_manager.rb +53 -0
  31. data/lib/geminstaller/geminstaller_access_error.rb +4 -0
  32. data/lib/geminstaller/geminstaller_error.rb +13 -0
  33. data/lib/geminstaller/hoe_extensions.rb +9 -0
  34. data/lib/geminstaller/install_processor.rb +71 -0
  35. data/lib/geminstaller/missing_dependency_finder.rb +46 -0
  36. data/lib/geminstaller/missing_file_error.rb +4 -0
  37. data/lib/geminstaller/noninteractive_chooser.rb +114 -0
  38. data/lib/geminstaller/outdated_gem_finder.rb +46 -0
  39. data/lib/geminstaller/output_filter.rb +49 -0
  40. data/lib/geminstaller/output_listener.rb +33 -0
  41. data/lib/geminstaller/output_observer.rb +36 -0
  42. data/lib/geminstaller/output_proxy.rb +36 -0
  43. data/lib/geminstaller/registry.rb +137 -0
  44. data/lib/geminstaller/requires.rb +83 -0
  45. data/lib/geminstaller/rogue_gem_finder.rb +195 -0
  46. data/lib/geminstaller/ruby_gem.rb +58 -0
  47. data/lib/geminstaller/rubygems_exit.rb +5 -0
  48. data/lib/geminstaller/rubygems_extensions.rb +9 -0
  49. data/lib/geminstaller/rubygems_version_checker.rb +21 -0
  50. data/lib/geminstaller/rubygems_version_warnings.rb +38 -0
  51. data/lib/geminstaller/source_index_search_adapter.rb +41 -0
  52. data/lib/geminstaller/unauthorized_dependency_prompt_error.rb +4 -0
  53. data/lib/geminstaller/unexpected_prompt_error.rb +4 -0
  54. data/lib/geminstaller/valid_platform_selector.rb +49 -0
  55. data/lib/geminstaller/version_specifier.rb +24 -0
  56. data/lib/geminstaller/yaml_loader.rb +22 -0
  57. data/lib/geminstaller.rb +103 -0
  58. data/lib/geminstaller_rails_preinitializer.rb +54 -0
  59. data/start_local_gem_server.sh +1 -0
  60. data/website/config.yaml +11 -0
  61. data/website/src/analytics.page +6 -0
  62. data/website/src/code/ci.virtual +5 -0
  63. data/website/src/code/coverage/index.virtual +5 -0
  64. data/website/src/code/index.page +92 -0
  65. data/website/src/code/rdoc/index.virtual +6 -0
  66. data/website/src/community/index.page +14 -0
  67. data/website/src/community/links.page +11 -0
  68. data/website/src/community/rubyforge.virtual +4 -0
  69. data/website/src/default.css +175 -0
  70. data/website/src/default.template +42 -0
  71. data/website/src/documentation/documentation.page +477 -0
  72. data/website/src/documentation/index.page +53 -0
  73. data/website/src/documentation/tutorials.page +337 -0
  74. data/website/src/download.page +12 -0
  75. data/website/src/faq.page +36 -0
  76. data/website/src/index.page +103 -0
  77. data/website/src/metainfo +54 -0
  78. data/website/src/webgen.css +112 -0
  79. metadata +139 -0
data/cruise_config.rb ADDED
@@ -0,0 +1,23 @@
1
+ # Project-specific configuration for CruiseControl.rb
2
+ require 'fileutils'
3
+ require 'socket'
4
+
5
+ Project.configure do |project|
6
+ triggers = []
7
+ if File.exists?(File.expand_path(File.dirname(project.path)) + '/../../RubyGems')
8
+ triggers << :RubyGems
9
+ end
10
+ if File.exists?(File.expand_path(File.dirname(project.path)) + '/../../dummyrepo')
11
+ triggers << :dummyrepo
12
+ end
13
+ project.triggered_by *triggers
14
+ project.email_notifier.emails = ['thewoolleyman@gmail.com'] if Socket.gethostname =~ /(thewoolleyweb.com|ci.pivotallabs.com)/
15
+ if project.name =~ /rubygems[_-](.*)$/ # geminstaller_using_rubygems_0-9-4
16
+ rubygems_version = $1
17
+ rubygems_version.gsub!('-','.')
18
+ ENV['RUBYGEMS_VERSION'] = rubygems_version
19
+ end
20
+ if project.name =~ /smoketest/i # smoketest project
21
+ project.rake_task = project.name
22
+ end
23
+ end
data/focused_spec.sh ADDED
@@ -0,0 +1,2 @@
1
+ # warning - experimental
2
+ ruby -I spec/fixture/rubygems_dist/rubygems-1.0.1/lib/ /usr/local/bin/spec $1 --line=$2
@@ -0,0 +1,2 @@
1
+ # warning - experimental
2
+ ruby -I spec/lib/ruby-debug-0.10.0/cli:spec/lib/ruby-debug-0.10.0/bin:spec/lib/ruby-debug-base-0.10.0/lib:spec/lib/ruby-debug-0.10.0/bin/rdebug:spec/lib/rspec-1.1.1/lib spec/lib/ruby-debug-0.10.0/bin/rdebug spec/lib/rspec-1.1.1/bin/spec -- $1 --line=$2
data/geminstaller.yml ADDED
@@ -0,0 +1,47 @@
1
+ ---
2
+ # GemInstaller config file which specifies the actual build, test, and doc dependencies for GemInstaller itself.
3
+ defaults:
4
+ install_options: --no-ri --no-rdoc
5
+ #fix_dependencies: true
6
+ gems:
7
+ - name: diff-lcs
8
+ version: '>= 1.1.2'
9
+ - name: hoe
10
+ version: '>= 2.3.2'
11
+ - name: hoe-seattlerb
12
+ version: '>= 1.2.0'
13
+ - name: open4
14
+ version: '>= 0.9.6'
15
+ - name: rake
16
+ version: '>= 0.7.1'
17
+ - name: rcov
18
+ version: '>= 0.7.0.1'
19
+ platform: <%= RUBY_PLATFORM =~ /mswin/ ? 'mswin32' : 'ruby'%>
20
+ - name: RedCloth
21
+ # version: '= 3.0.4'
22
+ version: '= 4.0.4'
23
+ - name: rspec
24
+ version: '>= 1.2.8'
25
+ # install dev dependencies for rspec, or else regression tests on older versions of rubygems with the dev dependencies
26
+ # bug (1.0, 1.1) fail - and currently Hoe swallows Rspec load error silently
27
+ install_options: --no-ri --no-rdoc --development
28
+ - name: cmdparse
29
+ version: '>= 2.0.2'
30
+ - name: ruby-debug
31
+ version: '>= 0.9.3'
32
+ - name: webgen
33
+ version: '= 0.5.5'
34
+ # - name: gettalong-webgen
35
+ # version: '>= 0.5.5.20081001'
36
+ <% if RUBY_PLATFORM =~ /mswin/ %>
37
+ - name: win32-process
38
+ version: '>= 0.5.5'
39
+ platform: 'mswin32'
40
+ - name: win32console
41
+ version: '>= 1.0.8'
42
+ platform: 'mswin32'
43
+ - name: win32-open3
44
+ version: '>= 0.2.5'
45
+ platform: 'mswin32'
46
+ <% end %>
47
+
@@ -0,0 +1,112 @@
1
+ module GemInstaller
2
+ class Application
3
+ # we have accessors instead of just writers so that we can ensure it is assembled correctly in the dependency injector test
4
+ attr_accessor :config_builder, :install_processor, :output_filter, :arg_parser, :args, :options, :rogue_gem_finder, :bundler_exporter, :outdated_gem_finder
5
+ attr_writer :autogem
6
+
7
+ def initialize
8
+ @args = nil
9
+ end
10
+
11
+ def install
12
+ begin
13
+ exit_flag_and_return_code = handle_args
14
+ if exit_flag_and_return_code[0]
15
+ return exit_flag_and_return_code[1]
16
+ end
17
+ if @options[:bundler_export]
18
+ @bundler_exporter.output(@config_builder.build_config)
19
+ return 0
20
+ end
21
+ gems = create_gems_from_config
22
+ if @options[:print_rogue_gems]
23
+ @rogue_gem_finder.print_rogue_gems(gems, @config_builder.config_file_paths_array)
24
+ return 0
25
+ elsif @options[:print_outdated_gems]
26
+ @outdated_gem_finder.print_outdated_gems(gems, @config_builder.config_file_paths_array)
27
+ return 0
28
+ end
29
+ if gems.size == 0
30
+ message = "No gems found in config file. Try the --print-rogue-gems option to help populate your config file."
31
+ @output_filter.geminstaller_output(:info,message + "\n")
32
+ else
33
+ process_gems(gems)
34
+ end
35
+ rescue Exception => e
36
+ handle_exception(e)
37
+ return 1
38
+ end
39
+ return 0
40
+ end
41
+
42
+ def autogem
43
+ begin
44
+ # TODO: do some validation that args only contains --config option, especially not print_rogue_gems since this would mask a missing file error
45
+ exit_flag_and_return_code = handle_args
46
+ if exit_flag_and_return_code[0]
47
+ return exit_flag_and_return_code[1]
48
+ end
49
+ gems = create_gems_from_config
50
+ message = "GemInstaller is automatically requiring gems: "
51
+ print_startup_message(gems, message)
52
+ return @autogem.autogem(gems)
53
+ rescue Exception => e
54
+ handle_exception(e)
55
+ return 1
56
+ end
57
+ end
58
+
59
+ def handle_exception(e)
60
+ message = e.message
61
+ message += "\n"
62
+ @output_filter.geminstaller_output(:error,message)
63
+ backtrace_as_string = e.backtrace.join("\n")
64
+ @output_filter.geminstaller_output(:debug,"#{backtrace_as_string}\n")
65
+ raise e if @options[:exceptions]
66
+ end
67
+
68
+ def create_gems_from_config
69
+ begin
70
+ config = @config_builder.build_config
71
+ rescue GemInstaller::MissingFileError => e
72
+ # if user wants to print rogue gems and they have no config at all, don't show an error
73
+ return [] if @options[:print_rogue_gems] && (@config_builder.config_file_paths_array.size == 1)
74
+ missing_path = e.message
75
+ error_message = "Error: A GemInstaller config file is missing at #{missing_path}. You can generate one with the --print-rogue-gems option. See the GemInstaller docs at http://geminstaller.rubyforge.org for more info."
76
+ raise GemInstaller::MissingFileError.new(error_message)
77
+ end
78
+ config.gems
79
+ end
80
+
81
+ def process_gems(gems)
82
+ message = "GemInstaller is verifying gem installation: "
83
+ print_startup_message(gems, message)
84
+ @install_processor.process(gems)
85
+ end
86
+
87
+ def handle_args
88
+ return_code = @arg_parser.parse(@args)
89
+ arg_parser_output = @arg_parser.output
90
+ if (arg_parser_output && arg_parser_output != '')
91
+ if return_code == 0
92
+ @output_filter.geminstaller_output(:info,arg_parser_output)
93
+ else
94
+ @output_filter.geminstaller_output(:error,arg_parser_output)
95
+ end
96
+ return [true, return_code]
97
+ end
98
+ config_file_paths = @options[:config_paths]
99
+ @config_builder.config_file_paths = config_file_paths if config_file_paths
100
+ return [false, 0]
101
+ end
102
+
103
+ def print_startup_message(gems, message)
104
+ gems.each_with_index do |gem, index|
105
+ gem_info = "#{gem.name} #{gem.version}"
106
+ message += gem_info
107
+ message += ", " if index + 1 < gems.size
108
+ end
109
+ @output_filter.geminstaller_output(:debug,message + "\n")
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,177 @@
1
+ module GemInstaller
2
+ class ArgParser
3
+ attr_reader :output
4
+ attr_writer :options
5
+
6
+ VALID_GEMINSTALLER_OUTPUT_FLAGS = [:none,:error,:install,:info,:commandecho,:debug,:all]
7
+ VALID_RUBYGEMS_OUTPUT_FLAGS = [:none,:stdout,:stderr,:all]
8
+
9
+ def parse(args = [])
10
+ raise GemInstaller::GemInstallerError.new("Args must be passed as an array.") unless args.nil? or args.respond_to? :shift
11
+ args = ARGV if args.nil? || args == []
12
+ # check to see if args is an array of (nothing but) gems here... if so, set args as [@options[:gems] and return
13
+
14
+ raise GemInstaller::GemInstallerError.new("Error: An array of options to be populated must be injected prior to calling GemInstaller::ArgParser.parse") unless @options
15
+ @options[:exceptions] = false
16
+ @options[:redirect_stderr_to_stdout] = false
17
+ @options[:silent] = false
18
+ @options[:sudo] = false
19
+ @options[:geminstaller_output] = [:error,:install,:info]
20
+ @options[:rubygems_output] = [:stderr]
21
+ @output = ""
22
+ @unparsed_geminstaller_output_flags = nil
23
+ @unparsed_rubygems_output_flags = nil
24
+ opts = OptionParser.new do |opts|
25
+ opts.banner = "Usage: geminstaller [options]"
26
+
27
+ opts.separator ""
28
+
29
+ config_msg = "Comma-delimited path(s) to GemInstaller config file(s)."
30
+ exceptions_msg = "Raise any exceptions, rather than just printing them and exiting\n" +
31
+ " with a non-zero return code."
32
+ redirect_stderr_to_stdout_msg = "Redirect all STDERR output to STDOUT. Useful to get all output when\n" +
33
+ " invoking GemInstaller via system()."
34
+ geminstaller_output_msg = "Comma-delimited list of output types to show from GemInstaller.\n" +
35
+ " Examples:\n" +
36
+ " --gall\n" +
37
+ " --geminstaller-output=error,install,commandecho\n" +
38
+ " Default: error,install,info\n" +
39
+ " Valid types:\n" +
40
+ " - none: print only fatal errors\n" +
41
+ " - error: print error messages\n" +
42
+ " - install: print install messages\n" +
43
+ " - info: print informational messages\n" +
44
+ " - commandecho: print rubygems commands as they are invoked\n" +
45
+ " - debug: print debug messages\n" +
46
+ " - all: print all messages"
47
+ help_msg = "Show this message."
48
+ print_outdated_gems_msg = "Print a report of all locally installed gems which have a later\n" +
49
+ " version installed than is specified in the geminstaller config file."
50
+ print_rogue_gems_msg = "Print a report of all locally installed gems which are not specified\n" +
51
+ " in the geminstaller config file."
52
+ bundler_export_msg = "Export a Bundler manifest Gemfile based on the geminstaller config"
53
+ rubygems_output_msg = "Comma-delimited list of output types to show from internal:\n" +
54
+ " RubyGems command invocation.\n" +
55
+ " Examples:\n" +
56
+ " --rall\n" +
57
+ " --rubygems-output=stderr\n" +
58
+ " Default: stderr\n" +
59
+ " Valid types:\n" +
60
+ " - none: print no output\n" +
61
+ " - stdout: print standard output stream\n" +
62
+ " - stderr: print standard error stream\n" +
63
+ " - all: print all output"
64
+ sudo_msg = "Perform all gem operations under sudo (as root). Will only work on\n" +
65
+ " correctly configured, supported systems. See docs for more info."
66
+ silent_msg = "Suppress all output except fatal exceptions, and output from\n" +
67
+ " rogue-gems and outdated-gems options."
68
+ version_msg = "Show GemInstaller version and exit."
69
+
70
+ opts.on("-cCONFIGPATHS", "--config=CONFIGPATHS", String, config_msg) do |config_paths|
71
+ @options[:config_paths] = config_paths
72
+ end
73
+
74
+ opts.on("-e", "--exceptions", exceptions_msg) do
75
+ @options[:exceptions] = true
76
+ end
77
+
78
+ opts.on("-d", "--redirect-stderr-to-stdout", redirect_stderr_to_stdout_msg) do
79
+ @options[:redirect_stderr_to_stdout] = true
80
+ end
81
+
82
+ opts.on("-gTYPES", "--geminstaller-output=TYPES", String, geminstaller_output_msg) do |geminstaller_output_flags|
83
+ @unparsed_geminstaller_output_flags = geminstaller_output_flags
84
+ end
85
+
86
+ opts.on("-h", "--help", help_msg) do
87
+ @output = opts.to_s
88
+ end
89
+
90
+ opts.on("-o", "--print-outdated-gems", print_outdated_gems_msg) do
91
+ @options[:print_outdated_gems] = true
92
+ end
93
+
94
+ opts.on("-p", "--print-rogue-gems", print_rogue_gems_msg) do
95
+ @options[:print_rogue_gems] = true
96
+ end
97
+
98
+ opts.on("-b", "--bundler-export", bundler_export_msg) do
99
+ @options[:bundler_export] = true
100
+ end
101
+
102
+ opts.on("-rTYPES", "--rubygems-output=TYPES", String, rubygems_output_msg) do |rubygems_output_flags|
103
+ @unparsed_rubygems_output_flags = rubygems_output_flags
104
+ end
105
+
106
+ opts.on("-s", "--sudo", sudo_msg) do
107
+ @options[:sudo] = true
108
+ end
109
+
110
+ opts.on("-t", "--silent", silent_msg) do
111
+ @options[:silent] = true
112
+ end
113
+
114
+ opts.on("-v", "--version", version_msg) do
115
+ @output = "#{GemInstaller::version}\n"
116
+ end
117
+ end
118
+
119
+ begin
120
+ opts.parse!(args)
121
+ rescue(OptionParser::InvalidOption)
122
+ @output << opts.to_s
123
+ return 1
124
+ end
125
+
126
+ if @options[:silent] and (@unparsed_geminstaller_output_flags or @unparsed_rubygems_output_flags)
127
+ @output = "The rubygems-output or geminstaller-output option cannot be specified if the silent option is true."
128
+ return 1
129
+ end
130
+
131
+ if (@options[:sudo])
132
+ @output = "The sudo option is not (yet) supported when invoking GemInstaller programatically. It is only supported when using the command line 'geminstaller' executable. See the docs for more info."
133
+ return 1
134
+ end
135
+
136
+ # TODO: remove duplication
137
+ if @unparsed_geminstaller_output_flags
138
+ flags = @unparsed_geminstaller_output_flags.split(',')
139
+ flags.delete_if {|flag| flag == nil or flag == ''}
140
+ flags.map! {|flag| flag.downcase}
141
+ flags.sort!
142
+ flags.uniq!
143
+ flags.map! {|flag| flag.to_sym}
144
+ geminstaller_output_valid = true
145
+ flags.each do |flag|
146
+ unless VALID_GEMINSTALLER_OUTPUT_FLAGS.include?(flag)
147
+ @output = "Invalid geminstaller-output flag: #{flag}\n"
148
+ geminstaller_output_valid = false
149
+ end
150
+ end
151
+ @options[:geminstaller_output] = flags if geminstaller_output_valid
152
+ end
153
+
154
+ if @unparsed_rubygems_output_flags
155
+ flags = @unparsed_rubygems_output_flags.split(',')
156
+ flags.delete_if {|flag| flag == nil or flag == ''}
157
+ flags.map! {|flag| flag.downcase}
158
+ flags.sort!
159
+ flags.uniq!
160
+ flags.map! {|flag| flag.to_sym}
161
+ rubygems_output_valid = true
162
+ flags.each do |flag|
163
+ unless VALID_RUBYGEMS_OUTPUT_FLAGS.include?(flag)
164
+ @output = "Invalid rubygems-output flag: #{flag}\n"
165
+ rubygems_output_valid = false
166
+ end
167
+ end
168
+ @options[:rubygems_output] = flags if rubygems_output_valid
169
+ end
170
+
171
+ # nil out @output if there was no output
172
+ @output = nil if @output == ""
173
+ return 0
174
+
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,48 @@
1
+ module GemInstaller
2
+ class Autogem
3
+ attr_writer :gem_command_manager, :gem_source_index_proxy
4
+ def autogem(gems)
5
+ @gem_source_index_proxy.refresh!
6
+ # REALLY refresh - refreshing the source_index directly isn't enough.
7
+ Gem.refresh
8
+ @completed_names = []
9
+ @completed_gems = []
10
+ gems.each do |gem|
11
+ process_gem(gem)
12
+ end
13
+ @completed_gems
14
+ end
15
+
16
+ def process_gem(gem)
17
+ name = gem.name
18
+ version = gem.version
19
+ unless @completed_names.index(name) or gem.no_autogem
20
+ begin
21
+ invoke_require_gem_command(name, version)
22
+ rescue Gem::LoadError => load_error
23
+ load_error_message = load_error.message
24
+ load_error_message.strip!
25
+ error_message = "Error: GemInstaller attempted to load gem '#{name}', version '#{version}', but that version is not installed. Use GemInstaller to install the gem. Original Gem::LoadError was: '#{load_error_message}'"
26
+ raise GemInstaller::GemInstallerError.new(error_message)
27
+ end
28
+ @completed_names << name
29
+ @completed_gems << gem
30
+ end
31
+ end
32
+
33
+ def invoke_require_gem_command(name, version)
34
+ if GemInstaller::RubyGemsVersionChecker.matches?('< 0.9')
35
+ require_gem(name, version)
36
+ else
37
+ begin
38
+ result = gem(name, version)
39
+ rescue Gem::Exception => e
40
+ exception_message = e.message
41
+ exception_message.strip!
42
+ error_message = "Error: GemInstaller failed to activate gem '#{name}', version '#{version}'. This may be because GemInstaller processes gems in order (was alphabetical prior to 0.5.0), and an earlier gem in your geminstaller.yml config already activated another version. Use the 'gem dependency [-R]' command to track this down, and reorder/edit your config as necessary. Original Gem::Exception was: '#{exception_message}'"
43
+ raise GemInstaller::GemInstallerError.new(error_message)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # this file supports backward compatibility for prior versions of RubyGems
2
+
3
+ # 0.9.3 reorganized commands to Gem::Commands:: module from Gem::
4
+ if GemInstaller::RubyGemsVersionChecker.matches?('<0.9.3')
5
+ LIST_COMMAND_CLASS = Gem::ListCommand
6
+ QUERY_COMMAND_CLASS = Gem::QueryCommand
7
+ else
8
+ LIST_COMMAND_CLASS = Gem::Commands::ListCommand
9
+ QUERY_COMMAND_CLASS = Gem::Commands::QueryCommand
10
+ end
11
+
12
+ # >1.3.5 changed Gem::Version::Requirement to Gem::Requirement
13
+ if GemInstaller::RubyGemsVersionChecker.matches?('>1.3.5')
14
+ GemInstaller::REQUIREMENT_CLASS = Gem::Requirement
15
+ else
16
+ GemInstaller::REQUIREMENT_CLASS = Gem::Version::Requirement
17
+ end
@@ -0,0 +1,19 @@
1
+ module GemInstaller
2
+ class BundlerExporter
3
+ attr_writer :output_proxy
4
+
5
+ def output(config)
6
+ output_string = convert(config)
7
+ @output_proxy.sysout output_string
8
+ output_string
9
+ end
10
+
11
+ def convert(config)
12
+ manifest = ""
13
+ config.gems.each do |gem|
14
+ manifest += %Q{gem "#{gem.name}", "#{gem.version}"\n}
15
+ end
16
+ manifest
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,68 @@
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
+ return gems
55
+ end
56
+
57
+ protected
58
+
59
+ def parse_defaults
60
+ defaults = @yaml["defaults"]
61
+ return if defaults.nil?
62
+ @default_install_options_string = defaults['install_options']
63
+ @default_check_for_upgrade = defaults['check_for_upgrade']
64
+ @default_fix_dependencies = defaults['fix_dependencies']
65
+ @default_no_autogem = defaults['no_autogem']
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,65 @@
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, :yaml_loader, :config_file_paths, :output_filter
8
+
9
+ def initialize(default_config_file_paths_array = ['geminstaller.yml','config/geminstaller.yml','ci/geminstaller.yml'])
10
+ @default_config_file_paths_array = default_config_file_paths_array
11
+ end
12
+
13
+ def build_config
14
+ @config_file_paths_array = @config_file_paths ? @config_file_paths.split(",") : @default_config_file_paths_array
15
+ merged_defaults = {}
16
+ merged_gems_in_order = []
17
+ merged_gems_by_key = {}
18
+ file_found = false
19
+ @config_file_paths_array.reverse.each do |path| # reverse because last config files win
20
+ if File.exists?(path)
21
+ file_found = true
22
+ else
23
+ next
24
+ end
25
+ file_contents = @file_reader.read(path)
26
+ next unless file_contents
27
+ next if file_contents.empty?
28
+ expanded_path = File.expand_path(path)
29
+ @output_filter.geminstaller_output(:debug,"Found GemInstaller config file at: #{expanded_path}\n")
30
+ erb = ERB.new(%{#{file_contents}})
31
+ erb_result = nil
32
+ Dir.chdir(File.dirname(expanded_path)) do |yaml_file_dir|
33
+ erb_result = erb.result(include_config_binding)
34
+ end
35
+ yaml = @yaml_loader.load(erb_result)
36
+ merged_defaults.merge!(yaml['defaults']) unless yaml['defaults'].nil?
37
+ next unless yaml['gems']
38
+ yaml['gems'].each do |new_gem|
39
+ gem_key = [new_gem['name'],new_gem['version'],new_gem['platform']].join('-')
40
+ existing_gem = merged_gems_by_key[gem_key]
41
+ unless existing_gem
42
+ merged_gems_in_order << new_gem
43
+ merged_gems_by_key[gem_key] = new_gem
44
+ end
45
+ end
46
+ end
47
+ raise GemInstaller::MissingFileError.new("No config files found at any of these paths: #{@config_file_paths_array.join(', ')}") unless file_found
48
+ merged_yaml = {}
49
+ merged_yaml['defaults'] = merged_defaults
50
+ merged_yaml['gems'] = merged_gems_in_order
51
+ config = GemInstaller::Config.new(merged_yaml)
52
+ config
53
+ end
54
+
55
+ def include_config_binding
56
+ def include_config(config_file)
57
+ Dir.chdir(File.dirname(config_file)) do |yaml_file_dir|
58
+ erb = File.open(config_file) { |io| ERB.new(io.read) }
59
+ erb.result(include_config_binding)
60
+ end
61
+ end
62
+ binding
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,71 @@
1
+ module GemInstaller
2
+ class EnhancedStreamUI < Gem::StreamUI
3
+ attr_writer :outs, :errs
4
+ attr_writer :gem_interaction_handler if GemInstaller::RubyGemsVersionChecker.matches?('<=0.9.4')
5
+
6
+ def initialize()
7
+ # override default constructor to have no args
8
+ end
9
+
10
+ def ask_yes_no(question, default=nil)
11
+ if GemInstaller::RubyGemsVersionChecker.matches?('<=0.9.4')
12
+ # Using defaults, we expect no interactive prompts RubyGems >= 0.9.5
13
+ begin
14
+ @gem_interaction_handler.handle_ask_yes_no(question)
15
+ rescue Exception => e
16
+ @outs.print(question)
17
+ @outs.flush
18
+ raise e
19
+ end
20
+ end
21
+ raise_unexpected_prompt_error(question)
22
+ end
23
+
24
+ def ask(question)
25
+ raise_unexpected_prompt_error(question)
26
+ end
27
+
28
+ def choose_from_list(question, list)
29
+ if GemInstaller::RubyGemsVersionChecker.matches?('<=0.9.4')
30
+ # Using defaults, we expect no interactive prompts RubyGems >= 0.9.5
31
+ @gem_interaction_handler.handle_choose_from_list(question, list)
32
+ else
33
+ list_string = list.join("\n")
34
+ question_and_list = "#{question}\n#{list_string}"
35
+ raise_unexpected_prompt_error(question_and_list)
36
+ end
37
+ end
38
+
39
+ if GemInstaller::RubyGemsVersionChecker.matches?('<=1.0.1')
40
+ # explicit exit in terminate_interation was removed after 1.0.1
41
+ def terminate_interaction!(status=-1)
42
+ raise_error(status)
43
+ end
44
+
45
+ def terminate_interaction(status=0)
46
+ raise_error(status) unless status == 0
47
+ raise GemInstaller::RubyGemsExit.new(status)
48
+ end
49
+ end
50
+
51
+ def alert_error(statement, question=nil)
52
+ # if alert_error got called due to a GemInstaller::UnexpectedPromptError, re-throw it
53
+ last_exception = $!
54
+ if last_exception.class == GemInstaller::UnauthorizedDependencyPromptError || last_exception.class == GemInstaller::RubyGemsExit
55
+ raise last_exception
56
+ end
57
+ # otherwise let alert_error continue normally...
58
+ super(statement, question)
59
+ end
60
+
61
+ protected
62
+ def raise_error(status)
63
+ raise GemInstaller::GemInstallerError.new("RubyGems exited abnormally. Status: #{status}\n")
64
+ end
65
+
66
+ def raise_unexpected_prompt_error(question)
67
+ raise GemInstaller::UnexpectedPromptError.new("GemInstaller Internal Error - Unexpected prompt received from RubyGems: '#{question}'.")
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,16 @@
1
+ module GemInstaller
2
+ class ExactMatchListCommand < LIST_COMMAND_CLASS
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}$/
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 = QUERY_COMMAND_CLASS.instance_method(:execute)
12
+ bound_execute_method = unbound_execute_method.bind(self)
13
+ bound_execute_method.call
14
+ end
15
+ end
16
+ end