rubygems-update 0.8.6 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (42) hide show
  1. data/ChangeLog +134 -0
  2. data/Rakefile +41 -17
  3. data/bin/gemwhich +61 -0
  4. data/examples/application/an-app.gemspec +1 -0
  5. data/lib/gemconfigure.rb +18 -0
  6. data/lib/rubygems.rb +65 -47
  7. data/lib/rubygems/cmd_manager.rb +3 -1
  8. data/lib/rubygems/command.rb +4 -0
  9. data/lib/rubygems/config_file.rb +2 -6
  10. data/lib/rubygems/custom_require.rb +2 -2
  11. data/lib/rubygems/dependency_list.rb +131 -0
  12. data/lib/rubygems/deployment.rb +265 -0
  13. data/lib/rubygems/doc_manager.rb +1 -0
  14. data/lib/rubygems/gem_commands.rb +216 -15
  15. data/lib/rubygems/installer.rb +111 -286
  16. data/lib/rubygems/remote_installer.rb +16 -6
  17. data/lib/rubygems/rubygems_version.rb +1 -1
  18. data/lib/rubygems/source_index.rb +11 -5
  19. data/lib/rubygems/specification.rb +5 -0
  20. data/lib/rubygems/version.rb +146 -129
  21. data/test/test_configfile.rb +1 -1
  22. data/test/test_dependency_list.rb +163 -0
  23. data/test/test_deployment.rb +93 -0
  24. data/test/test_remote_fetcher.rb +38 -36
  25. metadata +23 -47
  26. data/test/data/a-0.0.1.gem +0 -0
  27. data/test/data/a-0.0.2.gem +0 -0
  28. data/test/data/b-0.0.2.gem +0 -0
  29. data/test/data/c-1.2.gem +0 -0
  30. data/test/data/gemhome/cache/a-0.0.1.gem +0 -0
  31. data/test/data/gemhome/cache/a-0.0.2.gem +0 -0
  32. data/test/data/gemhome/cache/b-0.0.2.gem +0 -0
  33. data/test/data/gemhome/cache/c-1.2.gem +0 -0
  34. data/test/data/gemhome/gems/a-0.0.1/lib/code.rb +0 -1
  35. data/test/data/gemhome/gems/a-0.0.2/lib/code.rb +0 -1
  36. data/test/data/gemhome/gems/b-0.0.2/lib/code.rb +0 -1
  37. data/test/data/gemhome/gems/c-1.2/lib/code.rb +0 -1
  38. data/test/data/gemhome/specifications/a-0.0.1.gemspec +0 -8
  39. data/test/data/gemhome/specifications/a-0.0.2.gemspec +0 -8
  40. data/test/data/gemhome/specifications/b-0.0.2.gemspec +0 -8
  41. data/test/data/gemhome/specifications/c-1.2.gemspec +0 -8
  42. data/test/data/one/one-0.0.1.gem +0 -0
@@ -37,10 +37,12 @@ module Gem
37
37
  register_command UninstallCommand.new
38
38
  register_command CheckCommand.new
39
39
  register_command BuildCommand.new
40
+ register_command DependencyCommand.new
40
41
  register_command QueryCommand.new
41
42
  register_command ListCommand.new
42
43
  register_command SearchCommand.new
43
44
  register_command UpdateCommand.new
45
+ register_command CleanupCommand.new
44
46
  register_command RDocCommand.new
45
47
  register_command EnvironmentCommand.new
46
48
  register_command SpecificationCommand.new
@@ -111,7 +113,7 @@ module Gem
111
113
  # - if it's specified multiple times, the first one wins
112
114
  # - there is a default config file location HOME/.gemrc
113
115
  def load_config_file_options(args)
114
- config_file = File.join(ENV['HOME'], ".gemrc")
116
+ config_file = Gem.config_file
115
117
  if args.index("--config-file")
116
118
  config_file = args[args.index("--config-file")+1]
117
119
  end
@@ -78,6 +78,10 @@ module Gem
78
78
 
79
79
  private
80
80
 
81
+ def command_manager
82
+ Gem::CommandManager.instance
83
+ end
84
+
81
85
  def handle_options(args)
82
86
  args = add_extra_args(args)
83
87
  @options = @defaults.clone
@@ -13,13 +13,13 @@ module Gem
13
13
  rescue ArgumentError
14
14
  warn "Failed to load #{config_file_name}"
15
15
  rescue Errno::ENOENT
16
- warn "Config file #{config_file_name} does not exist"
16
+ # Ignore missing config file error.
17
17
  end
18
18
  @hash ||= {}
19
19
  end
20
20
 
