gem-compare 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41f631f7e0326a83d40c522f6003ee17c58d3862
4
- data.tar.gz: 93bbd6f62d8c2a98bd93458f6dbb1c9f74647825
3
+ metadata.gz: c0bf945c951c897beae61add41492c92c95248fa
4
+ data.tar.gz: 1113168bb3eeb4cc7af658f2b8a7bd2665c771a4
5
5
  SHA512:
6
- metadata.gz: d384515bab09282848e2900d9737f13222e331d2853cc4fc2bc49411b08118368aec9a4d3fcd023055fba4c3dc127654b35ff09679956485824196b01f35fea5
7
- data.tar.gz: 3859779673f455b99b0a0230386b25f1b9aab3e02a8db1a533c1fb5fc2f2b97ee16a06707168d041cb7e0dfd89848a98eaeaf14c769944c18c283dc1c8359a48
6
+ metadata.gz: c4da75c477e6784574cc96651df72e4aaa3621fac232170ace9634dce53192b88997cf42115285bad9a047fb69a0f217823f20e5a4da095ab85213f707ff0232
7
+ data.tar.gz: 0c0b71c3002837de7e87b096cd6c98189708baa56e9a478135974a35d7853c88620bdb145bf12321b11950bf9e92c3d3a962c032e1068cb4f904e7ea52dec24d
data/README.md CHANGED
@@ -134,6 +134,15 @@ Compared versions: ["0.1.0", "0.1.1", "0.1.2", "0.2.0", "0.2.1", "0.2.2", "0.2.3
134
134
  rspec from: [">= 0"] to: ["= 2.14.1"]
135
135
  ```
136
136
 
137
+ #### Platforms
138
+
139
+ *gem-compare* supports querying different gem platforms via standard `--platform` option. To compare
140
+ nokogiri gem on different platform run:
141
+ ```
142
+ $ gem compare nokogiri 1.5.6 1.6.1 -ak --platform java # for JRuby
143
+ $ gem compare nokogiri 1.5.6 1.6.1 -ak --platform x86-mingw32 # on Windows
144
+ ```
145
+
137
146
  ### Supported options
138
147
 
139
148
  To see all possible options run:
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rdoc/task'
4
4
 
5
5
  gemspec = Gem::Specification.new do |s|
6
6
  s.name = 'gem-compare'
7
- s.version = '0.0.2'
7
+ s.version = '0.0.3'
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.summary = 'RubyGems plugin for comparing gem versions'
10
10
  s.description = <<-EOF
@@ -19,6 +19,8 @@ gemspec = Gem::Specification.new do |s|
19
19
  'lib/**/*.rb', 'lib/**/**/*.rb', 'test/**/test*.rb']
20
20
  s.required_ruby_version = '>= 2.0.0'
21
21
  s.required_rubygems_version = '>= 2.0.0'
22
+ s.add_runtime_dependency 'json'
23
+ s.add_runtime_dependency 'curl'
22
24
  s.add_runtime_dependency 'diffy'
23
25
  s.add_runtime_dependency 'rainbow'
24
26
  s.add_runtime_dependency 'gemnasium-parser'
@@ -1,7 +1,10 @@
1
1
  require 'rubygems/command'
2
+ require 'rubygems/version_option'
2
3
  require 'rubygems/comparator'
3
4
 
4
5
  class Gem::Commands::CompareCommand < Gem::Command
6
+ include Gem::VersionOption
7
+
5
8
  def initialize
6
9
  super 'compare', 'Compare gem\'s versions and generate a report of changes',
7
10
  :output => Dir.pwd
@@ -18,7 +21,10 @@ class Gem::Commands::CompareCommand < Gem::Command
18
21
  options[:no_color] = true
19
22
  end
20
23
 
21
- add_option('-pPARAM', '--param=PARAM', 'Compare only a given paramater') do |param, options|
24
+ # Speficy the platform using --platform=PLATFORM
25
+ add_platform_option
26
+
27
+ add_option('-pPARAM', '--param PARAM', 'Compare only a given paramater') do |param, options|
22
28
  options[:param] = param
23
29
  end
24
30
 
@@ -1,10 +1,12 @@
1
1
  require 'tmpdir'
2
2
  require 'rbconfig'
3
3
  require 'rainbow'
4
+ require 'curb'
5
+ require 'json'
4
6
  require 'rubygems/package'
5
7
  require 'rubygems/dependency'
6
8
  require 'rubygems/spec_fetcher'
7
- require 'rubygems/comparator/base'
9
+ require 'rubygems/comparator/utils'
8
10
  require 'rubygems/comparator/report'
9
11
  require 'rubygems/comparator/spec_comparator'
10
12
  require 'rubygems/comparator/file_list_comparator'
@@ -17,7 +19,7 @@ require 'rubygems/comparator/gemfile_comparator'
17
19
  # Gemfiles
18
20
 
19
21
  class Gem::Comparator
20
- include Gem::Comparator::Base
22
+ include Gem::Comparator::Utils
21
23
  attr_accessor :options, :report
22
24
 
23
25
  VERSION = '0.0.2'
@@ -28,6 +30,8 @@ class Gem::Comparator
28
30
  # Creates temporal directory if the gem files shouldn't be kept
29
31
 
30
32
  def initialize(options)
33
+ info "gem-compare in #{VERSION}"
34
+
31
35
  unless options[:keep_all]
32
36
  options[:output] = Dir.mktmpdir
33
37
  end
@@ -40,6 +44,14 @@ class Gem::Comparator
40
44
  Rainbow.enabled = false
41
45
  end
42
46
 
47
+ # Let's override platforms with the latest one if
48
+ # a platform has been specified via --platform
49
+ if options[:added_platform]
50
+ Gem.platforms = [Gem.platforms.last]
51
+ options[:platform] = Gem.platforms.last.to_s
52
+ info "Overriding platform to: #{options[:platform]}"
53
+ end
54
+
43
55
  @options = options
44
56
 
45
57
  # Results from the comparison
@@ -52,18 +64,22 @@ class Gem::Comparator
52
64
  # Compares file lists, requirements, other meta data
53
65
 
54
66
  def compare_versions(gem_name, versions)
55
- info "gem-compare in #{VERSION}"
56
67
  # Expand versions (<=, >=, ~>) and sort them
57
68
  versions = expand_versions(gem_name, versions)
58
69
 
59
70
  error 'Only one version specified. Specify at lease two versions.' \
60
71
  if versions.size == 1
61
72
 
73
+ # This should match the final versions that has been compared
74
+ @compared_versions = versions
75
+
62
76
  versions.each do |version|
63
- download_gems? ? download_package(gem_name, version) : download_specification(gem_name, version)
77
+ download_gems? ?
78
+ get_package(gem_name, version) :
79
+ get_specification(gem_name, version)
64
80
  end
65
81
 
66
- @report.set_header "Compared versions: #{versions}"
82
+ @report.set_header "Compared versions: #{@compared_versions}"
67
83
 
68
84
  comparators = [SpecComparator,
69
85
  FileListComparator,
@@ -72,7 +88,7 @@ class Gem::Comparator
72
88
 
73
89
  comparators.each do |c|
74
90
  comparator = c.new
75
- cmp = (c::COMPARES == :packages) ? gem_packages.values : gem_specs.values
91
+ cmp = (comparator.compares == :packages) ? gem_packages.values : gem_specs.values
76
92
  @report = comparator.compare(cmp, @report, @options)
77
93
  end
78
94
 
@@ -95,9 +111,10 @@ class Gem::Comparator
95
111
  # Return list of expanded versions
96
112
 
97
113
  def expand_versions(gem_name, versions)
98
- info 'Expanding versions...'
114
+ info "Expanding versions #{versions}..."
99
115
  expanded = []
100
116
  versions.each do |version|
117
+ version = latest_gem_version(gem_name) if version == '_'
101
118
  if version =~ VERSION_REGEX
102
119
  expanded << version
103
120
  next
@@ -121,22 +138,46 @@ class Gem::Comparator
121
138
 
122
139
  error 'No versions found.' if versions.size == 0
123
140
 
124
- info "Versions: #{versions}"
141
+ info "Expanded versions: #{versions}"
125
142
  versions
126
143
  end
127
144
 
145
+ def remote_gem_versions(gem_name)
146
+ client = Curl::Easy.new
147
+ client.url = "https://rubygems.org/api/v1/versions/#{gem_name}.json"
148
+ client.follow_location = true
149
+ client.http_get
150
+ json = JSON.parse(client.body_str)
151
+ gems = json.collect { |version| version['number'] }
152
+ info "Upstream versions: #{gems}"
153
+ gems
154
+ end
155
+
156
+ def latest_gem_version(gem_name)
157
+ remote_gem_versions(gem_name).map{ |v| Gem::Version.new v }.max.to_s
158
+ end
159
+
128
160
  def gem_file_name(gem_name, version)
129
- "#{gem_name}-#{version}.gem"
161
+ if @options[:platform]
162
+ "#{gem_name}-#{version}-#{@options[:platform]}.gem"
163
+ else
164
+ "#{gem_name}-#{version}.gem"
165
+ end
130
166
  end
131
167
 
132
- def download_package(gem_name, version)
168
+ def get_package(gem_name, version)
133
169
  gem_file = gem_file_name(gem_name, version)
134
170
  return gem_packages["#{gem_file}"] if gem_packages["#{gem_file}"]
135
171
 
136
172
  find_downloaded_gem(gem_file)
137
173
  return gem_packages["#{gem_file}"] if gem_packages["#{gem_file}"]
138
174
 
139
- spec, source = download_specification(gem_name, version)
175
+ download_package(gem_name, version)
176
+ end
177
+
178
+ def download_package(gem_name, version)
179
+ spec, source = get_specification(gem_name, version)
180
+ gem_file = gem_file_name(gem_name, spec.version.to_s)
140
181
 
141
182
  Dir.chdir @options[:output] do
142
183
  source.download spec
@@ -149,22 +190,44 @@ class Gem::Comparator
149
190
  package
150
191
  end
151
192
 
152
- def download_specification(gem_name, version)
193
+ def get_specification(gem_name, version)
153
194
  gem_file = gem_file_name(gem_name, version)
154
195
  return gem_specs["#{gem_file}"] if gem_specs["#{gem_file}"]
155
196
 
156
197
  find_downloaded_gem(gem_file)
157
198
  return gem_specs["#{gem_file}"] if gem_specs["#{gem_file}"]
158
199
 
200
+ download_specification(gem_name, version)
201
+ end
202
+
203
+ def download_specification(gem_name, version)
159
204
  dep = Gem::Dependency.new gem_name, version
160
205
  specs_and_sources, _errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep
161
206
  spec, source = specs_and_sources.max_by { |s,| s.version }
162
207
  error "Gem #{gem_name} in #{version} doesn't exist." if spec.nil?
208
+
209
+ fix_comparing_version(version, spec.version.to_s)
210
+ gem_file = gem_file_name(gem_name, spec.version.to_s)
211
+
163
212
  gem_specs["#{gem_file}"] = spec
164
213
 
165
214
  [spec, source]
166
215
  end
167
216
 
217
+ ##
218
+ # Ensure the right version is referenced
219
+
220
+ def fix_comparing_version(version, spec_version)
221
+ if spec_version != version
222
+ @compared_versions.each do |v|
223
+ if v == version
224
+ @compared_versions[@compared_versions.index(version)] = spec_version
225
+ return
226
+ end
227
+ end
228
+ end
229
+ end
230
+
168
231
  def find_downloaded_gem(gem_file)
169
232
  if File.exist? File.join(@options[:output], gem_file)
170
233
  info "#{gem_file} exists, using already downloaded file."
@@ -184,7 +247,7 @@ class Gem::Comparator
184
247
 
185
248
  def download_gems?
186
249
  return true if @options[:keep_all]
187
- @options[:param] ? SPEC_FILES_PARAMS.include?(@options[:param]) : true
250
+ @options[:param] ? !param_available_in_marshal?(@options[:param]) : true
188
251
  end
189
252
 
190
253
  def gem_packages
@@ -1,65 +1,28 @@
1
1
  require 'rainbow'
2
+ require 'rubygems/comparator/utils'
3
+ require 'rubygems/comparator/report'
2
4
 
3
5
  class Gem::Comparator
4
- module Base
5
- include Gem::UserInteraction
6
+ class Base
7
+ include Gem::Comparator::Utils
8
+ include Gem::Comparator::Report::Signs
6
9
 
7
- class DiffCommandMissing < StandardError; end
10
+ attr_accessor :compares
8
11
 
9
- SPACE = ' '
10
- DEFAULT_INDENT = SPACE*7
11
- OPERATORS = ['=', '!=', '>', '<', '>=', '<=', '~>']
12
- VERSION_REGEX = /\A(\d+\.){0,}\d+(\.[a-zA-Z]+\d{0,1}){0,1}\z/
13
- SHEBANG_REGEX = /\A#!.*/
14
- SPEC_PARAMS = %w[ author authors name platform require_paths rubygems_version summary
15
- license licenses bindir cert_chain description email executables
16
- extensions homepage metadata post_install_message rdoc_options
17
- required_ruby_version required_rubygems_version requirements
18
- signing_key has_rdoc date version ].sort
19
- SPEC_FILES_PARAMS = %w[ files test_files extra_rdoc_files ]
20
- DEPENDENCY_PARAMS = %w[ runtime_dependency development_dependency ]
21
- GEMFILE_PARAMS = %w[ gemfiles ]
12
+ ##
13
+ # Compare Gem::Specification objects by default
14
+ #
15
+ # To override create your own initialize method and
16
+ # set expect(:packages) to expect Gem::Package objects.
22
17
 
23
- private
24
-
25
- def param_exists?(param)
26
- (SPEC_PARAMS.include? param) ||
27
- (SPEC_FILES_PARAMS.include? param) ||
28
- (DEPENDENCY_PARAMS.include? param) ||
29
- (GEMFILE_PARAMS.include? param)
30
- end
31
-
32
- def filter_params(params, param)
33
- if param
34
- if params.include? param
35
- return [param]
36
- else
37
- return []
38
- end
39
- end
40
-
41
- params
42
- end
43
-
44
- def same
45
- Rainbow('SAME').green.bright
46
- end
18
+ def initialize
19
+ expect(:specs)
20
+ end
47
21
 
48
- def different
49
- Rainbow('DIFFERENT').red.bright
50
- end
51
-
52
- def info(msg)
53
- say msg if Gem.configuration.really_verbose
54
- end
55
-
56
- def warn(msg)
57
- say Rainbow("WARNING: #{msg}").red
58
- end
22
+ private
59
23
 
60
- def error(msg)
61
- say Rainbow("ERROR: #{msg}").red
62
- exit 1
24
+ def expect(what)
25
+ @compares = what
63
26
  end
64
27
 
65
28
  def extract_gem(package, target_dir)
@@ -76,13 +39,5 @@ class Gem::Comparator
76
39
  gem_dir
77
40
  end
78
41
 
79
- def check_diff_command_is_installed
80
- begin
81
- IO.popen('diff --version')
82
- rescue Exception
83
- raise DiffCommandMissing, \
84
- 'Calling `diff` command failed. Do you have it installed?'
85
- end
86
- end
87
42
  end
88
43
  end
@@ -7,15 +7,12 @@ class Gem::Comparator
7
7
  # compare dependencies between gem's versions
8
8
  # based on the given Gem::Specification objects
9
9
 
10
- class DependencyComparator
11
- include Gem::Comparator::Base
12
-
13
- COMPARES = :specs
10
+ class DependencyComparator < Gem::Comparator::Base
14
11
 
15
12
  ##
16
13
  # Compare dependencies in given +specs+ and
17
14
  # write the changes to the +report+
18
- #
15
+ #
19
16
  # If +options[:param]+ is set, it compares only
20
17
  # those dependencies
21
18
 
@@ -25,12 +22,11 @@ class Gem::Comparator
25
22
  filter_params(DEPENDENCY_PARAMS, options[:param]).each do |param|
26
23
  all_same = true
27
24
  type = param.gsub('_dependency', '').to_sym
28
-
29
25
  specs.each_with_index do |s, index|
30
26
  next if index == 0
31
27
 
32
- prev_deps = specs[index-1].dependencies.keep_if { |d| d.type == type }
33
- curr_deps = specs[index].dependencies.keep_if { |d| d.type == type }
28
+ prev_deps = specs[index-1].dependencies.select { |d| d.type == type }
29
+ curr_deps = specs[index].dependencies.select { |d| d.type == type }
34
30
  added, deleted, updated = resolve_dependencies(prev_deps, curr_deps)
35
31
 
36
32
  if (!deleted.empty? || !added.empty? || !updated.empty?)
@@ -60,20 +56,21 @@ class Gem::Comparator
60
56
  end
61
57
  if all_same && options[:log_all]
62
58
  report[param].set_header "#{same} #{type} dependencies:" if options[:log_all]
63
- deps = specs[0].dependencies.keep_if{ |d| d.type == type }.map{ |d| "#{d.name}: #{d.requirements_list}" }
59
+ deps = specs[0].dependencies.select{ |d| d.type == type }.map{ |d| "#{d.name}: #{d.requirements_list}" }
64
60
  deps = '[]' if deps.empty?
65
61
  report[param] << deps
66
62
  elsif !all_same
67
63
  report[param].set_header "#{different} #{type} dependencies:"
68
64
  end
69
65
  end
66
+
70
67
  report
71
68
  end
72
69
 
73
70
  private
74
-
71
+
75
72
  ##
76
- # Find dependencies between +prev_deps+ and +curr_deps+
73
+ # Find dependencies between +prev_deps+ and +curr_deps+
77
74
  #
78
75
  # Return [added, deleted, updated] deps
79
76
 
@@ -82,7 +79,7 @@ class Gem::Comparator
82
79
  deleted = prev_deps - curr_deps
83
80
  split_dependencies(added, deleted)
84
81
  end
85
-
82
+
86
83
  ##
87
84
  # Find updated dependencies between +added+ and
88
85
  # +deleted+ deps and move them out to +updated+.
@@ -0,0 +1,51 @@
1
+ require 'pathname'
2
+
3
+ module DirUtils
4
+ SHEBANG_REGEX = /\A#!.*/
5
+
6
+ attr_accessor :files_first_line
7
+
8
+ def self.file_first_line(file)
9
+ File.open(file){ |f| f.readline }.gsub(/(.*)\n/, '\1')
10
+ rescue
11
+ end
12
+
13
+ def self.file_has_shebang?(file)
14
+ file_first_line(file) =~ SHEBANG_REGEX
15
+ end
16
+
17
+ def self.files_same_first_line?(file1, file2)
18
+ file_first_line(file1) == file_first_line(file2)
19
+ end
20
+
21
+ def self.file_permissions(file)
22
+ sprintf("%o", File.stat(file).mode)
23
+ end
24
+
25
+ def self.gem_bin_file?(file)
26
+ file =~ /(\A|.*\/)bin\/.*/
27
+ end
28
+
29
+ ##
30
+ # Returns a unique list of directories and top level files
31
+ # out of an array of files
32
+
33
+ def self.dirs_of_files(file_list)
34
+ dirs_of_files = []
35
+ file_list.each do |file|
36
+ unless Pathname.new(file).dirname.to_s == '.'
37
+ dirs_of_files << "#{Pathname.new(file).dirname.to_s}/"
38
+ else
39
+ dirs_of_files << file
40
+ end
41
+ end
42
+ dirs_of_files.uniq
43
+ end
44
+
45
+ def self.remove_subdirs(dirs)
46
+ dirs.dup.sort_by(&:length).reverse.each do |dir|
47
+ dirs.delete_if{ |d| d =~ /#{dir}\/.+/ }
48
+ end
49
+ dirs
50
+ end
51
+ end