Skip to content

Commit e852453

Browse files
Merge pull request #18 from jamesoneill997/add-min-date-arg
feat: add optional --older-than flag
2 parents 985e6e7 + d97148a commit e852453

File tree

7 files changed

+143
-14
lines changed

7 files changed

+143
-14
lines changed

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ GEM
5757

5858
PLATFORMS
5959
arm64-darwin-22
60+
arm64-darwin-23
61+
arm64-darwin-24
6062
x86_64-linux
6163

6264
DEPENDENCIES

lib/gem_dating.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@
55
require_relative "gem_dating/cli"
66

77
module GemDating
8-
def self.from_string(s)
8+
def self.from_string(s, options = {})
99
gems = Input.string(s).gems
10-
specs = Rubygems.fetch(gems)
11-
Result.new(specs)
10+
fetch_specs(gems, options)
1211
end
1312

14-
def self.from_file(path)
13+
def self.from_file(path, options = {})
1514
gems = Input.file(path).gems
15+
fetch_specs(gems, options)
16+
end
17+
18+
19+
def self.fetch_specs(gems, options)
1620
specs = Rubygems.fetch(gems)
17-
Result.new(specs)
21+
results = Result.new(specs)
22+
results.older_than(options[:older_than]) if options[:older_than]
23+
results
1824
end
25+
26+
private_class_method :fetch_specs
1927
end

lib/gem_dating/cli.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ class Cli
1010
GEMFILE_FILEPATH defaults to ./Gemfile if not provided.
1111
1212
Options:
13-
--help, -h Show this help message
13+
--help, -h, -? Show this help message
14+
--older-than=<AGE>, --ot=<AGE> Filter gems updated within the last X (e.g. 2y, 1m, 4w, 10d)
1415
HELP
1516

1617
def initialize(argv = [])
1718
args, file_path = argv.partition { |arg| (arg =~ /--\w+/) || (arg =~ /(-[a-z])/) }
1819

1920
@args = args
2021
@file_path = file_path.first
22+
@options = parse_args
2123
end
2224

2325
def run
24-
if (@args & ['-h', '--help']).any?
26+
if @options[:help]
2527
$stdout << HELP_TEXT
2628
return SUCCESS
2729
end
@@ -38,9 +40,20 @@ def run
3840
end
3941
end
4042

41-
$stdout << GemDating.from_file(@file_path).table_print << "\n"
43+
$stdout << GemDating.from_file(@file_path, @options).table_print << "\n"
4244

4345
SUCCESS
4446
end
47+
48+
private
49+
50+
def parse_args(args = @args)
51+
options = {}
52+
options[:help] = true if (args & %w[-h --help -?]).any?
53+
if (older_than = args.find { |arg| arg.start_with?("--older-than=", "--ot=") })
54+
options[:older_than] = older_than.split("=").last
55+
end
56+
options
57+
end
4558
end
4659
end

lib/gem_dating/result.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,32 @@ def to_h
2424
def table_print
2525
TablePrint::Printer.table_print(specs, [:name, :version, {date: {time_format: "%Y-%m-%d", width: 10}}]).encode("utf-8")
2626
end
27+
28+
def older_than(date)
29+
specs.select! { |spec| spec.date.to_date < self.cut_off(date) }
30+
end
31+
32+
private
33+
34+
def cut_off(date)
35+
return unless date
36+
curr_date = Date.today
37+
38+
number = date[0..-2].to_i
39+
unit = date[-1]
40+
41+
case unit
42+
when "y"
43+
curr_date << (12 * number)
44+
when "m"
45+
curr_date << number
46+
when "w"
47+
curr_date - (number * 7)
48+
when "d"
49+
curr_date - number
50+
else
51+
raise ArgumentError, "Invalid date format: #{date}"
52+
end
53+
end
2754
end
2855
end

test/cli_test.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ def test_default_to_existing_relative_gemfile
6161
end
6262

6363
expected_out = <<~EXPECTED
64-
NAME | VERSION | DATE
65-
----------------|----------|-----------
66-
banana-client | 21.1.0 | 1990-08-21
67-
rails-on-rubies | 70.0.5 | 2123-05-24
68-
giraffeql | 0.0.2227 | 2023-05-17
69-
EXPECTED
64+
NAME | VERSION | DATE
65+
----------------|----------|-----------
66+
banana-client | 21.1.0 | 1990-08-21
67+
rails-on-rubies | 70.0.5 | 2123-05-24
68+
giraffeql | 0.0.2227 | 2023-05-17
69+
EXPECTED
7070

