bundle_update_interactive 0.5.0 → 0.7.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 +6 -0
- data/lib/bundle_update_interactive/bundler_commands.rb +8 -0
- data/lib/bundle_update_interactive/cli/multi_select.rb +35 -17
- data/lib/bundle_update_interactive/cli/row.rb +4 -11
- data/lib/bundle_update_interactive/cli/table.rb +36 -4
- data/lib/bundle_update_interactive/cli.rb +20 -13
- data/lib/bundle_update_interactive/outdated_gem.rb +2 -1
- data/lib/bundle_update_interactive/report.rb +10 -41
- data/lib/bundle_update_interactive/reporter.rb +66 -0
- data/lib/bundle_update_interactive/semver_change.rb +3 -1
- data/lib/bundle_update_interactive/version.rb +1 -1
- data/lib/bundle_update_interactive.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58fa0e12f3322d018b1fcaa788dd3b8a2c3354042fe1e6ab21313d0bc0d7518b
|
4
|
+
data.tar.gz: a43866c8bad9bc0256b369cbf7e29db56c2b06293f2ae3a4a3e560ff75506e16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5325810c277c4a3f58d3308b9899c9097a2c723996e79030ccda96f79408c83734b2bcf9ae5920a1ee74f32837ebae91f4e946aa9ff08225db73bf6d06d69e91
|
7
|
+
data.tar.gz: d241d58cb408a0b6294a8b56e010b8ffa841bdbb5ccf28c794fb2db4ebcc562f7ec486742ec36720ed9522c9cf2ce1d27d8a68619fefbee59d28810b3044e7fb
|
data/README.md
CHANGED
@@ -63,6 +63,12 @@ Some gems, notably `rails`, are composed of smaller gems like `actionpack`, `act
|
|
63
63
|
|
64
64
|
Therefore, if any Rails component has a security vulnerability, `bundle update-interactive` will automatically roll up that information into a single `rails` line item, so you can select it and upgrade all of its components in one shot.
|
65
65
|
|
66
|
+
### Held back gems
|
67
|
+
|
68
|
+
When a newer version of a gem is available, but updating is not allowed due to a Gemfile requirement, `update-interactive` will report that the gem has been held back.
|
69
|
+
|
70
|
+
<img src="images/held-back.png" alt="Screenshot of rails and selenium-webdriver gems held back due to Gemfile requirements" width="717" />
|
71
|
+
|
66
72
|
### Changelogs
|
67
73
|
|
68
74
|
`bundle update-interactive` will do its best to find an appropriate changelog for each gem.
|
@@ -19,6 +19,14 @@ module BundleUpdateInteractive
|
|
19
19
|
`#{command.join(" ")}`.tap { raise "bundle lock command failed" unless Process.last_status.success? }
|
20
20
|
end
|
21
21
|
|
22
|
+
def parse_outdated(*gems)
|
23
|
+
command = ["#{bundle_bin.shellescape} outdated --parseable", *gems.flatten.map(&:shellescape)]
|
24
|
+
output = `#{command.join(" ")}`
|
25
|
+
raise "bundle outdated command failed" if output.empty? && !Process.last_status.success?
|
26
|
+
|
27
|
+
output.scan(/^(\S+) \(newest (\S+),/).to_h
|
28
|
+
end
|
29
|
+
|
22
30
|
private
|
23
31
|
|
24
32
|
def bundle_bin
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "launchy"
|
3
4
|
require "pastel"
|
4
5
|
require "tty/prompt"
|
5
6
|
require "tty/screen"
|
@@ -8,6 +9,7 @@ class BundleUpdateInteractive::CLI
|
|
8
9
|
class MultiSelect
|
9
10
|
class List < TTY::Prompt::MultiList
|
10
11
|
def initialize(prompt, **options)
|
12
|
+
@opener = options.delete(:opener)
|
11
13
|
defaults = {
|
12
14
|
cycle: true,
|
13
15
|
help_color: :itself.to_proc,
|
@@ -21,48 +23,64 @@ class BundleUpdateInteractive::CLI
|
|
21
23
|
def selected_names
|
22
24
|
""
|
23
25
|
end
|
26
|
+
|
27
|
+
# Unregister tty-prompt's default ctrl-a and ctrl-r bindings
|
28
|
+
alias select_all keyctrl_a
|
29
|
+
alias reverse_selection keyctrl_r
|
30
|
+
def keyctrl_a(*); end
|
31
|
+
def keyctrl_r(*); end
|
32
|
+
|
33
|
+
def keypress(event)
|
34
|
+
case event.value
|
35
|
+
when "k", "p" then keyup
|
36
|
+
when "j", "n" then keydown
|
37
|
+
when "a" then select_all
|
38
|
+
when "r" then reverse_selection
|
39
|
+
when "o" then opener&.call(choices[@active - 1].value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :opener
|
24
46
|
end
|
25
47
|
|
26
|
-
def self.prompt_for_gems_to_update(outdated_gems)
|
27
|
-
table = Table.
|
48
|
+
def self.prompt_for_gems_to_update(outdated_gems, prompt: nil)
|
49
|
+
table = Table.updatable(outdated_gems)
|
28
50
|
title = "#{outdated_gems.length} gems can be updated."
|
29
|
-
|
51
|
+
opener = lambda do |gem|
|
52
|
+
url = outdated_gems[gem].changelog_uri
|
53
|
+
Launchy.open(url) unless url.nil?
|
54
|
+
end
|
55
|
+
chosen = new(title: title, table: table, prompt: prompt, opener: opener).prompt
|
30
56
|
outdated_gems.slice(*chosen)
|
31
57
|
end
|
32
58
|
|
33
|
-
def initialize(title:, table:)
|
59
|
+
def initialize(title:, table:, opener: nil, prompt: nil)
|
34
60
|
@title = title
|
35
61
|
@table = table
|
36
|
-
@
|
62
|
+
@opener = opener
|
63
|
+
@tty_prompt = prompt || TTY::Prompt.new(
|
37
64
|
interrupt: lambda {
|
38
65
|
puts
|
39
66
|
exit(130)
|
40
67
|
}
|
41
68
|
)
|
42
|
-
add_keybindings
|
43
|
-
|
44
69
|
@pastel = BundleUpdateInteractive.pastel
|
45
70
|
end
|
46
71
|
|
47
72
|
def prompt
|
48
73
|
choices = table.gem_names.to_h { |name| [table.render_gem(name), name] }
|
49
|
-
tty_prompt.invoke_select(List, title, choices, help: help)
|
74
|
+
tty_prompt.invoke_select(List, title, choices, help: help, opener: opener)
|
50
75
|
end
|
51
76
|
|
52
77
|
private
|
53
78
|
|
54
|
-
attr_reader :pastel, :table, :tty_prompt, :title
|
55
|
-
|
56
|
-
def add_keybindings
|
57
|
-
tty_prompt.on(:keypress) do |event|
|
58
|
-
tty_prompt.trigger(:keyup) if %w[k p].include?(event.value)
|
59
|
-
tty_prompt.trigger(:keydown) if %w[j n].include?(event.value)
|
60
|
-
end
|
61
|
-
end
|
79
|
+
attr_reader :pastel, :table, :opener, :tty_prompt, :title
|
62
80
|
|
63
81
|
def help
|
64
82
|
[
|
65
|
-
pastel.dim("\nPress <space> to select, ↑/↓ move, <
|
83
|
+
pastel.dim("\nPress <space> to select, ↑/↓ move, <a> all, <r> reverse, <o> open url, <enter> to finish."),
|
66
84
|
"\n ",
|
67
85
|
table.render_header
|
68
86
|
].join
|
@@ -16,17 +16,6 @@ class BundleUpdateInteractive::CLI
|
|
16
16
|
@pastel = BundleUpdateInteractive.pastel
|
17
17
|
end
|
18
18
|
|
19
|
-
def to_a
|
20
|
-
[
|
21
|
-
formatted_gem_name,
|
22
|
-
formatted_current_version,
|
23
|
-
"→",
|
24
|
-
formatted_updated_version,
|
25
|
-
formatted_gemfile_groups,
|
26
|
-
formatted_changelog_uri
|
27
|
-
]
|
28
|
-
end
|
29
|
-
|
30
19
|
def formatted_gem_name
|
31
20
|
vulnerable? ? pastel.white.on_red(name) : apply_semver_highlight(name)
|
32
21
|
end
|
@@ -46,6 +35,10 @@ class BundleUpdateInteractive::CLI
|
|
46
35
|
gemfile_groups&.map(&:inspect)&.join(", ")
|
47
36
|
end
|
48
37
|
|
38
|
+
def formatted_gemfile_requirement
|
39
|
+
gemfile_requirement.to_s == ">= 0" ? "" : gemfile_requirement.to_s
|
40
|
+
end
|
41
|
+
|
49
42
|
def formatted_changelog_uri
|
50
43
|
pastel.blue(changelog_uri)
|
51
44
|
end
|
@@ -4,12 +4,44 @@ require "pastel"
|
|
4
4
|
|
5
5
|
class BundleUpdateInteractive::CLI
|
6
6
|
class Table
|
7
|
-
|
7
|
+
class << self
|
8
|
+
def withheld(gems)
|
9
|
+
columns = [
|
10
|
+
["name", :formatted_gem_name],
|
11
|
+
["requirement", :formatted_gemfile_requirement],
|
12
|
+
["current", :formatted_current_version],
|
13
|
+
["latest", :formatted_updated_version],
|
14
|
+
["group", :formatted_gemfile_groups],
|
15
|
+
["url", :formatted_changelog_uri]
|
16
|
+
]
|
17
|
+
new(gems, columns)
|
18
|
+
end
|
8
19
|
|
9
|
-
|
20
|
+
def updatable(gems)
|
21
|
+
columns = [
|
22
|
+
["name", :formatted_gem_name],
|
23
|
+
["from", :formatted_current_version],
|
24
|
+
[nil, "→"],
|
25
|
+
["to", :formatted_updated_version],
|
26
|
+
["group", :formatted_gemfile_groups],
|
27
|
+
["url", :formatted_changelog_uri]
|
28
|
+
]
|
29
|
+
new(gems, columns)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(gems, columns)
|
10
34
|
@pastel = BundleUpdateInteractive.pastel
|
11
|
-
@headers =
|
12
|
-
@rows =
|
35
|
+
@headers = columns.map { |header, _| pastel.dim.underline(header) }
|
36
|
+
@rows = gems.transform_values do |gem|
|
37
|
+
row = Row.new(gem)
|
38
|
+
columns.map do |_, col|
|
39
|
+
case col
|
40
|
+
when Symbol then row.public_send(col).to_s
|
41
|
+
when String then col
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
13
45
|
@column_widths = calculate_column_widths
|
14
46
|
end
|
15
47
|
|
@@ -11,19 +11,16 @@ module BundleUpdateInteractive
|
|
11
11
|
|
12
12
|
def run(argv: ARGV) # rubocop:disable Metrics/AbcSize
|
13
13
|
options = Options.parse(argv)
|
14
|
-
|
15
14
|
report = generate_report(options)
|
16
|
-
puts("No gems to update.").then { return } if report.updateable_gems.empty?
|
17
15
|
|
18
|
-
|
19
|
-
puts
|
20
|
-
|
21
|
-
selected_gems = MultiSelect.prompt_for_gems_to_update(report.
|
16
|
+
puts_legend_and_withheld_gems(report) unless report.empty?
|
17
|
+
puts("No gems to update.").then { return } if report.updatable_gems.empty?
|
18
|
+
|
19
|
+
selected_gems = MultiSelect.prompt_for_gems_to_update(report.updatable_gems)
|
22
20
|
puts("No gems to update.").then { return } if selected_gems.empty?
|
23
21
|
|
24
|
-
puts "
|
25
|
-
puts
|
26
|
-
puts Table.new(selected_gems).render
|
22
|
+
puts "Updating the following gems."
|
23
|
+
puts Table.updatable(selected_gems).render
|
27
24
|
puts
|
28
25
|
report.bundle_update!(*selected_gems.keys)
|
29
26
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
@@ -32,6 +29,17 @@ module BundleUpdateInteractive
|
|
32
29
|
|
33
30
|
private
|
34
31
|
|
32
|
+
def puts_legend_and_withheld_gems(report)
|
33
|
+
puts
|
34
|
+
puts legend
|
35
|
+
puts
|
36
|
+
return if report.withheld_gems.empty?
|
37
|
+
|
38
|
+
puts "The following gems are being held back and cannot be updated."
|
39
|
+
puts Table.withheld(report.withheld_gems).render
|
40
|
+
puts
|
41
|
+
end
|
42
|
+
|
35
43
|
def legend
|
36
44
|
pastel = BundleUpdateInteractive.pastel
|
37
45
|
<<~LEGEND
|
@@ -46,14 +54,13 @@ module BundleUpdateInteractive
|
|
46
54
|
|
47
55
|
def generate_report(options)
|
48
56
|
whisper "Resolving latest gem versions..."
|
49
|
-
report =
|
50
|
-
|
51
|
-
return report if updateable_gems.empty?
|
57
|
+
report = Reporter.new(groups: options.exclusively).generate_report
|
58
|
+
return report if report.empty?
|
52
59
|
|
53
60
|
whisper "Checking for security vulnerabilities..."
|
54
61
|
report.scan_for_vulnerabilities!
|
55
62
|
|
56
|
-
progress "Finding changelogs",
|
63
|
+
progress "Finding changelogs", report.all_gems.values, &:changelog_uri
|
57
64
|
report
|
58
65
|
end
|
59
66
|
|
@@ -4,13 +4,14 @@ module BundleUpdateInteractive
|
|
4
4
|
class OutdatedGem
|
5
5
|
attr_accessor :name,
|
6
6
|
:gemfile_groups,
|
7
|
+
:gemfile_requirement,
|
7
8
|
:git_source_uri,
|
8
9
|
:current_version,
|
9
10
|
:current_git_version,
|
10
11
|
:updated_version,
|
11
12
|
:updated_git_version
|
12
13
|
|
13
|
-
attr_writer :rubygems_source, :vulnerable
|
14
|
+
attr_writer :changelog_uri, :rubygems_source, :vulnerable
|
14
15
|
|
15
16
|
def initialize(**attrs)
|
16
17
|
@vulnerable = nil
|
@@ -7,38 +7,20 @@ require "set"
|
|
7
7
|
|
8
8
|
module BundleUpdateInteractive
|
9
9
|
class Report
|
10
|
-
|
11
|
-
def generate(groups: [])
|
12
|
-
gemfile = Gemfile.parse
|
13
|
-
current_lockfile = Lockfile.parse
|
14
|
-
gems = groups.any? ? current_lockfile.gems_exclusively_installed_by(gemfile: gemfile, groups: groups) : nil
|
10
|
+
attr_reader :withheld_gems, :updatable_gems
|
15
11
|
|
16
|
-
|
17
|
-
new(gemfile: gemfile, current_lockfile: current_lockfile, updated_lockfile: updated_lockfile)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :outdated_gems
|
22
|
-
|
23
|
-
def initialize(gemfile:, current_lockfile:, updated_lockfile:)
|
12
|
+
def initialize(current_lockfile:, withheld_gems:, updatable_gems:)
|
24
13
|
@current_lockfile = current_lockfile
|
25
|
-
@
|
26
|
-
|
27
|
-
updated_lockfile_entry = updated_lockfile && updated_lockfile[name]
|
28
|
-
next unless current_lockfile_entry.older_than?(updated_lockfile_entry)
|
29
|
-
|
30
|
-
hash[name] = build_outdated_gem(current_lockfile_entry, updated_lockfile_entry, gemfile[name]&.groups)
|
31
|
-
end.freeze
|
14
|
+
@withheld_gems = withheld_gems.freeze
|
15
|
+
@updatable_gems = updatable_gems.freeze
|
32
16
|
end
|
33
17
|
|
34
|
-
def
|
35
|
-
|
18
|
+
def empty?
|
19
|
+
withheld_gems.empty? && updatable_gems.empty?
|
36
20
|
end
|
37
21
|
|
38
|
-
def
|
39
|
-
@
|
40
|
-
current_lockfile[name].exact_requirement?
|
41
|
-
end.freeze
|
22
|
+
def all_gems
|
23
|
+
@all_gems ||= withheld_gems.merge(updatable_gems)
|
42
24
|
end
|
43
25
|
|
44
26
|
def expand_gems_with_exact_dependencies(*gem_names)
|
@@ -47,13 +29,13 @@ module BundleUpdateInteractive
|
|
47
29
|
end
|
48
30
|
|
49
31
|
def scan_for_vulnerabilities!
|
50
|
-
return false if
|
32
|
+
return false if all_gems.empty?
|
51
33
|
|
52
34
|
Bundler::Audit::Database.update!(quiet: true)
|
53
35
|
audit_report = Bundler::Audit::Scanner.new.report
|
54
36
|
vulnerable_gem_names = Set.new(audit_report.vulnerable_gems.map(&:name))
|
55
37
|
|
56
|
-
|
38
|
+
all_gems.each do |name, gem|
|
57
39
|
gem.vulnerable = (vulnerable_gem_names & [name, *current_lockfile[name].exact_dependencies]).any?
|
58
40
|
end
|
59
41
|
true
|
@@ -67,18 +49,5 @@ module BundleUpdateInteractive
|
|
67
49
|
private
|
68
50
|
|
69
51
|
attr_reader :current_lockfile
|
70
|
-
|
71
|
-
def build_outdated_gem(current_lockfile_entry, updated_lockfile_entry, gemfile_groups)
|
72
|
-
OutdatedGem.new(
|
73
|
-
name: current_lockfile_entry.name,
|
74
|
-
gemfile_groups: gemfile_groups,
|
75
|
-
rubygems_source: updated_lockfile_entry.rubygems_source?,
|
76
|
-
git_source_uri: updated_lockfile_entry.git_source_uri&.to_s,
|
77
|
-
current_version: current_lockfile_entry.version.to_s,
|
78
|
-
current_git_version: current_lockfile_entry.git_version&.strip,
|
79
|
-
updated_version: updated_lockfile_entry.version.to_s,
|
80
|
-
updated_git_version: updated_lockfile_entry.git_version&.strip
|
81
|
-
)
|
82
|
-
end
|
83
52
|
end
|
84
53
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BundleUpdateInteractive
|
4
|
+
class Reporter
|
5
|
+
def initialize(groups: [])
|
6
|
+
@gemfile = Gemfile.parse
|
7
|
+
@current_lockfile = Lockfile.parse
|
8
|
+
@candidate_gems = current_lockfile.gems_exclusively_installed_by(gemfile: gemfile, groups: groups) if groups.any?
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_report
|
12
|
+
updatable_gems = find_updatable_gems
|
13
|
+
withheld_gems = find_withheld_gems(exclude: updatable_gems.keys)
|
14
|
+
|
15
|
+
Report.new(current_lockfile: current_lockfile, updatable_gems: updatable_gems, withheld_gems: withheld_gems)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :gemfile, :current_lockfile, :candidate_gems
|
21
|
+
|
22
|
+
def find_updatable_gems
|
23
|
+
return {} if candidate_gems && candidate_gems.empty?
|
24
|
+
|
25
|
+
updated_lockfile = Lockfile.parse(BundlerCommands.read_updated_lockfile(*Array(candidate_gems)))
|
26
|
+
current_lockfile.entries.each_with_object({}) do |current_lockfile_entry, hash|
|
27
|
+
name = current_lockfile_entry.name
|
28
|
+
updated_lockfile_entry = updated_lockfile && updated_lockfile[name]
|
29
|
+
next unless current_lockfile_entry.older_than?(updated_lockfile_entry)
|
30
|
+
next if current_lockfile_entry.exact_requirement?
|
31
|
+
|
32
|
+
hash[name] = build_outdated_gem(name, updated_lockfile_entry.version, updated_lockfile_entry.git_version)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_outdated_gem(name, updated_version, updated_git_version)
|
37
|
+
current_lockfile_entry = current_lockfile[name]
|
38
|
+
|
39
|
+
OutdatedGem.new(
|
40
|
+
name: name,
|
41
|
+
gemfile_groups: gemfile[name]&.groups,
|
42
|
+
gemfile_requirement: gemfile[name]&.requirement&.to_s,
|
43
|
+
rubygems_source: current_lockfile_entry.rubygems_source?,
|
44
|
+
git_source_uri: current_lockfile_entry.git_source_uri&.to_s,
|
45
|
+
current_version: current_lockfile_entry.version.to_s,
|
46
|
+
current_git_version: current_lockfile_entry.git_version&.strip,
|
47
|
+
updated_version: updated_version.to_s,
|
48
|
+
updated_git_version: updated_git_version&.strip
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_withheld_gems(exclude: [])
|
53
|
+
possibly_withheld = gemfile.dependencies.filter_map do |dep|
|
54
|
+
dep.name if dep.should_include? && !dep.requirement.none? # rubocop:disable Style/InverseMethods
|
55
|
+
end
|
56
|
+
possibly_withheld -= exclude
|
57
|
+
possibly_withheld &= candidate_gems unless candidate_gems.nil?
|
58
|
+
|
59
|
+
return {} if possibly_withheld.empty?
|
60
|
+
|
61
|
+
BundlerCommands.parse_outdated(*possibly_withheld).to_h do |name, newest|
|
62
|
+
[name, build_outdated_gem(name, newest, nil)]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -10,10 +10,12 @@ module BundleUpdateInteractive
|
|
10
10
|
|
11
11
|
@same_segments = new_segments.take_while.with_index { |seg, i| seg == old_segments[i] }
|
12
12
|
@diff_segments = new_segments[same_segments.length..]
|
13
|
+
|
14
|
+
@changed = diff_segments.any? || old_segments.length != new_segments.length
|
13
15
|
end
|
14
16
|
|
15
17
|
def severity
|
16
|
-
return nil
|
18
|
+
return nil unless @changed
|
17
19
|
|
18
20
|
SEVERITIES[same_segments.length] || :patch
|
19
21
|
end
|
@@ -13,6 +13,7 @@ module BundleUpdateInteractive
|
|
13
13
|
autoload :LockfileEntry, "bundle_update_interactive/lockfile_entry"
|
14
14
|
autoload :OutdatedGem, "bundle_update_interactive/outdated_gem"
|
15
15
|
autoload :Report, "bundle_update_interactive/report"
|
16
|
+
autoload :Reporter, "bundle_update_interactive/reporter"
|
16
17
|
autoload :SemverChange, "bundle_update_interactive/semver_change"
|
17
18
|
autoload :VERSION, "bundle_update_interactive/version"
|
18
19
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundle_update_interactive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Brictson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.9.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: launchy
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.5.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.5.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: pastel
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,7 @@ files:
|
|
108
122
|
- lib/bundle_update_interactive/lockfile_entry.rb
|
109
123
|
- lib/bundle_update_interactive/outdated_gem.rb
|
110
124
|
- lib/bundle_update_interactive/report.rb
|
125
|
+
- lib/bundle_update_interactive/reporter.rb
|
111
126
|
- lib/bundle_update_interactive/semver_change.rb
|
112
127
|
- lib/bundle_update_interactive/version.rb
|
113
128
|
homepage: https://github.com/mattbrictson/bundle_update_interactive
|