Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/gem_dating.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def self.fetch_specs(gems, options)
specs = Rubygems.fetch(gems)
results = Result.new(specs)
results.older_than(options[:older_than]) if options[:older_than]
results.sort(options)
results
end

Expand Down
18 changes: 17 additions & 1 deletion lib/gem_dating/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class Cli
Options:
--help, -h, -? Show this help message
--older-than=<AGE>, --ot=<AGE> Filter gems updated within the last X (e.g. 2y, 1m, 4w, 10d)
--sort-by=<FIELD> Sort by field (name or date), defaults to name
--order=<DIRECTION> Sort direction (asc or desc), defaults to asc
--json Output results as JSON
HELP

def initialize(argv = [])
Expand Down Expand Up @@ -40,7 +43,9 @@ def run
end
end

$stdout << GemDating.from_file(@file_path, @options).table_print << "\n"
result = GemDating.from_file(@file_path, @options)
output = @options[:json] ? result.to_json : result.table_print
$stdout << output << "\n"

SUCCESS
end
Expand All @@ -50,9 +55,20 @@ def run
def parse_args(args = @args)
options = {}
options[:help] = true if (args & %w[-h --help -?]).any?
options[:json] = true if args.include?("--json")

if (older_than = args.find { |arg| arg.start_with?("--older-than=", "--ot=") })
options[:older_than] = older_than.split("=").last
end

if (sort_by = args.find { |arg| arg.start_with?("--sort-by=") })
options[:sort_by] = sort_by.split("=").last
end

if (order = args.find { |arg| arg.start_with?("--order=") })
options[:order] = order.split("=").last
end

options
end
end
Expand Down
26 changes: 26 additions & 0 deletions lib/gem_dating/result.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "table_print"
require "json"

module GemDating
class Result
Expand All @@ -25,8 +26,33 @@ def table_print
TablePrint::Printer.table_print(specs, [:name, :version, {date: {time_format: "%Y-%m-%d", width: 10}}]).encode("utf-8")
end

def to_json
JSON.generate(to_h)
end

def older_than(date)
specs.select! { |spec| spec.date.to_date < self.cut_off(date) }
self
end

def sort(options = {})
field = options[:sort_by] || "name"
direction = options[:order] || "asc"

@specs = @specs.sort_by do |spec|
case field
when "name"
spec.name.downcase
when "date"
spec.date
else
spec.name.downcase
end
end

@specs = @specs.reverse if direction.downcase == "desc"

self
end

private
Expand Down
74 changes: 72 additions & 2 deletions test/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def test_gemfile
NAME | VERSION | DATE
----------------|----------|-----------
banana-client | 21.1.0 | 1990-08-21
rails-on-rubies | 70.0.5 | 2123-05-24
giraffeql | 0.0.2227 | 2023-05-17
rails-on-rubies | 70.0.5 | 2123-05-24
EXPECTED

assert_equal 0, exit_code
Expand All @@ -64,8 +64,8 @@ def test_default_to_existing_relative_gemfile
NAME | VERSION | DATE
----------------|----------|-----------
banana-client | 21.1.0 | 1990-08-21
rails-on-rubies | 70.0.5 | 2123-05-24
giraffeql | 0.0.2227 | 2023-05-17
rails-on-rubies | 70.0.5 | 2123-05-24
EXPECTED

assert_equal 0, exit_code
Expand Down Expand Up @@ -114,7 +114,77 @@ def test_parse_args
cli = GemDating::Cli.new(["--help", "--older-than=2y"])
assert_equal({ help: true, older_than: "2y" }, cli.send(:parse_args))

cli = GemDating::Cli.new(["--json"])
assert_equal({ json: true }, cli.send(:parse_args))

cli = GemDating::Cli.new([])
assert_equal({}, cli.send(:parse_args))
end

def test_sort_by_name_asc
exit_code = nil

stdout, _stderr = capture_io do
exit_code = GemDating::Cli.new(["test/Gemfile.example", "--sort-by=name", "--order=asc"]).run
end

