gem_sorter 0.5.0 → 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 +4 -4
- data/README.md +5 -0
- data/lib/gem_sorter/version.rb +1 -1
- data/lib/gem_sorter.rb +127 -9
- data/lib/task_config.rb +8 -0
- data/lib/tasks/gem_sorter.rake +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7eb0be5f76f0fe5bf85c828b98e7bc0aa2fedbab8131a0db6aefbd8664bfbf8
|
|
4
|
+
data.tar.gz: 893bb62c2c6e21857660a911c649c88c244f3eb3d8dcb2fdc9b8274e535bc26b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b412dd7b89dd9a53115ec289b4010e7da6756b792e7cd16940fb0e06c53fbf44e96456d24cd84d0a9fa204babd2775252864a688382dfcb69baee4a3b44cbe92
|
|
7
|
+
data.tar.gz: e3b8fb028356f3c2de88c4c4bebde010325f8dc3b8d38bc1887c2c4ddf8c4f0f1162e3c86f9ea81992ccd7f88d9255e0f86b49089e6102f00e8151e6402360b3
|
data/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
<img src="https://i.imgur.com/WHOyL9W.png" width="150" alt="GemSorter Logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
+
[](https://badge.fury.io/rb/gem_sorter)
|
|
6
|
+
|
|
5
7
|
# GemSorter
|
|
6
8
|
|
|
7
9
|
GemSorter is a simple gem to sort the contents of your Gemfile alphabetically while preserving comments and group structure. It helps maintain a clean and organized Gemfile.
|
|
@@ -44,6 +46,7 @@ rake -r gem_sorter gemfile:sort
|
|
|
44
46
|
* `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
|
|
45
47
|
* `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
|
|
46
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`.
|
|
47
50
|
* `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
|
|
48
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.
|
|
49
52
|
|
|
@@ -59,6 +62,7 @@ Create a file in the root of your project called `gem_sorter.yml`
|
|
|
59
62
|
* `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
|
|
60
63
|
* `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
|
|
61
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`.
|
|
62
66
|
* `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
|
|
63
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.
|
|
64
68
|
* `ignore_gems`: Pass an array of GEMs you want to ignore versions and comments
|
|
@@ -71,6 +75,7 @@ Example:
|
|
|
71
75
|
backup: true
|
|
72
76
|
update_comments: true
|
|
73
77
|
update_versions: false
|
|
78
|
+
force_update: false
|
|
74
79
|
use_double_quotes: true
|
|
75
80
|
remove_versions: true
|
|
76
81
|
ignore_gems:
|
data/lib/gem_sorter/version.rb
CHANGED
data/lib/gem_sorter.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# lib/gem_sorter.rb
|
|
2
2
|
require 'net/http'
|
|
3
3
|
require 'cgi'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'json'
|
|
4
6
|
|
|
5
7
|
load File.expand_path('tasks/gem_sorter.rake', __dir__) if defined?(Rake)
|
|
6
8
|
|
|
@@ -11,22 +13,33 @@ module GemSorter
|
|
|
11
13
|
@filepath = task_config.gemfile_path
|
|
12
14
|
@content = File.read(task_config.gemfile_path)
|
|
13
15
|
@versions = nil
|
|
16
|
+
@version_updates = []
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
def sort
|
|
20
|
+
ruby_line = extract_ruby_line(@content)
|
|
21
|
+
|
|
17
22
|
parts = @content.split(/^group/)
|
|
18
23
|
main_section = parts.shift
|
|
19
24
|
group_sections = parts
|
|
20
25
|
|
|
21
|
-
source_line, gems = process_main_section(main_section)
|
|
26
|
+
source_line, gems, _ = process_main_section(main_section)
|
|
22
27
|
|
|
23
28
|
update_gem_summaries(gems) if @config.update_comments
|
|
24
|
-
|
|
29
|
+
if @config.force_update
|
|
30
|
+
force_update_versions(gems)
|
|
31
|
+
elsif @config.update_versions
|
|
32
|
+
update_version_text(gems)
|
|
33
|
+
end
|
|
25
34
|
remove_versions(gems) if @config.remove_versions
|
|
26
35
|
sorted_gems = sort_gem_blocks(gems)
|
|
27
36
|
|
|
28
37
|
result = []
|
|
29
38
|
result << source_line
|
|
39
|
+
if ruby_line
|
|
40
|
+
result << ''
|
|
41
|
+
result << ruby_line
|
|
42
|
+
end
|
|
30
43
|
result << ''
|
|
31
44
|
result.concat(sorted_gems)
|
|
32
45
|
result << ''
|
|
@@ -34,7 +47,11 @@ module GemSorter
|
|
|
34
47
|
group_sections.each do |section|
|
|
35
48
|
group_gems = process_group_section(section)
|
|
36
49
|
update_gem_summaries(group_gems) if @config.update_comments
|
|
37
|
-
|
|
50
|
+
if @config.force_update
|
|
51
|
+
force_update_versions(group_gems)
|
|
52
|
+
elsif @config.update_versions
|
|
53
|
+
update_version_text(group_gems)
|
|
54
|
+
end
|
|
38
55
|
remove_versions(group_gems) if @config.remove_versions
|
|
39
56
|
result << "group#{section.split("\n").first}"
|
|
40
57
|
result.concat(sort_gem_blocks(group_gems).map { |line| " #{line}" })
|
|
@@ -44,11 +61,19 @@ module GemSorter
|
|
|
44
61
|
|
|
45
62
|
result = transform_to_double_quotes(result) if @config.use_double_quotes
|
|
46
63
|
|
|
64
|
+
print_version_updates if @config.force_update && !@version_updates.empty?
|
|
65
|
+
|
|
47
66
|
result.join("\n")
|
|
48
67
|
end
|
|
49
68
|
|
|
50
69
|
private
|
|
51
70
|
|
|
71
|
+
def extract_ruby_line(content)
|
|
72
|
+
lines = content.split("\n")
|
|
73
|
+
ruby_line = lines.find { |line| line.strip.start_with?('ruby') }
|
|
74
|
+
ruby_line&.strip
|
|
75
|
+
end
|
|
76
|
+
|
|
52
77
|
def transform_to_double_quotes(gem_file_content)
|
|
53
78
|
return gem_file_content unless gem_file_content.is_a?(Array) || gem_file_content.is_a?(String)
|
|
54
79
|
|
|
@@ -100,6 +125,43 @@ module GemSorter
|
|
|
100
125
|
end
|
|
101
126
|
end
|
|
102
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
|
+
|
|
103
165
|
def remove_versions(gems)
|
|
104
166
|
gems.each do |gem_block|
|
|
105
167
|
gem_name = extract_gem_name(gem_block[:gem_line])
|
|
@@ -147,11 +209,14 @@ module GemSorter
|
|
|
147
209
|
source_line = lines.shift
|
|
148
210
|
|
|
149
211
|
gems = []
|
|
212
|
+
ruby_line = nil
|
|
150
213
|
current_comments = []
|
|
151
214
|
|
|
152
215
|
lines.each do |line|
|
|
153
216
|
if line.start_with?('#')
|
|
154
217
|
current_comments << line
|
|
218
|
+
elsif line.start_with?('ruby')
|
|
219
|
+
ruby_line = line
|
|
155
220
|
elsif line.start_with?('gem')
|
|
156
221
|
gems << {
|
|
157
222
|
comments: current_comments,
|
|
@@ -161,7 +226,7 @@ module GemSorter
|
|
|
161
226
|
end
|
|
162
227
|
end
|
|
163
228
|
|
|
164
|
-
[source_line, gems]
|
|
229
|
+
[source_line, gems, ruby_line]
|
|
165
230
|
end
|
|
166
231
|
|
|
167
232
|
def process_group_section(section)
|
|
@@ -215,7 +280,7 @@ module GemSorter
|
|
|
215
280
|
return get_summary(gem_name, true) unless remote
|
|
216
281
|
nil
|
|
217
282
|
end
|
|
218
|
-
rescue StandardError
|
|
283
|
+
rescue StandardError
|
|
219
284
|
nil
|
|
220
285
|
end
|
|
221
286
|
|
|
@@ -224,11 +289,18 @@ module GemSorter
|
|
|
224
289
|
url = URI(version ? "#{base_url}/versions/#{version.strip}" : base_url)
|
|
225
290
|
|
|
226
291
|
begin
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
292
|
+
http = Net::HTTP.new(url.host, url.port)
|
|
293
|
+
http.use_ssl = true
|
|
294
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
295
|
+
|
|
296
|
+
request = Net::HTTP::Get.new(url)
|
|
297
|
+
response = http.request(request)
|
|
298
|
+
|
|
299
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
300
|
+
raise "Error: Could not fetch gem information from RubyGems for #{gem_name} version #{version}. Status: #{response.code}"
|
|
230
301
|
end
|
|
231
|
-
|
|
302
|
+
|
|
303
|
+
match = response.body.match(/<input[^>]*id=["']gemfile_text["'][^>]*value=["']([^"']+)["']/)
|
|
232
304
|
|
|
233
305
|
if match
|
|
234
306
|
CGI.unescapeHTML(match[1])
|
|
@@ -268,5 +340,51 @@ module GemSorter
|
|
|
268
340
|
versions
|
|
269
341
|
end
|
|
270
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
|
+
|
|
271
389
|
end
|
|
272
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?
|
data/lib/tasks/gem_sorter.rake
CHANGED
|
@@ -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.
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Renan Garcia
|
|
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
71
|
version: '0'
|
|
72
72
|
requirements: []
|
|
73
|
-
rubygems_version: 3.6.
|
|
73
|
+
rubygems_version: 3.6.8
|
|
74
74
|
specification_version: 4
|
|
75
75
|
summary: Sort gems in the Gemfile alphabetically
|
|
76
76
|
test_files: []
|