21
21
  def config_file_name
22
- @config_file_name || default_config_file_name
22
+ @config_file_name || Gem.config_file
23
23
  end
24
24
 
25
25
  def [](key)
@@ -51,10 +51,6 @@ module Gem
51
51
  end
52
52
  end
53
53
  end
54
-
55
- def default_config_file_name
56
- File.join(ENV['HOME'], '.gemrc')
57
- end
58
54
  end
59
55
 
60
56
  end
@@ -93,8 +93,8 @@ module Gem
93
93
  # Return a list of all installed gemspecs, sorted by alphabetical order and in reverse
94
94
  # version order.
95
95
  def init_gemspecs
96
- Gem.source_index.map { |_, spec| spec }.sort_by { |spec|
97
- [spec.name, spec.version.to_ints.map { |n| -n } ]
96
+ Gem.source_index.map { |_, spec| spec }.sort { |a,b|
97
+ (a.name <=> b.name).nonzero? || (b.version <=> a.version)
98
98
  }
99
99
  end
100
100
 
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Gem
4
+ class DependencyList
5
+ def self.from_source_index(src_index)
6
+ deps = DependencyList.new
7
+ src_index.each do |full_name, spec|
8
+ deps.add(spec)
9
+ end
10
+ deps
11
+ end
12
+
13
+ def initialize
14
+ @specs = []
15
+ end
16
+
17
+ # Are all the dependencies in the list satisfied?
18
+ def ok?
19
+ @specs.all? { |spec|
20
+ spec.dependencies.all? { |dep|
21
+ @specs.find { |s| s.satisfies_requirement?(dep) }
22
+ }
23
+ }
24
+ end
25
+
26
+ # Add a gemspec to the dependency list.
27
+ def add(gemspec)
28
+ @specs << gemspec
29
+ end
30
+
31
+ def find_name(full_name)
32
+ @specs.find { |spec| spec.full_name == full_name }
33
+ end
34
+
35
+ def remove_by_name(full_name)
36
+ @specs.delete_if { |spec| spec.full_name == full_name }
37
+ end
38
+
39
+ # Is is ok to remove a gem from the dependency list?
40
+ #
41
+ # If removing the gemspec creates breaks a currently ok dependency,
42
+ # then it is NOT ok to remove the gem.
43
+ def ok_to_remove?(full_name)
44
+ gem_to_remove = find_name(full_name)
45
+ siblings = @specs.find_all { |s|
46
+ s.name == gem_to_remove.name &&
47
+ s.full_name != gem_to_remove.full_name
48
+ }
49
+ deps = []
50
+ @specs.each do |spec|
51
+ spec.dependencies.each do |dep|
52
+ deps << dep if gem_to_remove.satisfies_requirement?(dep)
53
+ end
54
+ end
55
+ deps.all? { |dep|
56
+ siblings.any? { |s|
57
+ s.satisfies_requirement?(dep)
58
+ }
59
+ }
60
+ end
61
+
62
+ # Return a list of the specifications in the dependency list,
63
+ # sorted in order so that no spec in the list depends on a gem
64
+ # earlier in the list.
65
+ #
66
+ # This is useful when removing gems from a set of installed gems.
67
+ # By removing them in the returned order, you don't get into as
68
+ # many dependency issues.
69
+ #
70
+ # If there are circular dependencies (yuck!), then gems will be
71
+ # returned in order until only the circular dependents and anything
72
+ # they reference are left. Then arbitrary gemspecs will be returned
73
+ # until the circular dependency is broken, after which gems will be
74
+ # returned in dependency order again.
75
+ def dependency_order
76
+ result = []
77
+ disabled = {}
78
+ predecessors = build_predecessors
79
+ while disabled.size < @specs.size
80
+ candidate = @specs.find { |spec|
81
+ ! disabled[spec.full_name] &&
82
+ active_count(predecessors[spec.full_name], disabled) == 0
83
+ }
84
+ if candidate
85
+ disabled[candidate.full_name] = true
86
+ result << candidate
87
+ elsif candidate = @specs.find { |spec| ! disabled[spec.full_name] }
88
+ # This case handles circular dependencies. Just choose a
89
+ # candidate and move on.
90
+ disabled[candidate.full_name] = true
91
+ result << candidate
92
+ else
93
+ # We should never get here, but just in case we will terminate
94
+ # the loop.
95
+ break
96
+ end
97
+ end
98
+ result
99
+ end
100
+
101
+ private
102
+
103
+ # Count the number of gemspecs in the list +specs+ that are still
104
+ # active (e.g. not listed in the ignore hash).
105
+ def active_count(specs, ignored)
106
+ result = 0
107
+ specs.each do |spec|
108
+ result += 1 unless ignored[spec.full_name]
109
+ end
110
+ result
111
+ end
112
+
113
+ # Return a hash of predecessors. E.g. results[spec.full_name] is a
114
+ # list of gemspecs that have a dependency satisfied by spec.
115
+ def build_predecessors
116
+ result = Hash.new { |h,k| h[k] = [] }
117
+ @specs.each do |spec|
118
+ @specs.each do |other|
119
+ next if spec.full_name == other.full_name
120
+ other.dependencies.each do |dep|
121
+ if spec.satisfies_requirement?(dep)
122
+ result[spec.full_name] << other
123
+ end
124
+ end
125
+ end
126
+ end
127
+ result
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,265 @@
1
+ # The following is borrowed from setup.rb
2
+
3
+ def File.binread(fname)
4
+ open(fname, 'rb') {|f|
5
+ return f.read
6
+ }
7
+ end
8
+
9
+ # for corrupted windows stat(2)
10
+ def File.dir?(path)
11
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
12
+ end
13
+
14
+
15
+ module Gem
16
+
17
+ module Deployment
18
+
19
+ # The following is borrowed from setup.rb
20
+ module FileOperations
21
+
22
+ def mkdir_p(dirname, prefix = nil)
23
+ dirname = prefix + File.expand_path(dirname) if prefix
24
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
25
+ return if no_harm?
26
+
27
+ # does not check '/'... it's too abnormal case
28
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
29
+ if /\A[a-z]:\z/i =~ dirs[0]
30
+ disk = dirs.shift
31
+ dirs[0] = disk + dirs[0]
32
+ end
33
+ dirs.each_index do |idx|
34
+ path = dirs[0..idx].join('')
35
+ Dir.mkdir path unless File.dir?(path)
36
+ end
37
+ end
38
+
39
+ def rm_f(fname)
40
+ $stderr.puts "rm -f #{fname}" if verbose?
41
+ return if no_harm?
42
+
43
+ if File.exist?(fname) or File.symlink?(fname)
44
+ File.chmod 0777, fname
45
+ File.unlink fname
46
+ end
47
+ end
48
+
49
+ def rm_rf(dn)
50
+ $stderr.puts "rm -rf #{dn}" if verbose?
51
+ return if no_harm?
52
+
53
+ Dir.chdir dn
54
+ Dir.foreach('.') do |fn|
55
+ next if fn == '.'
56
+ next if fn == '..'
57
+ if File.dir?(fn)
58
+ verbose_off {
59
+ rm_rf fn
60
+ }
61
+ else
62
+ verbose_off {
63
+ rm_f fn
64
+ }
65
+ end
66
+ end
67
+ Dir.chdir '..'
68
+ Dir.rmdir dn
69
+ end
70
+
71
+ def no_harm?
72
+ false
73
+ end
74
+
75
+ def verbose?
76
+ false
77
+ end
78
+
79
+ def verbose_off(&block)
80
+ block.call
81
+ end
82
+
83
+ end
84
+
85
+ class Manager
86
+
87
+ DEPLOYMENTS_DIR = "."
88
+ DEPLOYMENTS_DB = "deployments.yaml"
89
+
90
+ attr_reader :deployments
91
+
92
+ def initialize(dir = DEPLOYMENTS_DIR, db = DEPLOYMENTS_DB)
93
+ require 'yaml'
94
+ require 'digest/sha1'
95
+ @db_file = File.expand_path(File.join(dir, db))
96
+ if File.exist?(@db_file)
97
+ @deployments = YAML.load(File.binread(@db_file))
98
+ @deployments.each {|deployment| deployment.manager = self}
99
+ else
100
+ @deployments = []
101
+ end
102
+ end
103
+
104
+ def new_deployment(target_dir = nil)
105
+ unless target_dir
106
+ require 'rbconfig'
107
+ target_dir = Config::CONFIG['sitelibdir']
108
+ end
109
+ target_dir = File.expand_path(target_dir)
110
+ deployment = self[target_dir]
111
+ unless deployment
112
+ deployment = ActiveDeployment.new(target_dir)
113
+ deployment.manager = self
114
+ @deployments << deployment
115
+ end
116
+ deployment
117
+ end
118
+
119
+ def persist
120
+ File.open(@db_file, "wb") {|f| f.puts @deployments.to_yaml}
121
+ end
122
+
123
+ def [](target_dir)
124
+ target_dir = File.expand_path(target_dir)
125
+ @deployments.each {|deployment| return deployment if deployment.target_directory == target_dir}
126
+ nil
127
+ end
128
+ end
129
+
130
+ class ActiveDeployment
131
+ attr_reader :target_directory, :deployed_gems
132
+ attr_accessor :manager
133
+
134
+ def initialize(target_directory)
135
+ @target_directory = target_directory
136
+ @deployed_gems = []
137
+ end
138
+
139
+ def to_yaml_properties
140
+ ['@target_directory', '@deployed_gems']
141
+ end
142
+
143
+ def prepare
144
+ @deployed_gems.each {|gem| gem.prepare}
145
+ end
146
+
147
+ def deploy
148
+ @deployed_gems.each {|gem| gem.deploy}
149
+ if fully_deployed?
150
+ @manager.persist
151
+ else
152
+ raise "ERROR: Did not fully deploy"
153
+ end
154
+ end
155
+
156
+ def fully_deployed?
157
+ @deployed_gems.each {|gem| return false unless gem.deployed?}
158
+ return true
159
+ end
160
+
161
+ def add_all_gems
162
+ Gem.source_index.each do |name, spec|
163
+ @deployed_gems << DeployedGem.new(spec, @target_directory)
164
+ end
165
+ self
166
+ end
167
+
168
+ def add_gem(gem_to_add)
169
+ @deployed_gems.each {|dg| return if gem_to_add.full_name == dg.gem_name}
170
+ @deployed_gems << DeployedGem.new(gem_to_add, @target_directory)
171
+ return self if gem_to_add.dependencies.size == 0
172
+ # must fulfill dependencies
173
+ sats = {}
174
+ Gem.source_index.each do |name, gem|
175
+ gem_to_add.dependencies.each do |dependency|
176
+ (sats[dependency] ||= []) << gem if gem.satisfies_requirement?(dependency)
177
+ end
178
+ end
179
+ sats.each_value {|list| add_gem list.sort.last}
180
+ self
181
+ end
182
+ end
183
+
184
+ class DeployedGem
185
+ attr_reader :specification, :gem_name, :gem_path, :deployed_files
186
+
187
+ def initialize(spec, target_directory)
188
+ @gem_name = spec.full_name
189
+ @gem_path = spec.full_gem_path
190
+ @lib_paths = spec.require_paths
191
+ @target_directory = target_directory
192
+ @deployed_files = []
193
+ end
194
+
195
+ def to_yaml_properties
196
+ ['@gem_name', '@gem_path', '@lib_paths', '@target_directory', '@deployed_files']
197
+ end
198
+
199
+ def prepare
200
+ paths = @lib_paths.collect {|lib_path| File.expand_path(File.join(gem_path, lib_path))}
201
+ paths.each do |path|
202
+ Dir.glob("#{path}/**/*").each do |file|
203
+ unless File.directory?(file)
204
+ @deployed_files << DeployedFile.new(file, File.join(@target_directory, file[(path.size+1)..-1]))
205
+ end
206
+ end
207
+ end
208
+ @deployed_files.each {|df| df.prepare}
209
+ end
210
+
211
+ def deploy
212
+ @deployed_files.each {|file| file.deploy}
213
+ end
214
+
215
+ def deployed?
216
+ @deployed_files.each {|file| return false unless file.deployed?}
217
+ return true
218
+ end
219
+ end
220
+
221
+ class DeployedFile
222
+
223
+ include FileOperations
224
+
225
+ attr_reader :source_path, :destination_path, :checksum
226
+
227
+ def initialize(source_path, destination_path)
228
+ @source_path = source_path
229
+ @destination_path = destination_path
230
+ end
231
+
232
+ def to_yaml_properties
233
+ ['@source_path', '@destination_path', '@checksum']
234
+ end
235
+
236
+ def prepare
237
+ @checksum ||= Digest::SHA1.new(File.binread(@source_path)).hexdigest
238
+ end
239
+
240
+ def deploy
241
+ return if deployed?
242
+ File.open(@source_path, "rb") do |source|
243
+ mkdir_p(File.dirname(@destination_path))
244
+ File.open(@destination_path, "wb") do |destination|
245
+ destination.write(source.read)
246
+ end
247
+ end
248
+ end
249
+
250
+ def deployed?
251
+ return false unless File.exist?(@destination_path)
252
+ return false if File.size(@source_path) != File.size(@destination_path)
253
+ new_checksum = nil
254
+ begin
255
+ new_checksum = Digest::SHA1.new(File.binread(@destination_path)).hexdigest
256
+ rescue
257
+ puts $!
258
+ puts $!.backtrace.join("\n")
259
+ end
260
+ new_checksum == @checksum
261
+ end
262
+ end
263
+
264
+ end
265
+ end