diff_matcher 2.1.1 → 2.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.
- data/README.md +42 -6
- data/lib/diff_matcher/difference.rb +39 -16
- data/lib/diff_matcher/version.rb +1 -1
- data/spec/diff_matcher/difference_spec.rb +111 -27
- metadata +5 -5
data/README.md
CHANGED
@@ -105,20 +105,37 @@ puts DiffMatcher::difference([1], [1, 2])
|
|
105
105
|
```
|
106
106
|
|
107
107
|
|
108
|
-
When `expected`
|
108
|
+
When `expected` is a `Hash` with optional keys use a `Matcher`.
|
109
109
|
|
110
110
|
``` ruby
|
111
|
-
puts DiffMatcher::difference(
|
111
|
+
puts DiffMatcher::difference(
|
112
|
+
DiffMatcher::Matcher.new({:name=>String, :age=>Fixnum}, :optional_keys=>[:age]),
|
113
|
+
{:name=>0}
|
114
|
+
)
|
115
|
+
{
|
116
|
+
:name=>- String+ 0
|
117
|
+
}
|
118
|
+
Where, - 1 missing, + 1 additional
|
119
|
+
```
|
120
|
+
|
121
|
+
|
122
|
+
When `expected` can take multiple forms use some `Matcher`s `||`ed together.
|
123
|
+
|
124
|
+
``` ruby
|
125
|
+
puts DiffMatcher::difference(DiffMatcher::Matcher.new(Fixnum) || DiffMatcher.new(Float), "3")
|
112
126
|
- Float+ "3"
|
113
127
|
Where, - 1 missing, + 1 additional
|
114
128
|
```
|
129
|
+
(NB. `DiffMatcher::Matcher[Fixnum, Float]` can be used as a shortcut for
|
130
|
+
`DiffMatcher::Matcher.new(Fixnum) || DiffMatcher.new(Float)`
|
131
|
+
)
|
115
132
|
|
116
133
|
|
117
|
-
When `actual` is an array of unknown size use an `AllMatcher` to match
|
134
|
+
When `actual` is an array of *unknown* size use an `AllMatcher` to match
|
118
135
|
against *all* the elements in the array.
|
119
136
|
|
120
137
|
``` ruby
|
121
|
-
puts DiffMatcher::difference(DiffMatcher::AllMatcher
|
138
|
+
puts DiffMatcher::difference(DiffMatcher::AllMatcher.new(Fixnum), [1, 2, "3"])
|
122
139
|
[
|
123
140
|
: 1,
|
124
141
|
: 2,
|
@@ -128,15 +145,30 @@ Where, - 1 missing, + 1 additional, : 2 match_class
|
|
128
145
|
```
|
129
146
|
|
130
147
|
|
148
|
+
When `actual` is an array with a *limited* size use an `AllMatcher` to match
|
149
|
+
against *all* the elements in the array adhering to the limits of `:min`
|
150
|
+
and or `:max`.
|
151
|
+
|
152
|
+
``` ruby
|
153
|
+
puts DiffMatcher::difference(DiffMatcher::AllMatcher.new(Fixnum, :min=>3), [1, 2])
|
154
|
+
[
|
155
|
+
: 1,
|
156
|
+
: 2,
|
157
|
+
- Fixnum
|
158
|
+
]
|
159
|
+
Where, - 1 missing, : 2 match_class
|
160
|
+
```
|
161
|
+
|
162
|
+
|
131
163
|
When `actual` is an array of unknown size *and* `expected` can take
|
132
164
|
multiple forms use a `Matcher` inside of an `AllMatcher` to match
|
133
165
|
against *all* the elements in the array in any of the forms.
|
134
166
|
|
135
167
|
``` ruby
|
136
168
|
puts DiffMatcher::difference(
|
137
|
-
DiffMatcher::AllMatcher
|
169
|
+
DiffMatcher::AllMatcher.new(
|
138
170
|
DiffMatcher::Matcher[Fixnum, Float]
|
139
|
-
|
171
|
+
),
|
140
172
|
[1, 2.00, "3"]
|
141
173
|
)
|
142
174
|
[
|
@@ -175,6 +207,8 @@ The items shown in a difference are prefixed as follows:
|
|
175
207
|
match value =>
|
176
208
|
match regexp => "~ "
|
177
209
|
match class => ": "
|
210
|
+
match matcher => "| "
|
211
|
+
match proc => ". "
|
178
212
|
match proc => "{ "
|
179
213
|
|
180
214
|
|
@@ -189,6 +223,8 @@ Using the `:default` colour scheme items shown in a difference are coloured as f
|
|
189
223
|
match value =>
|
190
224
|
match regexp => green
|
191
225
|
match class => blue
|
226
|
+
match matcher => blue
|
227
|
+
match range => cyan
|
192
228
|
match proc => cyan
|
193
229
|
|
194
230
|
Other colour schemes, eg. `:color_scheme=>:white_background` will use different colour mappings.
|
@@ -8,13 +8,13 @@ module DiffMatcher
|
|
8
8
|
class Matcher
|
9
9
|
attr_reader :expecteds
|
10
10
|
|
11
|
-
def self.[](*
|
12
|
-
new(
|
11
|
+
def self.[](*expecteds)
|
12
|
+
expecteds.inject(nil) { |obj, e| obj ? obj | new(e) : new(e) }
|
13
13
|
end
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
@expecteds = [expected]
|
17
|
-
@
|
15
|
+
def initialize(expected, opts={})
|
16
|
+
@expecteds = [expected]
|
17
|
+
@expected_opts = {expected => opts}
|
18
18
|
end
|
19
19
|
|
20
20
|
def |(other)
|
@@ -22,25 +22,39 @@ module DiffMatcher
|
|
22
22
|
tap { @expecteds += other.expecteds }
|
23
23
|
end
|
24
24
|
|
25
|
-
def expected(
|
26
|
-
|
25
|
+
def expected(e, actual)
|
26
|
+
e
|
27
|
+
end
|
28
|
+
|
29
|
+
def expected_opts(e)
|
30
|
+
@expected_opts.fetch(e, {})
|
27
31
|
end
|
28
32
|
|
29
33
|
def diff(actual, opts={})
|
30
|
-
|
31
|
-
@expecteds.any? { |e|
|
32
|
-
d = DiffMatcher::Difference.new(expected(e, actual), actual, opts)
|
33
|
-
|
34
|
+
difs = []
|
35
|
+
matched = @expecteds.any? { |e|
|
36
|
+
d = DiffMatcher::Difference.new(expected(e, actual), actual, opts.merge(expected_opts(e)))
|
37
|
+
unless d.matching?
|
38
|
+
difs << [ d.dif_count, d.dif ]
|
39
|
+
end
|
34
40
|
d.matching?
|
35
41
|
}
|
36
|
-
|
42
|
+
unless matched
|
43
|
+
count, dif = difs.sort.last
|
44
|
+
dif
|
45
|
+
end
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
40
49
|
class NotAnArray < Exception; end
|
41
50
|
class AllMatcher < Matcher
|
42
|
-
def expected(
|
43
|
-
|
51
|
+
def expected(e, actual)
|
52
|
+
opts = expected_opts(e)
|
53
|
+
size = actual.size
|
54
|
+
min = opts[:min] || 0
|
55
|
+
max = opts[:max] || 1_000_000 # MAXINT?
|
56
|
+
size = size > min ? (size < max ? size : max) : min
|
57
|
+
[e]*size
|
44
58
|
end
|
45
59
|
|
46
60
|
def diff(actual, opts={})
|
@@ -67,6 +81,7 @@ module DiffMatcher
|
|
67
81
|
:match_regexp => [GREEN , "~"],
|
68
82
|
:match_class => [BLUE , ":"],
|
69
83
|
:match_matcher => [BLUE , "|"],
|
84
|
+
:match_range => [CYAN , "."],
|
70
85
|
:match_proc => [CYAN , "{"]
|
71
86
|
}
|
72
87
|
|
@@ -83,6 +98,8 @@ module DiffMatcher
|
|
83
98
|
@quiet = opts[:quiet]
|
84
99
|
@color_enabled = opts[:color_enabled] || !!opts[:color_scheme]
|
85
100
|
@color_scheme = COLOR_SCHEMES[opts[:color_scheme] || :default]
|
101
|
+
@optional_keys = opts.delete(:optional_keys) || []
|
102
|
+
@dif_count = 0
|
86
103
|
@difference = difference(expected, actual)
|
87
104
|
end
|
88
105
|
|
@@ -101,6 +118,7 @@ module DiffMatcher
|
|
101
118
|
unless item_type == :match_value
|
102
119
|
color, prefix = @color_scheme[item_type]
|
103
120
|
count = msg.scan("#{color}#{prefix}").size
|
121
|
+
@dif_count += count if [:missing, :additional].include? item_type
|
104
122
|
"#{color}#{prefix} #{BOLD}#{count} #{item_type}#{RESET}" if count > 0
|
105
123
|
end
|
106
124
|
}.compact.join(", ")
|
@@ -110,6 +128,10 @@ module DiffMatcher
|
|
110
128
|
end
|
111
129
|
end
|
112
130
|
|
131
|
+
def dif_count
|
132
|
+
@dif_count
|
133
|
+
end
|
134
|
+
|
113
135
|
def dif
|
114
136
|
@difference
|
115
137
|
end
|
@@ -132,7 +154,7 @@ module DiffMatcher
|
|
132
154
|
@matches_shown ||= lambda {
|
133
155
|
ret = []
|
134
156
|
unless @quiet
|
135
|
-
ret += [:match_matcher, :match_class, :match_proc, :match_regexp]
|
157
|
+
ret += [:match_matcher, :match_class, :match_range, :match_proc, :match_regexp]
|
136
158
|
ret += [:match_value]
|
137
159
|
end
|
138
160
|
ret
|
@@ -185,7 +207,7 @@ module DiffMatcher
|
|
185
207
|
|
186
208
|
def missing(left, right, expected_class)
|
187
209
|
compare(left, expected_class) { |k|
|
188
|
-
"#{"#{k.inspect}=>" if expected_class == Hash}#{left[k].inspect}" unless right.has_key?(k)
|
210
|
+
"#{"#{k.inspect}=>" if expected_class == Hash}#{left[k].inspect}" unless right.has_key?(k) || @optional_keys.include?(k)
|
189
211
|
}
|
190
212
|
end
|
191
213
|
|
@@ -199,6 +221,7 @@ module DiffMatcher
|
|
199
221
|
d = expected.diff(actual, @opts)
|
200
222
|
[d.nil? , :match_matcher, d]
|
201
223
|
when Class ; [actual.is_a?(expected) , :match_class ]
|
224
|
+
when Range ; [expected.include?(actual) , :match_range ]
|
202
225
|
when Proc ; [expected.call(actual) , :match_proc ]
|
203
226
|
when Regexp ; [actual.is_a?(String) && actual.match(expected) , :match_regexp ]
|
204
227
|
else [actual == expected , :match_value ]
|
data/lib/diff_matcher/version.rb
CHANGED
@@ -9,13 +9,15 @@ def fix_EOF_problem(s)
|
|
9
9
|
# <<-EOF isn't working like its meant to :(
|
10
10
|
whitespace = s.split("\n")[-1][/^[ ]+/]
|
11
11
|
indentation = whitespace ? whitespace.size : 0
|
12
|
-
s.gsub("\n#{" " * indentation}", "\n").
|
12
|
+
s.gsub("\n#{" " * indentation}", "\n").tap { |result|
|
13
|
+
result.strip! if whitespace
|
14
|
+
}
|
13
15
|
end
|
14
16
|
|
15
17
|
|
16
|
-
shared_examples_for "
|
18
|
+
shared_examples_for "an or-ed matcher" do |expected, expected2, same, different, difference, opts|
|
17
19
|
opts ||= {}
|
18
|
-
context "
|
20
|
+
context "where expected=#{expected.inspect}, expected2=#{expected2.inspect}" do
|
19
21
|
describe "diff(#{same.inspect}#{opts_to_s(opts)})" do
|
20
22
|
let(:expected ) { expected }
|
21
23
|
let(:expected2) { expected }
|
@@ -32,7 +34,7 @@ shared_examples_for "a matcher" do |expected, expected2, same, different, differ
|
|
32
34
|
let(:opts ) { opts }
|
33
35
|
|
34
36
|
it { should_not be_nil } unless RUBY_1_9
|
35
|
-
it { should == fix_EOF_problem(difference)
|
37
|
+
it { should == fix_EOF_problem(difference) } if RUBY_1_9
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -44,23 +46,24 @@ describe DiffMatcher::Matcher do
|
|
44
46
|
{:name => String , :age => Integer },
|
45
47
|
{:name => "Peter" , :age => 21 },
|
46
48
|
{:name => 21 , :age => 21 },
|
47
|
-
|
48
|
-
{
|
49
|
-
:name=>\e[31m- \e[1mString\e[0m\e[33m+ \e[1m21\e[0m,
|
50
|
-
:age=>\e[34m: \e[1m21\e[0m
|
51
|
-
}
|
52
|
-
EOF
|
49
|
+
"{\n :name=>\e[31m- \e[1mString\e[0m\e[33m+ \e[1m21\e[0m,\n :age=>\e[34m: \e[1m21\e[0m\n}\n"
|
53
50
|
|
54
51
|
describe "DiffMatcher::Matcher[expected, expected2]," do
|
55
52
|
subject { DiffMatcher::Matcher[expected, expected2].diff(actual) }
|
56
53
|
|
57
|
-
it_behaves_like "
|
58
|
-
end
|
54
|
+
it_behaves_like "an or-ed matcher", expected, expected2, same, different, difference
|
59
55
|
|
60
|
-
|
61
|
-
|
56
|
+
context "when Matchers are or-ed it works the same" do
|
57
|
+
subject { (DiffMatcher::Matcher[expected] | DiffMatcher::Matcher[expected2]).diff(actual) }
|
58
|
+
|
59
|
+
it_behaves_like "an or-ed matcher", expected, expected2, same, different, difference
|
60
|
+
end
|
62
61
|
|
63
|
-
|
62
|
+
context "expecteds are in different order it still uses the closest dif" do
|
63
|
+
subject { DiffMatcher::Matcher[expected2, expected].diff(actual) }
|
64
|
+
|
65
|
+
it_behaves_like "an or-ed matcher", expected2, expected, same, different, difference
|
66
|
+
end
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -119,6 +122,36 @@ shared_examples_for "a diff matcher" do |expected, same, different, difference,
|
|
119
122
|
end
|
120
123
|
end
|
121
124
|
|
125
|
+
describe "DiffMatcher::Matcher[expected].diff(actual, opts)" do
|
126
|
+
subject { DiffMatcher::Matcher[expected].diff(actual, opts) }
|
127
|
+
|
128
|
+
describe "when expected is an instance," do
|
129
|
+
context "of Fixnum," do
|
130
|
+
expected, same, different =
|
131
|
+
1,
|
132
|
+
1,
|
133
|
+
2
|
134
|
+
|
135
|
+
it_behaves_like "a diff matcher", expected, same, different,
|
136
|
+
"\e[31m- \e[1m1\e[0m\e[33m+ \e[1m2\e[0m", {}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "when expected is an instance," do
|
141
|
+
context "of Hash, with optional keys" do
|
142
|
+
expected, same, different =
|
143
|
+
{:a=>1, :b=>Fixnum},
|
144
|
+
{:a=>1},
|
145
|
+
{:a=>2}
|
146
|
+
|
147
|
+
it_behaves_like "a diff matcher", expected, same, different,
|
148
|
+
"{\n :a=>\e[31m- \e[1m1\e[0m\e[33m+ \e[1m2\e[0m\n}\n",
|
149
|
+
{:optional_keys=>[:b]}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
122
155
|
describe "DiffMatcher::difference(expected, actual, opts)" do
|
123
156
|
subject { DiffMatcher::difference(expected, actual, opts) }
|
124
157
|
|
@@ -247,6 +280,19 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
247
280
|
end
|
248
281
|
end
|
249
282
|
|
283
|
+
context "of Range," do
|
284
|
+
expected, same, different =
|
285
|
+
(1..3),
|
286
|
+
2,
|
287
|
+
4
|
288
|
+
|
289
|
+
it_behaves_like "a diff matcher", expected, same, different,
|
290
|
+
<<-EOF
|
291
|
+
- 1..3+ 4
|
292
|
+
Where, - 1 missing, + 1 additional
|
293
|
+
EOF
|
294
|
+
end
|
295
|
+
|
250
296
|
context "of Hash," do
|
251
297
|
expected, same, different =
|
252
298
|
{ "a"=>1 },
|
@@ -396,6 +442,40 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
396
442
|
EOF
|
397
443
|
|
398
444
|
end
|
445
|
+
|
446
|
+
context "with a min restriction" do
|
447
|
+
expected, same, different =
|
448
|
+
DiffMatcher::AllMatcher.new(String, :min=>3),
|
449
|
+
%w(ay be ci),
|
450
|
+
%w(ay be)
|
451
|
+
|
452
|
+
it_behaves_like "a diff matcher", expected, same, different,
|
453
|
+
<<-EOF
|
454
|
+
[
|
455
|
+
: "ay",
|
456
|
+
: "be",
|
457
|
+
- String
|
458
|
+
]
|
459
|
+
Where, - 1 missing, : 2 match_class
|
460
|
+
EOF
|
461
|
+
end
|
462
|
+
|
463
|
+
context "with a max restriction" do
|
464
|
+
expected, same, different =
|
465
|
+
DiffMatcher::AllMatcher.new(String, :max=>2),
|
466
|
+
%w(ay be),
|
467
|
+
%w(ay be ci)
|
468
|
+
|
469
|
+
it_behaves_like "a diff matcher", expected, same, different,
|
470
|
+
<<-EOF
|
471
|
+
[
|
472
|
+
: "ay",
|
473
|
+
: "be",
|
474
|
+
+ "ci"
|
475
|
+
]
|
476
|
+
Where, + 1 additional, : 2 match_class
|
477
|
+
EOF
|
478
|
+
end
|
399
479
|
end
|
400
480
|
|
401
481
|
context "a DiffMatcher::AllMatcher using an or-ed DiffMatcher::Matcher," do
|
@@ -450,11 +530,11 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
450
530
|
|
451
531
|
context "when expected has multiple items," do
|
452
532
|
expected, same, different =
|
453
|
-
[ 1, 2, /\d/, Fixnum, lambda { |x|
|
454
|
-
[ 1, 2, "3" , 4 , 5
|
455
|
-
[ 0, 2, "3" , 4 , 5
|
533
|
+
[ 1, 2, /\d/, Fixnum, 4..6 , lambda { |x| x % 6 == 0 } ],
|
534
|
+
[ 1, 2, "3" , 4 , 5 , 6 ],
|
535
|
+
[ 0, 2, "3" , 4 , 5 , 6 ]
|
456
536
|
|
457
|
-
describe "it shows regex, class, proc matches and matches" do
|
537
|
+
describe "it shows regex, class, range, proc matches and matches" do
|
458
538
|
it_behaves_like "a diff matcher", expected, same, different,
|
459
539
|
<<-EOF
|
460
540
|
[
|
@@ -462,9 +542,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
462
542
|
2,
|
463
543
|
~ "(3)",
|
464
544
|
: 4,
|
465
|
-
|
545
|
+
. 5,
|
546
|
+
{ 6
|
466
547
|
]
|
467
|
-
Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, { 1 match_proc
|
548
|
+
Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc
|
468
549
|
EOF
|
469
550
|
end
|
470
551
|
|
@@ -486,9 +567,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
486
567
|
2,
|
487
568
|
~ "(3)",
|
488
569
|
: 4,
|
489
|
-
|
570
|
+
. 5,
|
571
|
+
{ 6
|
490
572
|
]
|
491
|
-
Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, { 1 match_proc
|
573
|
+
Where, - 1 missing, + 1 additional, ~ 1 match_regexp, : 1 match_class, . 1 match_range, { 1 match_proc
|
492
574
|
EOF
|
493
575
|
end
|
494
576
|
|
@@ -500,9 +582,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
500
582
|
\e[0m 2,
|
501
583
|
\e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
|
502
584
|
\e[0m \e[34m: \e[1m4\e[0m,
|
503
|
-
\e[0m \e[36m
|
585
|
+
\e[0m \e[36m. \e[1m5\e[0m,
|
586
|
+
\e[0m \e[36m{ \e[1m6\e[0m
|
504
587
|
\e[0m]
|
505
|
-
Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
|
588
|
+
Where, \e[31m- \e[1m1 missing\e[0m, \e[33m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
|
506
589
|
EOF
|
507
590
|
|
508
591
|
context "on a white background" do
|
@@ -513,9 +596,10 @@ describe "DiffMatcher::difference(expected, actual, opts)" do
|
|
513
596
|
\e[0m 2,
|
514
597
|
\e[0m \e[32m~ \e[0m"\e[32m(\e[1m3\e[0m\e[32m)\e[0m"\e[0m,
|
515
598
|
\e[0m \e[34m: \e[1m4\e[0m,
|
516
|
-
\e[0m \e[36m
|
599
|
+
\e[0m \e[36m. \e[1m5\e[0m,
|
600
|
+
\e[0m \e[36m{ \e[1m6\e[0m
|
517
601
|
\e[0m]
|
518
|
-
Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
|
602
|
+
Where, \e[31m- \e[1m1 missing\e[0m, \e[35m+ \e[1m1 additional\e[0m, \e[32m~ \e[1m1 match_regexp\e[0m, \e[34m: \e[1m1 match_class\e[0m, \e[36m. \e[1m1 match_range\e[0m, \e[36m{ \e[1m1 match_proc\e[0m
|
519
603
|
EOF
|
520
604
|
end
|
521
605
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diff_matcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 2.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 2.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Playup
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-19 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|