rebundler 0.1.3 → 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 +4 -4
- data/README.md +1 -1
- data/exe/rebundle +23 -2
- data/lib/bundler/rebundle.rb +10 -1
- data/lib/rebundler/gem_fetcher.rb +41 -0
- data/lib/rebundler/gem_set.rb +29 -0
- data/lib/rebundler/parser.rb +16 -133
- data/lib/rebundler/serializer.rb +41 -0
- data/lib/rebundler/version.rb +1 -1
- data/lib/rebundler/visitor.rb +33 -0
- data/lib/rebundler/writer.rb +58 -0
- data/lib/rebundler.rb +7 -5
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b98128fc72f25553bf3989f1cda39f09d0b38553185bbb9bd6e92a3fe4646cc8
|
|
4
|
+
data.tar.gz: 580694dd7a91592f95f1c32173e625f1a17c6c7dfc9bfc1c708bc565e422f4fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c83d1b995968f668a96b656036c9ba19f646bf3af2ee32611867ba820894acdfbead0b9662e60f1db3d08e1a8cef8476283cf3be855aefed921b7bf00e15d5d9
|
|
7
|
+
data.tar.gz: a4f681d93564b7111de675f8b576f62b3837fe0f2704f75cfa96d4a0ff7a0b106e726c09a26e7a8b8744a44f2ba24200a95be42249a8987f991583c1bf98c257
|
data/README.md
CHANGED
data/exe/rebundle
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
require_relative "../lib/rebundler"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# Parse command line arguments
|
|
7
|
+
ci_mode = ARGV.include?("--ci")
|
|
8
|
+
file = ARGV.reject { |arg| arg.start_with?("--") }[0] || (Dir.pwd + "/Gemfile")
|
|
7
9
|
|
|
8
10
|
puts "Reordering and annotating Gemfile..."
|
|
9
11
|
|
|
@@ -12,7 +14,26 @@ begin
|
|
|
12
14
|
# having to hit rubygems.org
|
|
13
15
|
Bundler.setup
|
|
14
16
|
parser = Rebundler::Parser.new(file)
|
|
15
|
-
|
|
17
|
+
new_content = parser.parse_and_write!
|
|
18
|
+
|
|
19
|
+
if ci_mode
|
|
20
|
+
# In CI mode, compare the new content with the existing file
|
|
21
|
+
current_content = File.read(file)
|
|
22
|
+
|
|
23
|
+
if new_content == current_content
|
|
24
|
+
puts "✓ Gemfile is already properly formatted"
|
|
25
|
+
exit 0
|
|
26
|
+
else
|
|
27
|
+
puts "✗ Gemfile is not properly formatted"
|
|
28
|
+
puts "Run 'rebundle' to fix formatting issues"
|
|
29
|
+
exit 1
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
# In normal mode, write the new content to the file
|
|
33
|
+
File.write(file, new_content)
|
|
34
|
+
puts "✓ Gemfile has been reordered and annotated"
|
|
35
|
+
end
|
|
16
36
|
rescue StandardError => e
|
|
17
37
|
puts "Error parsing Gemfile: #{e.message}"
|
|
38
|
+
exit 1
|
|
18
39
|
end
|
data/lib/bundler/rebundle.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler"
|
|
4
|
+
require "tempfile"
|
|
4
5
|
|
|
5
6
|
module Bundler
|
|
6
7
|
class Rebundle < Bundler::Plugin::API
|
|
@@ -25,7 +26,15 @@ module Bundler
|
|
|
25
26
|
Bundler.setup
|
|
26
27
|
|
|
27
28
|
parser = ::Rebundler::Parser.new(file)
|
|
28
|
-
|
|
29
|
+
content = parser.parse_and_write!
|
|
30
|
+
|
|
31
|
+
# Use atomic write to prevent corruption if write fails
|
|
32
|
+
Tempfile.create("Gemfile", Bundler.root.to_s) do |tmp|
|
|
33
|
+
tmp.write(content)
|
|
34
|
+
tmp.flush
|
|
35
|
+
tmp.close
|
|
36
|
+
FileUtils.mv(tmp.path, file)
|
|
37
|
+
end
|
|
29
38
|
rescue StandardError => e
|
|
30
39
|
Bundler.ui.error "Error parsing Gemfile: #{e.message}"
|
|
31
40
|
raise Bundler::PluginError, e
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rebundler
|
|
4
|
+
class GemFetcher
|
|
5
|
+
class << self
|
|
6
|
+
def parse_gem(node)
|
|
7
|
+
return unless node.type == :call_node && SORTABLE_NODES.include?(node.name)
|
|
8
|
+
|
|
9
|
+
gem_name = node.arguments.child_nodes[0].content
|
|
10
|
+
|
|
11
|
+
find_gem(gem_name).merge(node:)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def find_gem(name)
|
|
17
|
+
summary = find_loaded_gem_summary(name) || find_external_gem_summary(name)
|
|
18
|
+
|
|
19
|
+
{ name:, summary: }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def find_loaded_gem_summary(name)
|
|
23
|
+
gem = Gem::Specification.find_by_name(name)
|
|
24
|
+
|
|
25
|
+
gem.summary
|
|
26
|
+
rescue Gem::MissingSpecError
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def find_external_gem_summary(name)
|
|
31
|
+
spec = Gem::SpecFetcher.fetcher.spec_for_dependency Gem::Dependency.new(name)
|
|
32
|
+
|
|
33
|
+
return unless spec
|
|
34
|
+
# SpecFetcher returns [[], []] when gem exists but has no versions available
|
|
35
|
+
return if spec == [[], []]
|
|
36
|
+
|
|
37
|
+
spec.first.first.first.summary
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rebundler
|
|
4
|
+
class GemSet
|
|
5
|
+
include Comparable
|
|
6
|
+
|
|
7
|
+
attr_reader :name, :node, :plugins, :gems, :default
|
|
8
|
+
|
|
9
|
+
def initialize(name: nil, node: nil, default: false)
|
|
10
|
+
@name = name
|
|
11
|
+
@node = node
|
|
12
|
+
@default = default
|
|
13
|
+
|
|
14
|
+
@plugins = []
|
|
15
|
+
@gems = []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def <=>(other)
|
|
19
|
+
return nil unless other.is_a?(GemSet)
|
|
20
|
+
|
|
21
|
+
# Default first, then sort by name
|
|
22
|
+
[default ? 0 : 1, name] <=> [other.default ? 0 : 1, other.name]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ==(other)
|
|
26
|
+
other.is_a?(GemSet) && other.name == name
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/rebundler/parser.rb
CHANGED
|
@@ -4,158 +4,41 @@ require "prism"
|
|
|
4
4
|
|
|
5
5
|
module Rebundler
|
|
6
6
|
class Parser
|
|
7
|
-
|
|
8
|
-
BLOCK_NODES = %i[gemspec git group path platforms ruby source].freeze
|
|
9
|
-
|
|
10
|
-
attr_reader :file, :before, :sets, :frozen_string_literal
|
|
7
|
+
attr_reader :file, :preamble_nodes, :gem_sets, :frozen_string_literal
|
|
11
8
|
|
|
12
9
|
def initialize(file)
|
|
13
10
|
@file = file
|
|
14
11
|
@frozen_string_literal = false
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
{ name: "", node: nil, plugin: [], gem: [] } # all gems outside a specific block (group, source, etc) will end up here
|
|
18
|
-
]
|
|
12
|
+
@preamble_nodes = []
|
|
13
|
+
@gem_sets = [GemSet.new(default: true)] # all gems outside a specific block (group, source, etc) will end up here
|
|
19
14
|
end
|
|
20
15
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
buffer = []
|
|
25
|
-
|
|
26
|
-
buffer << "# frozen_string_literal: true" if frozen_string_literal
|
|
27
|
-
|
|
28
|
-
before.each do |node|
|
|
29
|
-
buffer << node_to_s(node)
|
|
16
|
+
def build_set(name:, node: nil)
|
|
17
|
+
GemSet.new(name:, node:).tap do |set|
|
|
18
|
+
@gem_sets << set
|
|
30
19
|
end
|
|
31
|
-
|
|
32
|
-
sets.sort_by { _1[:name] }.each do |set|
|
|
33
|
-
set_node = set[:node]
|
|
34
|
-
set_buffer = []
|
|
35
|
-
|
|
36
|
-
set_buffer << [node_to_s(set_node), set_node.block.opening].compact.join(" ") if set_node
|
|
37
|
-
|
|
38
|
-
set_buffer << SORTABLE_NODES.map do |node_type|
|
|
39
|
-
nodes = set[node_type].sort_by { _1[:name].tr("-_", "").downcase }
|
|
40
|
-
|
|
41
|
-
nodes.map do |gem|
|
|
42
|
-
line = +""
|
|
43
|
-
line << " " if set_node
|
|
44
|
-
line << node_to_s(gem[:node])
|
|
45
|
-
line << " # #{gem[:summary]}" if gem[:summary]
|
|
46
|
-
|
|
47
|
-
line
|
|
48
|
-
end.join("\n")
|
|
49
|
-
end.reject(&:empty?).join("\n\n")
|
|
50
|
-
|
|
51
|
-
set_buffer << set_node.block.closing if set_node&.block
|
|
52
|
-
|
|
53
|
-
buffer << set_buffer.join("\n")
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
buffer.reject(&:empty?).join("\n\n") + "\n"
|
|
57
20
|
end
|
|
58
21
|
|
|
59
|
-
private
|
|
60
|
-
|
|
61
22
|
def parse!
|
|
23
|
+
return if @parsed
|
|
24
|
+
|
|
62
25
|
parsed = Prism.parse(File.read(file))
|
|
63
26
|
|
|
64
27
|
@frozen_string_literal = parsed.magic_comments.map(&:key).include?("frozen_string_literal")
|
|
65
28
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
when :call_node
|
|
69
|
-
case node.name
|
|
70
|
-
when *SORTABLE_NODES
|
|
71
|
-
@sets[0][node.name] << parse_gem(node)
|
|
72
|
-
when *BLOCK_NODES
|
|
73
|
-
if node.block
|
|
74
|
-
children = node.block.body.compact_child_nodes
|
|
75
|
-
name = node_to_s(node.arguments)
|
|
76
|
-
|
|
77
|
-
set = @sets.find { |set| set[:name] == name } || { name:, node:, plugin: [], gem: [] }
|
|
78
|
-
|
|
79
|
-
children.each do |child_node|
|
|
80
|
-
parsed_node = parse_gem(child_node)
|
|
81
|
-
|
|
82
|
-
set[child_node.name] << parsed_node if parsed_node
|
|
83
|
-
end
|
|
29
|
+
visitor = Visitor.new(self)
|
|
30
|
+
parsed.value.accept(visitor)
|
|
84
31
|
|
|
85
|
-
|
|
86
|
-
else
|
|
87
|
-
@before << node
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def find_gem(name)
|
|
95
|
-
summary = find_loaded_gem_summary(name) || find_external_gem_summary(name)
|
|
96
|
-
|
|
97
|
-
{ name:, summary: }
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def find_loaded_gem_summary(name)
|
|
101
|
-
gem = Gem::Specification.find_by_name(name)
|
|
102
|
-
|
|
103
|
-
gem.summary
|
|
104
|
-
rescue Gem::MissingSpecError
|
|
105
|
-
nil
|
|
32
|
+
@parsed = true
|
|
106
33
|
end
|
|
107
34
|
|
|
108
|
-
def
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return unless spec
|
|
112
|
-
return if spec == [[], []]
|
|
113
|
-
|
|
114
|
-
spec.first.first.first.summary
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def node_to_s(node)
|
|
118
|
-
return if node.nil?
|
|
119
|
-
|
|
120
|
-
case node.type
|
|
121
|
-
when :call_node
|
|
122
|
-
[node.name, node_to_s(node.arguments)].compact.join(" ")
|
|
123
|
-
when :keyword_hash_node
|
|
124
|
-
node.elements.map do |element|
|
|
125
|
-
key = node_to_s(element.key)
|
|
126
|
-
value = node_to_s(element.value)
|
|
127
|
-
|
|
128
|
-
"#{key} #{value}"
|
|
129
|
-
end
|
|
130
|
-
when :symbol_node
|
|
131
|
-
"#{node.opening}#{node.value}#{node.closing}"
|
|
132
|
-
when :string_node
|
|
133
|
-
"#{node.opening}#{node.content}#{node.closing}"
|
|
134
|
-
when :array_node
|
|
135
|
-
separator = node.opening == "[" ? ", " : " "
|
|
136
|
-
|
|
137
|
-
node.opening + node.elements.map do |element|
|
|
138
|
-
node_to_s(element)
|
|
139
|
-
end.join(separator) + node.closing
|
|
140
|
-
when :true_node
|
|
141
|
-
"true"
|
|
142
|
-
when :false_node
|
|
143
|
-
"false"
|
|
144
|
-
when :arguments_node
|
|
145
|
-
return if node.child_nodes.empty?
|
|
146
|
-
|
|
147
|
-
node.child_nodes.map { node_to_s(_1) }.join(", ")
|
|
148
|
-
else
|
|
149
|
-
raise NotImplementedError, "Unknown node type: #{node.type}"
|
|
150
|
-
end
|
|
35
|
+
def parse_and_write!
|
|
36
|
+
parse!
|
|
37
|
+
Writer.new(self).write!
|
|
151
38
|
end
|
|
152
39
|
|
|
153
|
-
def
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
gem_name = node.arguments.child_nodes[0].content
|
|
157
|
-
|
|
158
|
-
find_gem(gem_name).merge(node:)
|
|
40
|
+
def find_or_build_set(name:, node: nil)
|
|
41
|
+
gem_sets.find { |set| set.name == name } || build_set(name:, node:)
|
|
159
42
|
end
|
|
160
43
|
end
|
|
161
44
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rebundler
|
|
4
|
+
class Serializer
|
|
5
|
+
def self.node_to_s(node)
|
|
6
|
+
return if node.nil?
|
|
7
|
+
|
|
8
|
+
case node.type
|
|
9
|
+
when :call_node
|
|
10
|
+
[node.name, node_to_s(node.arguments)].compact.join(" ")
|
|
11
|
+
when :keyword_hash_node
|
|
12
|
+
node.elements.map do |element|
|
|
13
|
+
key = node_to_s(element.key)
|
|
14
|
+
value = node_to_s(element.value)
|
|
15
|
+
|
|
16
|
+
"#{key} #{value}"
|
|
17
|
+
end
|
|
18
|
+
when :symbol_node
|
|
19
|
+
"#{node.opening}#{node.value}#{node.closing}"
|
|
20
|
+
when :string_node
|
|
21
|
+
"#{node.opening}#{node.content}#{node.closing}"
|
|
22
|
+
when :array_node
|
|
23
|
+
separator = node.opening == "[" ? ", " : " "
|
|
24
|
+
|
|
25
|
+
node.opening + node.elements.map do |element|
|
|
26
|
+
node_to_s(element)
|
|
27
|
+
end.join(separator) + node.closing
|
|
28
|
+
when :true_node
|
|
29
|
+
"true"
|
|
30
|
+
when :false_node
|
|
31
|
+
"false"
|
|
32
|
+
when :arguments_node
|
|
33
|
+
return if node.child_nodes.empty?
|
|
34
|
+
|
|
35
|
+
node.child_nodes.map { |child| node_to_s(child) }.join(", ")
|
|
36
|
+
else
|
|
37
|
+
raise Rebundler::Error, "Unsupported node type: #{node.type}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/rebundler/version.rb
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rebundler
|
|
4
|
+
class Visitor < Prism::Visitor
|
|
5
|
+
def initialize(parser)
|
|
6
|
+
super()
|
|
7
|
+
@parser = parser
|
|
8
|
+
@current_set = @parser.gem_sets.find(&:default)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def visit_call_node(node)
|
|
12
|
+
case node.name
|
|
13
|
+
when :plugin
|
|
14
|
+
parsed_gem = GemFetcher.parse_gem(node)
|
|
15
|
+
@current_set.plugins << parsed_gem if parsed_gem
|
|
16
|
+
when :gem
|
|
17
|
+
parsed_gem = GemFetcher.parse_gem(node)
|
|
18
|
+
@current_set.gems << parsed_gem if parsed_gem
|
|
19
|
+
when *BLOCK_NODES
|
|
20
|
+
if node.block
|
|
21
|
+
name = Serializer.node_to_s(node)
|
|
22
|
+
|
|
23
|
+
previous_set = @current_set
|
|
24
|
+
@current_set = @parser.find_or_build_set(name:, node:)
|
|
25
|
+
node.block.body&.accept(self)
|
|
26
|
+
@current_set = previous_set
|
|
27
|
+
else
|
|
28
|
+
@parser.preamble_nodes << node
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rebundler
|
|
4
|
+
class Writer
|
|
5
|
+
def initialize(parser)
|
|
6
|
+
@parser = parser
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def write!
|
|
10
|
+
buffer = []
|
|
11
|
+
|
|
12
|
+
buffer << "# frozen_string_literal: true" if frozen_string_literal
|
|
13
|
+
|
|
14
|
+
preamble_nodes.each do |node|
|
|
15
|
+
buffer << Serializer.node_to_s(node)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
gem_sets.sort.each do |set|
|
|
19
|
+
set_buffer = []
|
|
20
|
+
|
|
21
|
+
set_buffer << [Serializer.node_to_s(set.node), set.node.block.opening].compact.join(" ") if set.node
|
|
22
|
+
|
|
23
|
+
set_buffer << [set.plugins, set.gems].map do |nodes|
|
|
24
|
+
sorted = nodes.sort_by { |node| node[:name].tr("-_", "").downcase }
|
|
25
|
+
|
|
26
|
+
sorted.map do |gem|
|
|
27
|
+
line = +""
|
|
28
|
+
line << " " if set.node
|
|
29
|
+
line << Serializer.node_to_s(gem[:node])
|
|
30
|
+
line << " # #{gem[:summary]}" if gem[:summary]
|
|
31
|
+
|
|
32
|
+
line
|
|
33
|
+
end.join("\n")
|
|
34
|
+
end.reject(&:empty?).join("\n\n")
|
|
35
|
+
|
|
36
|
+
set_buffer << set.node.block.closing if set.node&.block
|
|
37
|
+
|
|
38
|
+
buffer << set_buffer.join("\n")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
buffer.reject(&:empty?).join("\n\n") + "\n"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def preamble_nodes
|
|
47
|
+
@parser.preamble_nodes
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def gem_sets
|
|
51
|
+
@parser.gem_sets
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def frozen_string_literal
|
|
55
|
+
@parser.frozen_string_literal
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/rebundler.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
require "zeitwerk"
|
|
4
|
+
loader = Zeitwerk::Loader.for_gem
|
|
5
|
+
loader.ignore("#{__dir__}/bundler")
|
|
6
|
+
loader.setup
|
|
7
7
|
|
|
8
8
|
module Rebundler
|
|
9
9
|
class Error < StandardError; end
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
SORTABLE_NODES = %i[plugin gem].freeze
|
|
12
|
+
BLOCK_NODES = %i[gemspec git group path platforms ruby source].freeze
|
|
11
13
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rebundler
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dennis Paagman
|
|
@@ -25,8 +25,13 @@ files:
|
|
|
25
25
|
- lib/bundler/rebundle.rb
|
|
26
26
|
- lib/rebundler.rb
|
|
27
27
|
- lib/rebundler/Rakefile
|
|
28
|
+
- lib/rebundler/gem_fetcher.rb
|
|
29
|
+
- lib/rebundler/gem_set.rb
|
|
28
30
|
- lib/rebundler/parser.rb
|
|
31
|
+
- lib/rebundler/serializer.rb
|
|
29
32
|
- lib/rebundler/version.rb
|
|
33
|
+
- lib/rebundler/visitor.rb
|
|
34
|
+
- lib/rebundler/writer.rb
|
|
30
35
|
- plugins.rb
|
|
31
36
|
homepage: https://github.com/dennispaagman/rebundler
|
|
32
37
|
licenses:
|
|
@@ -50,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
50
55
|
- !ruby/object:Gem::Version
|
|
51
56
|
version: '0'
|
|
52
57
|
requirements: []
|
|
53
|
-
rubygems_version: 3.6.
|
|
58
|
+
rubygems_version: 3.6.9
|
|
54
59
|
specification_version: 4
|
|
55
60
|
summary: Rebundler makes your Gemfile look good.
|
|
56
61
|
test_files: []
|