gem_sorter 0.1.1 → 0.2.0

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: d91ddab7a3117bdca0c33158d6b6cb836e1eb75126ef8e101335bc0ddb55daa4
4
- data.tar.gz: 0b059c69f84a26e5f55b603777e73a1941b3be1e0bc64f7b247b213ce27fed04
3
+ metadata.gz: 9a7e010153615999089999a370d116a6404dbdaf855bcb6257c801279baec90b
4
+ data.tar.gz: 23c131930d94049ad3c90f556fd2e8fc3a7b2c74b3a7eadbed026fb4ef08b333
5
5
  SHA512:
6
- metadata.gz: 70d59f3a8cd42b31378ba99433db9e638aca693ad0c4cf83143f12aa4e381bdd6e34c1e6067a56633d0fc20282993bc35e4c0b3c1c36ffeaf8d83514b2927b26
7
- data.tar.gz: f64d158253309097b7b5cf9b4421414ea4d69635f27e8e071a67ddc8b084a7f751f47f0973cbbec6e1b0ff9fb71e90f6bb2c3dad8461cb61faa649b189ab1d64
6
+ metadata.gz: e0f45801b449beff02390ae7227ef679148214cbf79a96068ef17fa7d668eff14bc7fa64d78309fbeb02e32e9677813adcb96a3371ca2a2d54690b91a26c9022
7
+ data.tar.gz: 29529cd23267c390d2bafe645a10d612d6f22aca97706157501091952f5266ba3ec735e52f47bdab733318ce41ada18cb28e81230efe091e18702d1f9e8bb59e
data/README.md CHANGED
@@ -7,6 +7,7 @@ GemSorter is a simple gem to sort the contents of your Gemfile alphabetically wh
7
7
  * Preserves comments and their association with gems.
8
8
  * Maintains group structure in the Gemfile.
9
9
  * Optionally creates a backup of the original Gemfile.
10
+ * Update the comments of the gems based on their descriptions.
10
11
 
11
12
  ## Installation
12
13
  Add the gem to your project's `Gemfile`:
@@ -24,14 +25,16 @@ rake gemfile:sort
24
25
 
25
26
  ### Options
26
27
  * `backup`: Pass `true` to create a backup of your Gemfile as `Gemfile.old` before sorting.
28
+ * `update_comments`: Pass `true` to update the comments of the gems based on their descriptions.
29
+ * `update_versions`: Pass `true` to update the versions of the gems based on the lockfile.
27
30
 
28
31
  Example:
29
32
 
30
33
  ```bash
31
- rake gemfile:sort[true]
34
+ rake gemfile:sort[true,true,true]
32
35
  ```
33
36
 
34
- This will sort your Gemfile and create a backup.
37
+ This will sort your Gemfile, create a backup, and update comments and versions.
35
38
 
36
39
  ## Example
37
40
  ### Input Gemfile
@@ -40,12 +43,11 @@ source "https://rubygems.org"
40
43
 
41
44
  # Framework
42
45
  gem "rails"
43
- # Web server
44
- gem "puma"
46
+ gem "puma", "~> 5.3"
45
47
 
46
48
  group :development do
47
- gem "pry"
48
49
  gem "dotenv-rails"
50
+ gem "pry"
49
51
  end
50
52
  ```
51
53
 
@@ -53,13 +55,15 @@ end
53
55
  ```ruby
54
56
  source "https://rubygems.org"
55
57
 
56
- # Web server
57
- gem "puma"
58
- # Framework
59
- gem "rails"
58
+ # A Ruby/Rack web server built for parallelism.
59
+ gem "puma", "~> 5.3"
60
+ # Full-stack web application framework.
61
+ gem "rails", "~> 8.0", ">= 8.0.1"
60
62
 
61
63
  group :development do
62
- gem "dotenv-rails"
64
+ # Autoload dotenv in Rails.
65
+ gem 'dotenv-rails', '~> 3.1', '>= 3.1.7'
66
+ # A runtime developer console and IRB alternative with powerful introspection capabilities.
63
67
  gem "pry"
