gem_sorter 0.5.2 → 0.5.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a14433575929ce85e046a16391ef12ca535aaf889e270311831d6afc84d39c7
4
- data.tar.gz: efffe4275cca1eb81d9f824e858945748070137c57d0c6872ec66b985aca7125
3
+ metadata.gz: e7eb0be5f76f0fe5bf85c828b98e7bc0aa2fedbab8131a0db6aefbd8664bfbf8
4
+ data.tar.gz: 893bb62c2c6e21857660a911c649c88c244f3eb3d8dcb2fdc9b8274e535bc26b
5
5
  SHA512:
6
- metadata.gz: dcc7cc1833d9c17b4b04e4a0442fa8e09630a48cce2eae2bf316726f4f267ce77e0d23e87b60783d776c1da7433ebb5ca06f0eaf72f8efb33c520628f74af27d
7
- data.tar.gz: 3c5b1e7ae3724f8b3143daac366df453c9196a92b5123e6972a9ea2713d32a9f46a161625a5c817f9a074896a7d2c91a90cb78fb73b370db5e4ed8f43d47f496
6
+ metadata.gz: b412dd7b89dd9a53115ec289b4010e7da6756b792e7cd16940fb0e06c53fbf44e96456d24cd84d0a9fa204babd2775252864a688382dfcb69baee4a3b44cbe92
7
+ data.tar.gz: e3b8fb028356f3c2de88c4c4bebde010325f8dc3b8d38bc1887c2c4ddf8c4f0f1162e3c86f9ea81992ccd7f88d9255e0f86b49089e6102f00e8151e6402360b3
data/README.md CHANGED
@@ -46,6 +46,7 @@ rake -r gem_sorter gemfile:sort
46
46
  * `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
47
47
  * `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
48
48
  * `update_versions`: Pass `true` to update the versions of the gems based on the lockfile.
49
+ * `force_update`: Pass `true` to update gems to their latest available versions from RubyGems, ignoring the lockfile. This will print a summary of updated gems and remind you to run `bundle install`.
49
50
  * `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
50
51
  * `remove_versions`: Pass `true` to remove version constraints from gems while preserving other parameters like `require` or `platforms`. This option takes precedence over `update_versions` if both are enabled.
51
52
 
@@ -61,6 +62,7 @@ Create a file in the root of your project called `gem_sorter.yml`
61
62
  * `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
62
63
  * `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
63
64
  * `update_versions`: Pass `true` to update the versions of the gems based on the lockfile.
65
+ * `force_update`: Pass `true` to update gems to their latest available versions from RubyGems, ignoring the lockfile. This will print a summary of updated gems and remind you to run `bundle install`.
64
66
  * `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
65
67
  * `remove_versions`: Pass `true` to remove version constraints from gems while preserving other parameters like `require` or `platforms`. This option takes precedence over `update_versions` if both are enabled.
66
68
  * `ignore_gems`: Pass an array of GEMs you want to ignore versions and comments
@@ -73,6 +75,7 @@ Example:
73
75
  backup: true
74
76
  update_comments: true
75
77
  update_versions: false
78
+ force_update: false
76
79
  use_double_quotes: true
77
80
  remove_versions: true
78
81
  ignore_gems:
@@ -1,3 +1,3 @@
1
1
  module GemSorter
2
- VERSION = '0.5.2'
2
+ VERSION = '0.5.3'
3
3
  end
data/lib/gem_sorter.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  require 'net/http'
3
3
  require 'cgi'
4
4
  require 'openssl'
5
+ require 'json'
5
6
 
6
7
  load File.expand_path('tasks/gem_sorter.rake', __dir__) if defined?(Rake)
7
8
 
@@ -12,6 +13,7 @@ module GemSorter
12
13
  @filepath = task_config.gemfile_path
13
14
  @content = File.read(task_config.gemfile_path)
14
15
  @versions = nil
16
+ @version_updates = []
15
17
  end
16
18
 
17
19
  def sort
@@ -24,7 +26,11 @@ module GemSorter
24
26
  source_line, gems, _ = process_main_section(main_section)
25
27
 
26
28
  update_gem_summaries(gems) if @config.update_comments
27
- update_version_text(gems) if @config.update_versions
29
+ if @config.force_update
30
+ force_update_versions(gems)
31
+ elsif @config.update_versions
32
+ update_version_text(gems)
33
+ end
28
34
  remove_versions(gems) if @config.remove_versions