expected_out = <<~EXPECTED
NAME | VERSION | DATE
----------------|----------|-----------
banana-client | 21.1.0 | 1990-08-21
giraffeql | 0.0.2227 | 2023-05-17
rails-on-rubies | 70.0.5 | 2123-05-24
EXPECTED

assert_equal 0, exit_code
assert_equal expected_out, stdout
end

def test_sort_by_date_desc
exit_code = nil

stdout, _stderr = capture_io do
exit_code = GemDating::Cli.new(["test/Gemfile.example", "--sort-by=date", "--order=desc"]).run
end

expected_out = <<~EXPECTED
NAME | VERSION | DATE
----------------|----------|-----------
rails-on-rubies | 70.0.5 | 2123-05-24
giraffeql | 0.0.2227 | 2023-05-17
banana-client | 21.1.0 | 1990-08-21
EXPECTED

assert_equal 0, exit_code
assert_equal expected_out, stdout
end

def test_json_output
exit_code = nil

stdout, _stderr = capture_io do
exit_code = GemDating::Cli.new(["test/Gemfile.example", "--json"]).run
end

expected_data = {
"banana-client" => {
"name" => "banana-client",
"version" => "21.1.0",
"date" => "1990-08-21"
},
"giraffeql" => {
"name" => "giraffeql",
"version" => "0.0.2227",
"date" => "2023-05-17"
},
"rails-on-rubies" => {
"name" => "rails-on-rubies",
"version" => "70.0.5",
"date" => "2123-05-24"
}
}

assert_equal 0, exit_code
assert_equal expected_data, JSON.parse(stdout)
end
end
3 changes: 2 additions & 1 deletion test/gem_dating_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def test_gems_copy_pasted_from_gemfile
gem "puma", "~> 5.0"
TEXT

rails, _rest = GemDating.from_string(pasteboard).to_a
specs = GemDating.from_string(pasteboard).to_a
rails = specs.find { |spec| spec.name == "rails" }

assert_equal "rails", rails.name
assert_operator Gem::Version.new("7.0"), :<=, rails.version
Expand Down
52 changes: 52 additions & 0 deletions test/result_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ def test_hash
assert_equal expected, @result.to_h
end

def test_json
expected = {
"hi" => {
"name" => "hi",
"version" => "42.42",
"date" => "2015-09-18"
},
"there" => {
"name" => "there",
"version" => "1.27.0.01",
"date" => "2009-09-02"
}
}
assert_equal expected, JSON.parse(@result.to_json)
end

def test_table
expected = <<-TEXT
NAME | VERSION | DATE
Expand Down Expand Up @@ -110,4 +126,40 @@ def test_cut_off_invalid_format_raises
assert_raises(ArgumentError) { @date_result.older_than("abc") }
assert_raises(ArgumentError) { @date_result.older_than("") }
end

def test_sort_by_name_asc
result = GemDating::Result.new([@spec1, @spec2])
sorted = result.sort(sort_by: "name", order: "asc")

assert_equal ["hi", "there"], sorted.to_a.map(&:name)
end

def test_sort_by_name_desc
result = GemDating::Result.new([@spec1, @spec2])
sorted = result.sort(sort_by: "name", order: "desc")

assert_equal ["there", "hi"], sorted.to_a.map(&:name)
end

def test_sort_by_date_asc
result = GemDating::Result.new([@spec1, @spec2])
sorted = result.sort(sort_by: "date", order: "asc")

assert_equal ["there", "hi"], sorted.to_a.map(&:name)
end

def test_sort_by_date_desc
result = GemDating::Result.new([@spec1, @spec2])
sorted = result.sort(sort_by: "date", order: "desc")

assert_equal ["hi", "there"], sorted.to_a.map(&:name)
end

def test_sort_defaults
result = GemDating::Result.new([@spec2, @spec1])
sorted = result.sort

# Default sort is by name in ascending order
assert_equal ["hi", "there"], sorted.to_a.map(&:name)
end
end