7171
assert_equal 0, exit_code
7272
assert_equal expected_out, stdout
@@ -109,4 +109,12 @@ def test_help_option
109109
assert_includes expected_out, stdout.split("\n").first
110110
assert_includes expected_out, stdout.split("\n").last
111111
end
112+
113+
def test_parse_args
114+
cli = GemDating::Cli.new(["--help", "--older-than=2y"])
115+
assert_equal({ help: true, older_than: "2y" }, cli.send(:parse_args))
116+
117+
cli = GemDating::Cli.new([])
118+
assert_equal({}, cli.send(:parse_args))
119+
end
112120
end

test/result_test.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
require "date"
33

44
class TestResult < Minitest::Test
5+
6+
def build_mock_spec(name:, version:, date:)
7+
spec = Gem::Specification.new
8+
spec.name = name
9+
spec.version = Gem::Version.new(version)
10+
spec.date = date
11+
spec
12+
end
13+
514
def setup
615
@spec1 = Gem::Specification.new do |s|
716
s.name = "hi"
@@ -14,6 +23,18 @@ def setup
1423
s.date = DateTime.parse("2009-09-02")
1524
end
1625
@result = GemDating::Result.new([@spec1, @spec2])
26+
27+
today = Date.today
28+
29+
@recent_gem = build_mock_spec(name: "recent", version: "1.0", date: today - 10)
30+
@months_old_gem = build_mock_spec(name: "months_old", version: "1.0", date: today << 2)
31+
@year_old_gem = build_mock_spec(name: "year_old", version: "1.0", date: today - 400)
32+
33+
@date_result = GemDating::Result.new([
34+
@recent_gem,
35+
@months_old_gem,
36+
@year_old_gem
37+
])
1738
end
1839

1940
def test_specs
@@ -51,4 +72,42 @@ def test_table
5172
assert_equal line.strip, table.split[index].strip
5273
end
5374
end
75+
76+
def test_cut_off_parsing_years
77+
@date_result.older_than("1y")
78+
79+
assert_equal @date_result.specs.include?(@year_old_gem), true
80+
assert_equal @date_result.specs.include?(@months_old_gem), false
81+
assert_equal @date_result.specs.include?(@recent_gem), false
82+
end
83+
84+
def test_cut_off_parsing_months
85+
@date_result.older_than("1m")
86+
87+
assert_equal @date_result.specs.include?(@year_old_gem), true
88+
assert_equal @date_result.specs.include?(@months_old_gem), true
89+
assert_equal @date_result.specs.include?(@recent_gem), false
90+
end
91+
92+
def test_cut_off_parsing_weeks
93+
@date_result.older_than("3w")
94+
95+
assert_equal @date_result.specs.include?(@year_old_gem), true
96+
assert_equal @date_result.specs.include?(@months_old_gem), true
97+
assert_equal @date_result.specs.include?(@recent_gem), false
98+
end
99+
100+
def test_cut_off_parsing_days
101+
@date_result.older_than("7d")
102+
103+
assert_equal @date_result.specs.include?(@year_old_gem), true
104+
assert_equal @date_result.specs.include?(@months_old_gem), true
105+
assert_equal @date_result.specs.include?(@recent_gem), true
106+
end
107+
108+
def test_cut_off_invalid_format_raises
109+
assert_raises(ArgumentError) { @date_result.older_than("5x") }
110+
assert_raises(ArgumentError) { @date_result.older_than("abc") }
111+
assert_raises(ArgumentError) { @date_result.older_than("") }
112+
end
54113
end

test/rubygems_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require "test_helper"
2+
require "date"
3+
4+
class GemDating::RubygemsTest < Minitest::Test
5+
def test_unknown_version_returns_spec_with_defaults
6+
rubygems = GemDating::Rubygems.new
7+
spec = rubygems.unknown_version("foobar")
8+
assert_equal "foobar", spec.name
9+
assert_equal Gem::Version.new("0.0.0.UNKNOWN"), spec.version
10+
assert_equal Date.parse("1970-01-01"), spec.date.to_date
11+
end
12+
end

0 commit comments

Comments
 (0)