gem_sorter 0.5.2 → 0.5.6
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 +17 -1
- data/lib/gem_sorter/railtie.rb +13 -0
- data/lib/gem_sorter/version.rb +1 -1
- data/lib/gem_sorter.rb +106 -3
- data/lib/task_config.rb +8 -0
- data/lib/tasks/gem_sorter.rake +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c19d0f251f29c0467ca815ced49892bd916c2a9090057f5b0303cb5a5c662b95
|
|
4
|
+
data.tar.gz: 90efd7fd7a67541856a5889cdc3fded9955e8e3006ad4639e3a631c2cf33ddaf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 30c2df4815a3232b8c476dfddc74edad9f90537c0d36ddcbb04143693e5c4033cd3ae445b0cb36c5a9edffb692a33fe51adb9f17a512e1cae40edc332198873c
|
|
7
|
+
data.tar.gz: bea536e4ea2bf06e0ebdfebad84ee7bfe4d256cd94af23f5cc52559aeebb811d8bbe0a033fde91d9c4efdf6a111f0cc159ef163f7dd5ce8de505e6545a263399
|
data/README.md
CHANGED
|
@@ -36,7 +36,20 @@ Once installed, you can use the provided Rake task to sort your Gemfile:
|
|
|
36
36
|
rake gemfile:sort
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
### Inside a Rails application
|
|
40
|
+
When you add `gem_sorter` to a Rails app's `Gemfile`, the `gemfile:sort` task is
|
|
41
|
+
registered automatically through a Railtie, using Rails' own task-loading
|
|
42
|
+
pipeline. This means the task is reliably available under both `bin/rails` and
|
|
43
|
+
`bin/rake`, and the gem no longer defines tasks during application boot:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bin/rails gemfile:sort
|
|
47
|
+
# or
|
|
48
|
+
bin/rake gemfile:sort
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Standalone (global)
|
|
52
|
+
You can also run gem_sorter globally, without adding it to your Gemfile:
|
|
40
53
|
|
|
41
54
|
```bash
|
|
42
55
|
rake -r gem_sorter gemfile:sort
|
|
@@ -46,6 +59,7 @@ rake -r gem_sorter gemfile:sort
|
|
|
46
59
|
* `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
|
|
47
60
|
* `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
|
|
48
61
|
* `update_versions`: Pass `true` to update the versions of the gems based on the lockfile.
|
|
62
|
+
* `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
63
|
* `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
|
|
50
64
|
* `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
65
|
|
|
@@ -61,6 +75,7 @@ Create a file in the root of your project called `gem_sorter.yml`
|
|
|
61
75
|
* `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
|
|
62
76
|
* `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
|
|
63
77
|
* `update_versions`: Pass `true` to update the versions of the gems based on the lockfile.
|
|
78
|
+
* `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
79
|
* `use_double_quotes`: Pass `true` to convert single quotes to double quotes in gem declarations.
|
|
65
80
|
* `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
81
|
* `ignore_gems`: Pass an array of GEMs you want to ignore versions and comments
|
|
@@ -73,6 +88,7 @@ Example:
|
|
|
73
88
|
backup: true
|
|
74
89
|
update_comments: true
|
|
75
90
|
update_versions: false
|
|
91
|
+
force_update: false
|
|
76
92
|
use_double_quotes: true
|
|
77
93
|
remove_versions: true
|
|
78
94
|
ignore_gems:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'rails/railtie'
|
|
2
|
+
|
|
3
|
+
module GemSorter
|
|
4
|
+
# Registers the gem's rake tasks through the Rails task-loading pipeline.
|
|
5
|
+
# Using a Railtie ensures the tasks are available reliably inside a Rails
|
|
6
|
+
# application (under both `bin/rails` and `bin/rake`) without defining tasks
|
|
7
|
+
# during `Bundler.require`, which is order-dependent and could break boot.
|
|
8
|
+
class Railtie < Rails::Railtie
|
|
9
|
+
rake_tasks do
|
|
10
|
+
load File.expand_path('../tasks/gem_sorter.rake', __dir__)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/gem_sorter/version.rb
CHANGED
data/lib/gem_sorter.rb
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
require 'net/http'
|
|
3
3
|
require 'cgi'
|
|
4
4
|
require 'openssl'
|
|
5
|
+
require 'json'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
# Inside a Rails app, let the Railtie register the rake tasks through Rails'
|
|
8
|
+
# own task-loading pipeline (reliable and not tied to require order). When used
|
|
9
|
+
# standalone (e.g. `rake -r gem_sorter gemfile:sort`), load the tasks directly.
|
|
10
|
+
if defined?(Rails::Railtie)
|
|
11
|
+
require 'gem_sorter/railtie'
|
|
12
|
+
elsif defined?(Rake)
|
|
13
|
+
load File.expand_path('tasks/gem_sorter.rake', __dir__)
|
|
14
|
+
end
|
|
7
15
|
|
|
8
16
|
module GemSorter
|
|
9
17
|
class Sorter
|
|
@@ -12,6 +20,7 @@ module GemSorter
|
|
|
12
20
|
@filepath = task_config.gemfile_path
|
|
13
21
|
@content = File.read(task_config.gemfile_path)
|
|
14
22
|
@versions = nil
|
|
23
|
+
@version_updates = []
|
|
15
24
|
end
|
|
16
25
|
|
|
17
26
|
def sort
|
|
@@ -24,7 +33,11 @@ module GemSorter
|
|
|
24
33
|
source_line, gems, _ = process_main_section(main_section)
|
|
25
34
|
|
|
26
35
|
update_gem_summaries(gems) if @config.update_comments
|
|
27
|
-
|
|
36
|
+
if @config.force_update
|
|
37
|
+
force_update_versions(gems)
|
|
38
|
+
elsif @config.update_versions
|
|
39
|
+
update_version_text(gems)
|
|
40
|
+
end
|
|
28
41
|
remove_versions(gems) if @config.remove_versions
|
|
29
42
|
sorted_gems = sort_gem_blocks(gems)
|
|
30
43
|
|
|
@@ -41,7 +54,11 @@ module GemSorter
|
|
|
41
54
|
group_sections.each do |section|
|
|
42
55
|
group_gems = process_group_section(section)
|
|
43
56
|
update_gem_summaries(group_gems) if @config.update_comments
|
|
44
|
-
|
|
57
|
+
if @config.force_update
|
|
58
|
+
force_update_versions(group_gems)
|
|
59
|
+
elsif @config.update_versions
|
|
60
|
+
update_version_text(group_gems)
|
|
61
|
+
end
|
|
45
62
|
remove_versions(group_gems) if @config.remove_versions
|
|
46
63
|
result << "group#{section.split("\n").first}"
|
|
47
64
|
result.concat(sort_gem_blocks(group_gems).map { |line| " #{line}" })
|
|
@@ -51,6 +68,8 @@ module GemSorter
|
|
|
51
68
|
|
|
52
69
|
result = transform_to_double_quotes(result) if @config.use_double_quotes
|
|
53
70
|
|
|
71
|
+
print_version_updates if @config.force_update && !@version_updates.empty?
|
|
72
|
+
|
|
54
73
|
result.join("\n")
|
|
55
74
|
end
|
|
56
75
|
|
|
@@ -113,6 +132,44 @@ module GemSorter
|
|
|
113
132
|
end
|
|
114
133
|
end
|
|
115
134
|
|
|
135
|
+
def force_update_versions(gems)
|
|
136
|
+
@versions ||= fetch_versions_from_lockfile("#{@filepath}.lock")
|
|
137
|
+
|
|
138
|
+
gems.each do |gem_block|
|
|
139
|
+
gem_name = extract_gem_name(gem_block[:gem_line])
|
|
140
|
+
next if @config.ignore_gems.include?(gem_name) || @config.ignore_gem_versions.include?(gem_name)
|
|
141
|
+
|
|
142
|
+
original_line = gem_block[:gem_line]
|
|
143
|
+
latest_version = fetch_latest_version(gem_name)
|
|
144
|
+
|
|
145
|
+
next unless latest_version
|
|
146
|
+
|
|
147
|
+
extra_params = extract_params(original_line)
|
|
148
|
+
new_gemfile_text = fetch_gemfile_text(gem_name, latest_version, original_line)
|
|
149
|
+
|
|
150
|
+
next unless new_gemfile_text && new_gemfile_text != original_line
|
|
151
|
+
|
|
152
|
+
gem_block[:gem_line] = [new_gemfile_text.strip, extra_params].select { |value| !value.nil? && !value.empty? }.join(',')
|
|
153
|
+
|
|
154
|
+
next unless version_changed?(original_line, new_gemfile_text)
|
|
155
|
+
|
|
156
|
+
@version_updates << {
|
|
157
|
+
gem_name: gem_name,
|
|
158
|
+
from_version: extract_current_version(original_line) || 'no version specified',
|
|
159
|
+
to_version: latest_version
|
|
160
|
+
}
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Detects whether a gem line actually changed version between what is declared
|
|
165
|
+
# in the Gemfile and what RubyGems returns. The comparison is based purely on
|
|
166
|
+
# the version constraint, ignoring cosmetic differences (e.g. quote style), so
|
|
167
|
+
# re-running the task does not report the same update again. The lockfile is
|
|
168
|
+
# intentionally not consulted here: it stays stale until `bundle install` runs.
|
|
169
|
+
def version_changed?(original_line, new_gemfile_text)
|
|
170
|
+
extract_current_version(original_line) != extract_current_version(new_gemfile_text)
|
|
171
|
+
end
|
|
172
|
+
|
|
116
173
|
def remove_versions(gems)
|
|
117
174
|
gems.each do |gem_block|
|
|
118
175
|
gem_name = extract_gem_name(gem_block[:gem_line])
|
|
@@ -291,5 +348,51 @@ module GemSorter
|
|
|
291
348
|
versions
|
|
292
349
|
end
|
|
293
350
|
|
|
351
|
+
def fetch_latest_version(gem_name)
|
|
352
|
+
url = URI("https://rubygems.org/api/v1/gems/#{gem_name.strip}.json")
|
|
353
|
+
|
|
354
|
+
begin
|
|
355
|
+
http = Net::HTTP.new(url.host, url.port)
|
|
356
|
+
http.use_ssl = true
|
|
357
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
358
|
+
|
|
359
|
+
request = Net::HTTP::Get.new(url)
|
|
360
|
+
response = http.request(request)
|
|
361
|
+
|
|
362
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
363
|
+
return nil
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
gem_data = JSON.parse(response.body)
|
|
367
|
+
gem_data['version']
|
|
368
|
+
rescue => e
|
|
369
|
+
nil
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def extract_current_version(gem_line)
|
|
374
|
+
# Try to extract version from gem line
|
|
375
|
+
# Examples: gem "rails", "~> 7.0" or gem "rails", "7.0.0" or gem "rails", ">= 7.0", "< 8.0"
|
|
376
|
+
# Match first version string after gem name
|
|
377
|
+
version_match = gem_line.match(/gem\s+['"][^'"]+['"]\s*,\s*['"]([^'"]+)['"]/)
|
|
378
|
+
return nil unless version_match
|
|
379
|
+
|
|
380
|
+
version_string = version_match[1]
|
|
381
|
+
# Extract semantic version (x.y.z) from version string, or return the full version string
|
|
382
|
+
semantic_version = version_string.match(/(\d+\.\d+\.\d+)/)
|
|
383
|
+
semantic_version ? semantic_version[1] : version_string
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def print_version_updates
|
|
387
|
+
return if @version_updates.empty?
|
|
388
|
+
|
|
389
|
+
puts "\nThe following gems were updated:"
|
|
390
|
+
@version_updates.each do |update|
|
|
391
|
+
puts " * #{update[:gem_name]} (#{update[:from_version]} -> #{update[:to_version]})"
|
|
392
|
+
end
|
|
393
|
+
puts "\nRun `bundle install` to install the updated gems."
|
|
394
|
+
puts ""
|
|
395
|
+
end
|
|
396
|
+
|
|
294
397
|
end
|
|
295
398
|
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.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Renan Garcia
|
|
@@ -47,6 +47,7 @@ extra_rdoc_files: []
|
|
|
47
47
|
files:
|
|
48
48
|
- README.md
|
|
49
49
|
- lib/gem_sorter.rb
|
|
50
|
+
- lib/gem_sorter/railtie.rb
|
|
50
51
|
- lib/gem_sorter/version.rb
|
|
51
52
|
- lib/task_config.rb
|
|
52
53
|
- lib/tasks/gem_sorter.rake
|
|
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
70
71
|
- !ruby/object:Gem::Version
|
|
71
72
|
version: '0'
|
|
72
73
|
requirements: []
|
|
73
|
-
rubygems_version: 3.6.
|
|
74
|
+
rubygems_version: 3.6.9
|
|
74
75
|
specification_version: 4
|
|
75
76
|
summary: Sort gems in the Gemfile alphabetically
|
|
76
77
|
test_files: []
|