29
35
  sorted_gems = sort_gem_blocks(gems)
30
36
 
@@ -41,7 +47,11 @@ module GemSorter
41
47
  group_sections.each do |section|
42
48
  group_gems = process_group_section(section)
43
49
  update_gem_summaries(group_gems) if @config.update_comments
44
- update_version_text(group_gems) if @config.update_versions
50
+ if @config.force_update
51
+ force_update_versions(group_gems)
52
+ elsif @config.update_versions
53
+ update_version_text(group_gems)
54
+ end
45
55
  remove_versions(group_gems) if @config.remove_versions
46
56
  result << "group#{section.split("\n").first}"
47
57
  result.concat(sort_gem_blocks(group_gems).map { |line| " #{line}" })
@@ -51,6 +61,8 @@ module GemSorter
51
61
 
52
62
  result = transform_to_double_quotes(result) if @config.use_double_quotes
53
63
 
64
+ print_version_updates if @config.force_update && !@version_updates.empty?
65
+
54
66
  result.join("\n")
55
67
  end
56
68
 
@@ -113,6 +125,43 @@ module GemSorter
113
125
  end
114
126
  end
115
127
 
128
+ def force_update_versions(gems)
129
+ @versions ||= fetch_versions_from_lockfile("#{@filepath}.lock")
130
+
131
+ gems.each do |gem_block|
132
+ gem_name = extract_gem_name(gem_block[:gem_line])
133
+ next if @config.ignore_gems.include?(gem_name) || @config.ignore_gem_versions.include?(gem_name)
134
+
135
+ # Try to get current version from lockfile first, then from gem line
136
+ current_version = @versions[gem_name] || extract_current_version(gem_block[:gem_line])
137
+ latest_version = fetch_latest_version(gem_name)
138
+
139
+ next unless latest_version
140
+
141
+ extra_params = extract_params(gem_block[:gem_line])
142
+ new_gemfile_text = fetch_gemfile_text(gem_name, latest_version, gem_block[:gem_line])
143
+
144
+ next unless new_gemfile_text && new_gemfile_text != gem_block[:gem_line]
145
+
146
+ gem_block[:gem_line] = [new_gemfile_text.strip, extra_params].select { |value| !value.nil? && !value.empty? }.join(',')
147
+
148
+ # Track version update if version changed
149
+ # Compare semantic versions (x.y.z) for accurate comparison
150
+ current_semantic = current_version&.match(/(\d+\.\d+\.\d+)/)
151
+ current_semantic = current_semantic ? current_semantic[1] : nil
152
+ latest_semantic = latest_version.match(/(\d+\.\d+\.\d+)/)
153
+ latest_semantic = latest_semantic ? latest_semantic[1] : nil
154
+
155
+ if current_semantic != latest_semantic
156
+ @version_updates << {
157
+ gem_name: gem_name,
158
+ from_version: current_version || 'no version specified',
159
+ to_version: latest_version
160
+ }
161
+ end
162
+ end
163
+ end
164
+
116
165
  def remove_versions(gems)
117
166
  gems.each do |gem_block|
118
167
  gem_name = extract_gem_name(gem_block[:gem_line])
@@ -291,5 +340,51 @@ module GemSorter
291
340
  versions
292
341
  end
293
342
 
343
+ def fetch_latest_version(gem_name)
344
+ url = URI("https://rubygems.org/api/v1/gems/#{gem_name.strip}.json")
345
+
346
+ begin
347
+ http = Net::HTTP.new(url.host, url.port)
348
+ http.use_ssl = true
349
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
350
+
351
+ request = Net::HTTP::Get.new(url)
352
+ response = http.request(request)
353
+
354
+ unless response.is_a?(Net::HTTPSuccess)
355
+ return nil
356
+ end
357
+
358
+ gem_data = JSON.parse(response.body)
359
+ gem_data['version']
360
+ rescue => e
361
+ nil
362
+ end
363
+ end
364
+
365
+ def extract_current_version(gem_line)
366
+ # Try to extract version from gem line
367
+ # Examples: gem "rails", "~> 7.0" or gem "rails", "7.0.0" or gem "rails", ">= 7.0", "< 8.0"
368
+ # Match first version string after gem name
369
+ version_match = gem_line.match(/gem\s+['"][^'"]+['"]\s*,\s*['"]([^'"]+)['"]/)
370
+ return nil unless version_match
371
+
372
+ version_string = version_match[1]
373
+ # Extract semantic version (x.y.z) from version string, or return the full version string
374
+ semantic_version = version_string.match(/(\d+\.\d+\.\d+)/)
375
+ semantic_version ? semantic_version[1] : version_string
376
+ end
377
+
378
+ def print_version_updates
379
+ return if @version_updates.empty?
380
+
381
+ puts "\nThe following gems were updated:"
382
+ @version_updates.each do |update|
383
+ puts " * #{update[:gem_name]} (#{update[:from_version]} -> #{update[:to_version]})"
384
+ end
385
+ puts "\nRun `bundle install` to install the updated gems."
386
+ puts ""
387
+ end
388
+
294
389
  end
