1require 'rubygems/command' 2require 'rubygems/remote_fetcher' 3require 'rubygems/spec_fetcher' 4require 'rubygems/local_remote_options' 5 6class Gem::Commands::SourcesCommand < Gem::Command 7 8 include Gem::LocalRemoteOptions 9 10 def initialize 11 require 'fileutils' 12 13 super 'sources', 14 'Manage the sources and cache file RubyGems uses to search for gems' 15 16 add_option '-a', '--add SOURCE_URI', 'Add source' do |value, options| 17 options[:add] = value 18 end 19 20 add_option '-l', '--list', 'List sources' do |value, options| 21 options[:list] = value 22 end 23 24 add_option '-r', '--remove SOURCE_URI', 'Remove source' do |value, options| 25 options[:remove] = value 26 end 27 28 add_option '-c', '--clear-all', 29 'Remove all sources (clear the cache)' do |value, options| 30 options[:clear_all] = value 31 end 32 33 add_option '-u', '--update', 'Update source cache' do |value, options| 34 options[:update] = value 35 end 36 37 add_proxy_option 38 end 39 40 def defaults_str 41 '--list' 42 end 43 44 def execute 45 options[:list] = !(options[:add] || 46 options[:clear_all] || 47 options[:remove] || 48 options[:update]) 49 50 if options[:clear_all] then 51 path = File.join Gem.user_home, '.gem', 'specs' 52 FileUtils.rm_rf path 53 54 unless File.exist? path then 55 say "*** Removed specs cache ***" 56 else 57 unless File.writable? path then 58 say "*** Unable to remove source cache (write protected) ***" 59 else 60 say "*** Unable to remove source cache ***" 61 end 62 63 terminate_interaction 1 64 end 65 end 66 67 if source_uri = options[:add] then 68 uri = URI source_uri 69 70 if uri.scheme and uri.scheme.downcase == 'http' and 71 uri.host.downcase == 'rubygems.org' then 72 question = <<-QUESTION.chomp 73https://rubygems.org is recommended for security over #{uri} 74 75Do you want to add this insecure source? 76 QUESTION 77 78 terminate_interaction 1 unless ask_yes_no question 79 end 80 81 source = Gem::Source.new source_uri 82 83 begin 84 if Gem.sources.include? source_uri then 85 say "source #{source_uri} already present in the cache" 86 else 87 source.load_specs :released 88 Gem.sources << source 89 Gem.configuration.write 90 91 say "#{source_uri} added to sources" 92 end 93 rescue URI::Error, ArgumentError 94 say "#{source_uri} is not a URI" 95 terminate_interaction 1 96 rescue Gem::RemoteFetcher::FetchError => e 97 say "Error fetching #{source_uri}:\n\t#{e.message}" 98 terminate_interaction 1 99 end 100 end 101 102 if options[:remove] then 103 source_uri = options[:remove] 104 105 unless Gem.sources.include? source_uri then 106 say "source #{source_uri} not present in cache" 107 else 108 Gem.sources.delete source_uri 109 Gem.configuration.write 110 111 say "#{source_uri} removed from sources" 112 end 113 end 114 115 if options[:update] then 116 Gem.sources.each_source do |src| 117 src.load_specs :released 118 src.load_specs :latest 119 end 120 121 say "source cache successfully updated" 122 end 123 124 if options[:list] then 125 say "*** CURRENT SOURCES ***" 126 say 127 128 Gem.sources.each do |src| 129 say src 130 end 131 end 132 end 133 134 private 135 136 def remove_cache_file(desc, path) 137 FileUtils.rm_rf path 138 139 if not File.exist?(path) then 140 say "*** Removed #{desc} source cache ***" 141 elsif not File.writable?(path) then 142 say "*** Unable to remove #{desc} source cache (write protected) ***" 143 else 144 say "*** Unable to remove #{desc} source cache ***" 145 end 146 end 147 148end 149 150