64
68
  end
65
69
  ```
@@ -1,3 +1,3 @@
1
1
  module GemSorter
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/gem_sorter.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # lib/gem_sorter.rb
2
+ require 'net/http'
3
+ require 'cgi'
2
4
 
3
5
  load File.expand_path('tasks/gem_sorter.rake', __dir__) if defined?(Rake)
4
6
 
@@ -7,15 +9,19 @@ module GemSorter
7
9
  def initialize(filepath)
8
10
  @filepath = filepath
9
11
  @content = File.read(filepath)
12
+ @versions = nil
10
13
  end
11
14
 
12
- def sort
15
+ def sort(update_comments = false, update_versions = false)
13
16
  parts = @content.split(/^group/)
14
17
  main_section = parts.shift
15
18
  group_sections = parts
16
19
 
17
20
  source_line, gems = process_main_section(main_section)
18
21
 
22
+ update_gem_summaries(gems) if update_comments
23
+ update_version_text(gems) if update_versions
24
+
19
25
  sorted_gems = sort_gem_blocks(gems)
20
26
 
21
27
  result = []
@@ -26,6 +32,8 @@ module GemSorter
26
32
 
27
33
  group_sections.each do |section|
28
34
  group_gems = process_group_section(section)
35
+ update_gem_summaries(group_gems) if update_comments
36
+ update_version_text(group_gems) if update_versions
29
37
  result << "group#{section.split("\n").first}"
30
38
  result.concat(sort_gem_blocks(group_gems).map { |line| " #{line}" })
31
39
  result << 'end'
@@ -37,6 +45,40 @@ module GemSorter
37
45
 
38
46
  private
39
47
 
48
+ def update_version_text(gems)
49
+ @versions ||= fetch_versions_from_lockfile("#{@filepath}.lock")
50
+ gems.each do |gem_block|
51
+ gem_name = gem_block[:gem_line].match(/gem\s*"([^"]+)"/)[1]
52
+ version = @versions[gem_name]
53
+ extra_params = extract_params(gem_block[:gem_line])
54
+ base = version ? "#{fetch_gemfile_text(gem_name, version, gem_block[:gem_line])}" : gem_block[:gem_line]
55
+ return base if base == gem_block[:gem_line]
56
+
57
+ gem_block[:gem_line] = [base, extra_params].select { |value| !value.nil? && !value.empty? }.join(',')
58
+ end
59
+ end
60
+
61
+ def extract_params(gem_line)
62
+ return nil unless gem_line =~ /gem\s*"([^"]+)"/
63
+
64
+ if gem_line =~ /gem\s*"[^"]*"\s*,\s*(.*)/
65
+ additional_params = $1.strip
66
+ return nil if additional_params.empty?
67
+ params_with_colon = additional_params.scan(/(\w+:\s*[^,]+)/).flatten
68
+ return params_with_colon.join(', ') unless params_with_colon.empty?
69
+ end
70
+ nil
71
+ end
72
+
73
+ def update_gem_summaries(gems)
74
+ gems.each do |gem_block|
75
+ gem_name = gem_block[:gem_line].match(/gem\s*"([^"]+)"/)[1]
76
+ if summary = get_summary(gem_name, false)
77
+ gem_block[:comments] = ["# #{summary}"]
78
+ end
79
+ end
80
+ end
81
+
40
82
  def process_main_section(section)
41
83
  lines = section.split("\n").map(&:strip).reject(&:empty?)
42
84
  source_line = lines.shift
@@ -83,7 +125,12 @@ module GemSorter
83
125
 
84
126
  def sort_gem_blocks(gems)
85
127
  sorted = gems.sort_by do |gem_block|
86
- gem_block[:gem_line].match(/gem\s*"([^"]+)"/)[1].downcase
128
+ match_data = gem_block[:gem_line].match(/gem\s*['"]([^'"]+)['"]/)
129
+ if match_data
130
+ match_data[1].downcase
131
+ else
132
+ ''
133
+ end
87
134
  end
88
135
 
89
136
  result = []
@@ -94,5 +141,69 @@ module GemSorter
94
141
 
95
142
  result
96
143
  end
144
+
145
+ def get_summary(gem_name, remote)
146
+ source = remote ? "-r" : "-l"
147
+ output = `gem list -d #{source} -e #{gem_name}`
148
+ if output.include?(gem_name)
149
+ summary = output.split("\n").last.strip
150
+ summary
151
+ else
152
+ return get_summary(gem_name, true) unless remote
153
+ nil
154
+ end
155
+ rescue StandardError => e
156
+ nil
157
+ end
158
+
159
+ def fetch_gemfile_text(gem_name, version, original)
160
+ base_url = "https://rubygems.org/gems/#{gem_name.strip}"
161
+ url = URI(version ? "#{base_url}/versions/#{version.strip}" : base_url)
162
+
163
+ begin
164
+ response = Net::HTTP.get(url)
165
+ unless response
166
+ raise "Error: Could not fetch gem information from RubyGems for #{gem_name} version #{version}."
167
+ end
168
+ match = response.match(/<input[^>]*id=["']gemfile_text["'][^>]*value=["']([^"']+)["']/)
169
+
170
+ if match
171
+ CGI.unescapeHTML(match[1])
172
+ else
173
+ raise "Error: Could not extract Gemfile text for #{gem_name} version #{version}."
174
+ end
175
+
176
+ rescue => e
177
+ puts e.message
178
+
179
+ original
180
+ end
181
+ end
182
+
183
+ def fetch_versions_from_lockfile(lockfile_path)
184
+ return {} unless File.exist?(lockfile_path)
185
+
186
+ versions = {}
187
+ inside_specs = false
188
+
189
+ File.readlines(lockfile_path).each do |line|
190
+ line.strip!
191
+
192
+ if line == "specs:"
193
+ inside_specs = true
194
+ next
195
+ end
196
+
197
+ inside_specs = false if inside_specs && line.empty?
198
+
199
+ if inside_specs && line =~ /^([^\s]+)\s\(([^)]+)\)$/
200
+ gem_name, gem_version = $1, $2
201
+ gem_version = gem_version.match(/(\d+\.\d+\.\d+)/)[0] if gem_version =~ /(\d+\.\d+\.\d+)/
202
+ versions[gem_name] = gem_version
203
+ end
204
+ end
205
+ versions
206
+ end
207
+
97
208
  end
98
- end
209
+ end
@@ -1,9 +1,14 @@
1
1
  require 'gem_sorter'
2
2
 
3
3
  namespace :gemfile do
4
- desc 'Sort gems in Gemfile alphabetically'
5
- task :sort, [:backup] do |_t, args|
6
- args.with_defaults(backup: 'false')
4
+ desc 'Sort gems in Gemfile alphabetically. Options: [backup=true|false] [update_comments=true|false] [update_versions=true|false]'
5
+ task :sort, [:backup, :update_comments, :update_versions] do |_t, args|
6
+ args.with_defaults(
7
+ backup: 'false',
8
+ update_comments: 'false',
9
+ update_versions: 'false'
10
+ )
11
+
7
12
  gemfile_path = 'Gemfile'
8
13
 
9
14
  if File.exist?(gemfile_path)
@@ -13,7 +18,7 @@ namespace :gemfile do
13
18
  end
14
19
 
15
20
  sorter = ::GemSorter::Sorter.new(gemfile_path)
16
- sorted_content = sorter.sort
21
+ sorted_content = sorter.sort(args.update_comments.downcase == 'true', args.update_versions.downcase == 'true')
17
22
 
18
23
  File.write(gemfile_path, sorted_content)
19
24
 
@@ -22,4 +27,4 @@ namespace :gemfile do
22
27
  puts 'Error: Gemfile not found in current directory'
23
28
  end
24
29
  end
25
- end
30
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_sorter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renan Garcia
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-02 00:00:00.000000000 Z
10
+ date: 2025-01-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rake