295
390
  end
data/lib/task_config.rb CHANGED
@@ -10,6 +10,7 @@ module GemSorter
10
10
  'update_versions' => false,
11
11
  'use_double_quotes' => false,
12
12
  'remove_versions' => false,
13
+ 'force_update' => false,
13
14
  'gemfile_path' => 'Gemfile',
14
15
  'ignore_gems' => [],
15
16
  'ignore_gem_versions' => [],
@@ -22,6 +23,7 @@ module GemSorter
22
23
  @update_versions = nil
23
24
  @use_double_quotes = nil
24
25
  @remove_versions = nil
26
+ @force_update = nil
25
27
  @ignore_gems = nil
26
28
  @ignore_gem_versions = nil
27
29
  @ignore_gem_comments = nil
@@ -49,6 +51,10 @@ module GemSorter
49
51
  @remove_versions.nil? ? DEFAULT_CONFIG['remove_versions'] : @remove_versions
50
52
  end
51
53
 
54
+ def force_update
55
+ @force_update.nil? ? DEFAULT_CONFIG['force_update'] : @force_update
56
+ end
57
+
52
58
  def ignore_gems
53
59
  @ignore_gems.nil? ? DEFAULT_CONFIG['ignore_gems'] : @ignore_gems
54
60
  end
@@ -82,6 +88,7 @@ module GemSorter
82
88
  @gemfile_path = task_config['gemfile_path'] if task_config.key?('gemfile_path')
83
89
  @use_double_quotes = task_config['use_double_quotes'] if task_config.key?('use_double_quotes')
84
90
  @remove_versions = task_config['remove_versions'] if task_config.key?('remove_versions')
91
+ @force_update = task_config['force_update'] if task_config.key?('force_update')
85
92
  @ignore_gems = task_config['ignore_gems'] if task_config.key?('ignore_gems')
86
93
  @ignore_gem_versions = task_config['ignore_gem_versions'] if task_config.key?('ignore_gem_versions')
87
94
  @ignore_gem_comments = task_config['ignore_gem_comments'] if task_config.key?('ignore_gem_comments')
@@ -96,6 +103,7 @@ module GemSorter
96
103
  @gemfile_path = args[:gemfile_path] unless args[:gemfile_path].nil?
97
104
  @use_double_quotes = parse_boolean(args[:use_double_quotes]) unless args[:use_double_quotes].nil?
98
105
  @remove_versions = parse_boolean(args[:remove_versions]) unless args[:remove_versions].nil?
106
+ @force_update = parse_boolean(args[:force_update]) unless args[:force_update].nil?
99
107
  @ignore_gems = args[:ignore_gems] unless args[:ignore_gems].nil?
100
108
  @ignore_gem_versions = args[:ignore_gem_versions] unless args[:ignore_gem_versions].nil?
101
109
  @ignore_gem_comments = args[:ignore_gem_comments] unless args[:ignore_gem_comments].nil?
@@ -3,8 +3,8 @@ require 'yaml'
3
3
  require 'task_config'
4
4
 
5
5
  namespace :gemfile do
6
- desc 'Sort gems in Gemfile alphabetically. Options: [backup=true|false] [update_comments=true|false] [update_versions=true|false]'
7
- task :sort, [:backup, :update_comments, :update_versions] do |_t, args|
6
+ desc 'Sort gems in Gemfile alphabetically. Options: [backup=true|false] [update_comments=true|false] [update_versions=true|false] [force_update=true|false]'
7
+ task :sort, [:backup, :update_comments, :update_versions, :force_update] do |_t, args|
8
8
  task_config = GemSorter::TaskConfig.new(args)
9
9
 
10
10
  if File.exist?(task_config.gemfile_path)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_sorter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renan Garcia