twig 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,7 +8,7 @@ class Twig
8
8
 
9
9
  # Shorten relative time
10
10
  @time_ago = time_ago.
11
- sub(' years', 'y').
11
+ sub(/ years?/, 'y').
12
12
  sub(' months', 'mo').
13
13
  sub(' weeks', 'w').
14
14
  sub(' days', 'd').
@@ -66,7 +66,6 @@ class Twig
66
66
  end
67
67
 
68
68
  def branch_list_headers(header_options = {})
69
- all_property_names = Twig::Branch.all_property_names
70
69
  branch_indicator_padding = ' ' * CURRENT_BRANCH_INDICATOR.size
71
70
 
72
71
  header_options.merge!(
@@ -81,7 +80,7 @@ class Twig
81
80
  )
82
81
 
83
82
  out = column(' ', :width => date_time_column_width) << column_gutter
84
- out << all_property_names.map do |property|
83
+ out << property_names.map do |property|
85
84
  width = property_column_width(property)
86
85
  column(property, header_options.merge(:width => width)) << column_gutter
87
86
  end.join
@@ -89,7 +88,7 @@ class Twig
89
88
  out << "\n"
90
89
 
91
90
  out << column(' ', :width => date_time_column_width) << column_gutter
92
- out << all_property_names.map do |property|
91
+ out << property_names.map do |property|
93
92
  width = property_column_width(property)
94
93
  underline = '-' * property.size
95
94
  column(underline, header_options.merge(:width => width)) << column_gutter
@@ -101,11 +100,10 @@ class Twig
101
100
  end
102
101
 
103
102
  def branch_list_line(branch)
104
- all_property_names = Twig::Branch.all_property_names
105
103
  is_current_branch = branch.name == current_branch_name
106
104
 
107
- properties = branch.get_properties(all_property_names)
108
- properties = all_property_names.inject({}) do |result, property_name|
105
+ properties = branch.get_properties(property_names)
106
+ properties = property_names.inject({}) do |result, property_name|
109
107
  property_value = (properties[property_name] || '').strip
110
108
  property_value = EMPTY_BRANCH_PROPERTY_INDICATOR if property_value.empty?
111
109
  property_value.gsub!(/[\n\r]+/, ' ')
@@ -116,7 +114,7 @@ class Twig
116
114
  line << column_gutter
117
115
 
118
116
  line <<
119
- all_property_names.map do |property_name|
117
+ property_names.map do |property_name|
120
118
  property_value = properties[property_name] || ''
121
119
  width = property_column_width(property_name)
122
120
  column(property_value, :width => width) << column_gutter
@@ -141,7 +139,7 @@ class Twig
141
139
  require 'json'
142
140
 
143
141
  data = {
144
- 'branches' => branches.map { |branch| branch.to_hash }
142
+ 'branches' => branches.map { |branch| branch.to_hash(property_names) }
145
143
  }
146
144
  data.to_json
147
145
  end
@@ -66,6 +66,21 @@ class Twig
66
66
  options.each do |key, value|
67
67
  case key
68
68
 
69
+ # Displaying branches:
70
+ when 'format'
71
+ set_option(:format, value)
72
+ when 'except-property'
73
+ set_option(:property_except_name, value)
74
+ when 'only-property'
75
+ set_option(:property_only_name, value)
76
+ when 'header-style'
77
+ set_option(:header_style, value)
78
+ when 'reverse'
79
+ set_option(:reverse, value)
80
+ when /-width$/
81
+ property_name = key.sub(/-width$/, '').to_sym
82
+ set_option(:property_width, property_name => value)
83
+
69
84
  # Filtering branches:
70
85
  when 'branch'
71
86
  set_option(:branch, value)
@@ -78,17 +93,6 @@ class Twig
78
93
  property_name = key.sub(/^only-/, '').to_sym
79
94
  set_option(:property_only, property_name => value)
80
95
 
81
- # Displaying branches:
82
- when 'format'
83
- set_option(:format, value)
84
- when 'header-style'
85
- set_option(:header_style, value)
86
- when 'reverse'
87
- set_option(:reverse, value)
88
- when /-width$/
89
- property_name = key.sub(/-width$/, '').to_sym
90
- set_option(:property_width, property_name => value)
91
-
92
96
  # GitHub integration:
93
97
  when 'github-api-uri-prefix'
94
98
  set_option(:github_api_uri_prefix, value)
@@ -102,7 +106,7 @@ class Twig
102
106
  def set_option(key, value)
103
107
  case key
104
108
  when :branch
105
- if all_branch_names.include?(value)
109
+ if Twig::Branch.all_branch_names.include?(value)
106
110
  options[:branch] = value
107
111
  else
108
112
  abort %{The branch `#{value}` could not be found.}
@@ -128,19 +132,15 @@ class Twig
128
132
  abort %{The value `--max-days-old=#{value}` is invalid.}
129
133
  end
130
134
 
131
- when :property_except
135
+ when :property_except, :property_only
132
136
  property_hash = value.inject({}) do |hsh, (property, val)|
133
137
  hsh.merge(property => Regexp.new(val))
134
138
  end
135
- options[:property_except] ||= {}
136
- options[:property_except].merge!(property_hash)
139
+ options[key] ||= {}
140
+ options[key].merge!(property_hash)
137
141
 
138
- when :property_only
139
- property_hash = value.inject({}) do |hsh, (property, val)|
140
- hsh.merge(property => Regexp.new(val))
141
- end
142
- options[:property_only] ||= {}
143
- options[:property_only].merge!(property_hash)
142
+ when :property_except_name, :property_only_name
143
+ options[key] = Regexp.new(value)
144
144
 
145
145
  when :property_width
146
146
  set_property_width_option(value)
@@ -149,7 +149,7 @@ class Twig
149
149
  options[:reverse] = Twig::Util.truthy?(value)
150
150
 
151
151
  when :unset_property
152
- options[:unset_property] = value
152
+ options[key] = value
153
153
  end
154
154
  end
155
155
 
@@ -175,6 +175,8 @@ class Twig
175
175
  end
176
176
 
177
177
  def set_property_width_option(value)
178
+ options[:property_width] ||= {}
179
+
178
180
  value.each do |property_name, property_value|
179
181
  unless Twig::Util.numeric?(property_value)
180
182
  abort %{The value `--#{property_name}-width=#{property_value}` is invalid.}
@@ -197,8 +199,7 @@ class Twig
197
199
  abort error
198
200
  end
199
201
 
200
- options[:property_width] ||= {}
201
- options[:property_width].merge!(property_name => property_value)
202
+ options[:property_width][property_name] = property_value
202
203
  end
203
204
  end
204
205
 
@@ -1,3 +1,3 @@
1
1
  class Twig
2
- VERSION = '1.5'
2
+ VERSION = '1.6'
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'twig'
2
2
  require 'json'
3
+ require 'rspec/radar'
3
4
 
4
5
  RSpec.configure do |config|
5
6
  config.expect_with :rspec do |c|
@@ -6,6 +6,73 @@ describe Twig::Branch do
6
6
  @twig = Twig.new
7
7
  end
8
8
 
9
+ describe '.all_branches' do
10
+ before :each do
11
+ @branch_names = %w[
12
+ fix_some_of_the_things
13
+ fix_some_other_of_the_things
14
+ fix_nothing
15
+ ]
16
+ @commit_time_strings = ['2001-01-01', '2002-02-02', '2003-03-03' ]
17
+ @commit_time_agos = ['111 days ago', '2 months ago', '3 years, 3 months ago']
18
+ @command =
19
+ %{git for-each-ref #{Twig::REF_PREFIX} --format="#{Twig::REF_FORMAT}"}
20
+
21
+ @branch_tuples = (0..2).map do |i|
22
+ [
23
+ @branch_names[i],
24
+ @commit_time_strings[i],
25
+ @commit_time_agos[i]
26
+ ].join(Twig::REF_FORMAT_SEPARATOR)
27
+ end.join("\n")
28
+ end
29
+
30
+ it 'returns an array of branches' do
31
+ expect(Twig).to receive(:run).with(@command).and_return(@branch_tuples)
32
+
33
+ branches = Twig::Branch.all_branches
34
+
35
+ expect(branches[0].name).to eq(@branch_names[0])
36
+ expect(branches[0].last_commit_time.to_s).to match(
37
+ %r{#{@commit_time_strings[0]} .* \(111d ago\)}
38
+ )
39
+ expect(branches[1].name).to eq(@branch_names[1])
40
+ expect(branches[1].last_commit_time.to_s).to match(
41
+ %r{#{@commit_time_strings[1]} .* \(2mo ago\)}
42
+ )
43
+ expect(branches[2].name).to eq(@branch_names[2])
44
+ expect(branches[2].last_commit_time.to_s).to match(
45
+ %r{#{@commit_time_strings[2]} .* \(3y ago\)}
46
+ )
47
+ end
48
+
49
+ it 'memoizes the result' do
50
+ Twig::Branch.instance_variable_set(:@_all_branches, nil)
51
+ expect(Twig).to receive(:run).with(@command).once.and_return(@branch_tuples)
52
+
53
+ 2.times { Twig::Branch.all_branches }
54
+ end
55
+ end
56
+
57
+ describe '.all_branch_names' do
58
+ before :each do
59
+ @branch_names = %w[foo bar baz]
60
+ @branches = @branch_names.map { |name| Twig::Branch.new(name) }
61
+ end
62
+
63
+ it 'returns an array of all branch names' do
64
+ expect(Twig::Branch).to receive(:all_branches).and_return(@branches)
65
+ expect(Twig::Branch.all_branch_names).to eq(@branch_names)
66
+ end
67
+
68
+ it 'memoizes the result' do
69
+ Twig::Branch.instance_variable_set(:@_all_branch_names, nil)
70
+ expect(Twig::Branch).to receive(:all_branches).once.and_return(@branches)
71
+
72
+ 2.times { Twig::Branch.all_branch_names }
73
+ end
74
+ end
75
+
9
76
  describe '.all_property_names' do
10
77
  before :each do
11
78
  Twig::Branch.instance_variable_set(:@_all_property_names, nil)
@@ -63,6 +130,20 @@ describe Twig::Branch do
63
130
  end
64
131
  end
65
132
 
133
+ describe '.validate_property_name' do
134
+ it 'raises an exception if the property name is empty' do
135
+ expect {
136
+ Twig::Branch.validate_property_name('')
137
+ }.to raise_exception(Twig::Branch::EmptyPropertyNameError)
138
+ end
139
+
140
+ it 'does nothing if the property name is not empty' do
141
+ expect {
142
+ Twig::Branch.validate_property_name('test')
143
+ }.not_to raise_exception
144
+ end
145
+ end
146
+
66
147
  describe '#initialize' do
67
148
  it 'requires a name' do
68
149
  branch = Twig::Branch.new('test')
@@ -97,12 +178,11 @@ describe Twig::Branch do
97
178
  end
98
179
 
99
180
  it 'returns the hash for a branch with properties' do
100
- expect(Twig::Branch).to receive(:all_property_names) { %w[foo bar] }
101
- expect(@branch).to receive(:get_properties) do
181
+ expect(@branch).to receive(:get_properties).with(%w[foo bar]) do
102
182
  { 'foo' => 'foo!', 'bar' => 'bar!' }
103
183
  end
104
184
 
105
- result = @branch.to_hash
185
+ result = @branch.to_hash(%w[foo bar])
106
186
 
107
187
  expect(result).to eq(
108
188
  'name' => 'test',
@@ -115,10 +195,9 @@ describe Twig::Branch do
115
195
  end
116
196
 
117
197
  it 'returns the hash for a branch with no properties' do
118
- expect(Twig::Branch).to receive(:all_property_names) { %w[foo bar] }
119
- expect(@branch).to receive(:get_properties).and_return({})
198
+ expect(@branch).to receive(:get_properties).with(%w[foo bar]).and_return({})
120
199
 
121
- result = @branch.to_hash
200
+ result = @branch.to_hash(%w[foo bar])
122
201
 
123
202
  expect(result).to eq(
124
203
  'name' => 'test',
@@ -2,6 +2,44 @@ require 'spec_helper'
2
2
 
3
3
  describe Twig::Cli do
4
4
 
5
+ describe '.prompt_with_choices' do
6
+ it 'prints a prompt with the given choices' do
7
+ stdout_orig = $stdout
8
+ stdout_test = StringIO.new
9
+ $stdout = stdout_test
10
+ prompt = 'What does the fox say?'
11
+ choices = [
12
+ 'Ring-ding-ding-ding-dingeringeding!',
13
+ 'Wa-pa-pa-pa-pa-pa-pow!',
14
+ 'Hatee-hatee-hatee-ho!',
15
+ 'Joff-tchoff-tchoffo-tchoffo-tchoff!'
16
+ ]
17
+ expect($stdin).to receive(:gets).and_return('4')
18
+
19
+ result = Twig::Cli.prompt_with_choices(prompt, choices)
20
+
21
+ $stdout = stdout_orig
22
+ expect(stdout_test.string).to eq(
23
+ prompt + "\n" +
24
+ " 1. #{choices[0]}\n" +
25
+ " 2. #{choices[1]}\n" +
26
+ " 3. #{choices[2]}\n" +
27
+ " 4. #{choices[3]}\n" +
28
+ '> '
29
+ )
30
+ expect(result).to eq(choices[3])
31
+ end
32
+
33
+ it 'requires at least two choices' do
34
+ expect {
35
+ Twig::Cli.prompt_with_choices(
36
+ 'What does the fox say?',
37
+ ['Ring-ding-ding-ding-dingeringeding!']
38
+ )
39
+ }.to raise_exception(ArgumentError)
40
+ end
41
+ end
42
+
5
43
  describe '#help_description' do
6
44
  before :each do
7
45
  @twig = Twig.new
@@ -104,6 +142,10 @@ describe Twig::Cli do
104
142
  expect(@twig.help_line_for_custom_property?(' --except-branch ')).to be_false
105
143
  end
106
144
 
145
+ it 'returns false for `--except-property`' do
146
+ expect(@twig.help_line_for_custom_property?(' --except-property ')).to be_false
147
+ end
148
+
107
149
  it 'returns false for `--except-PROPERTY`' do
108
150
  expect(@twig.help_line_for_custom_property?(' --except-PROPERTY ')).to be_false
109
151
  end
@@ -116,6 +158,10 @@ describe Twig::Cli do
116
158
  expect(@twig.help_line_for_custom_property?(' --only-branch ')).to be_false
117
159
  end
118
160
 
161
+ it 'returns false for `--only-property`' do
162
+ expect(@twig.help_line_for_custom_property?(' --only-property ')).to be_false
163
+ end
164
+
119
165
  it 'returns false for `--only-PROPERTY`' do
120
166
  expect(@twig.help_line_for_custom_property?(' --only-PROPERTY ')).to be_false
121
167
  end
@@ -200,7 +246,7 @@ describe Twig::Cli do
200
246
  end
201
247
 
202
248
  it 'recognizes `-b` and sets a `:branch` option' do
203
- expect(@twig).to receive(:all_branch_names).and_return(['test'])
249
+ expect(Twig::Branch).to receive(:all_branch_names).and_return(['test'])
204
250
  expect(@twig.options[:branch]).to be_nil
205
251
 
206
252
  @twig.read_cli_options!(%w[-b test])
@@ -209,7 +255,7 @@ describe Twig::Cli do
209
255
  end
210
256
 
211
257
  it 'recognizes `--branch` and sets a `:branch` option' do
212
- expect(@twig).to receive(:all_branch_names).and_return(['test'])
258
+ expect(Twig::Branch).to receive(:all_branch_names).and_return(['test'])
213
259
  expect(@twig.options[:branch]).to be_nil
214
260
 
215
261
  @twig.read_cli_options!(%w[--branch test])
@@ -262,14 +308,13 @@ describe Twig::Cli do
262
308
  expect(Twig::Branch.all_property_names).not_to include(property_name)
263
309
  allow(@twig).to receive(:puts)
264
310
 
265
- begin
311
+ expect {
266
312
  @twig.read_cli_options!(["--only-#{property_name}", 'test'])
267
- rescue SystemExit => exception
268
- expected_exception = exception
269
- end
313
+ }.to raise_exception { |exception|
314
+ expect(exception).to be_a(SystemExit)
315
+ expect(exception.status).to eq(1)
316
+ }
270
317
 
271
- expect(expected_exception).not_to be_nil
272
- expect(expected_exception.status).to eq(0)
273
318
  expect(@twig.options[:property_only]).to be_nil
274
319
  end
275
320
  end
@@ -301,14 +346,13 @@ describe Twig::Cli do
301
346
  expect(Twig::Branch.all_property_names).not_to include(property_name)
302
347
  allow(@twig).to receive(:puts)
303
348
 
304
- begin
349
+ expect {
305
350
  @twig.read_cli_options!(["--except-#{property_name}", 'test'])
306
- rescue SystemExit => exception
307
- expected_exception = exception
308
- end
351
+ }.to raise_exception { |exception|
352
+ expect(exception).to be_a(SystemExit)
353
+ expect(exception.status).to eq(1)
354
+ }
309
355
 
310
- expect(expected_exception).not_to be_nil
311
- expect(expected_exception.status).to eq(0)
312
356
  expect(@twig.options[:property_except]).to be_nil
313
357
  end
314
358
  end
@@ -346,6 +390,18 @@ describe Twig::Cli do
346
390
  @twig.read_cli_options!(%w[--foo-width 10])
347
391
  end
348
392
 
393
+ it 'recognizes `--only-property`' do
394
+ expect(@twig.options[:property_only_name]).to be_nil
395
+ @twig.read_cli_options!(%w[--only-property foo])
396
+ expect(@twig.options[:property_only_name]).to eq(/foo/)
397
+ end
398
+
399
+ it 'recognizes `--except-property`' do
400
+ expect(@twig.options[:property_except_name]).to be_nil
401
+ @twig.read_cli_options!(%w[--except-property foo])
402
+ expect(@twig.options[:property_except_name]).to eq(/foo/)
403
+ end
404
+
349
405
  it 'recognizes `--header-style`' do
350
406
  expect(@twig.options[:header_color]).to eq(Twig::DEFAULT_HEADER_COLOR)
351
407
  expect(@twig.options[:header_weight]).to be_nil
@@ -402,15 +458,18 @@ describe Twig::Cli do
402
458
  @twig = Twig.new
403
459
  end
404
460
 
405
- it 'prints a message and exits' do
461
+ it 'prints a message and aborts' do
406
462
  exception = Exception.new('test exception')
407
- expect(@twig).to receive(:puts).with(exception.message)
408
463
  expect(@twig).to receive(:puts) do |message|
409
464
  expect(message).to include('`twig --help`')
410
465
  end
411
- expect(@twig).to receive(:exit)
412
466
 
413
- @twig.abort_for_option_exception(exception)
467
+ expect {
468
+ @twig.abort_for_option_exception(exception)
469
+ }.to raise_exception { |exception|
470
+ expect(exception).to be_a(SystemExit)
471
+ expect(exception.status).to eq(1)
472
+ }
414
473
  end
415
474
  end
416
475
 
@@ -431,14 +490,12 @@ describe Twig::Cli do
431
490
  # Since we're stubbing `exec` (with an expectation), we still need it
432
491
  # to exit early like the real implementation. The following handles the
433
492
  # exit somewhat gracefully.
434
- begin
493
+ expect {
435
494
  @twig.read_cli_args!(['subcommand'])
436
- rescue SystemExit => exception
437
- expected_exception = exception
438
- end
439
-
440
- expect(expected_exception).not_to be_nil
441
- expect(expected_exception.status).to eq(0)
495
+ }.to raise_exception { |exception|
496
+ expect(exception).to be_a(SystemExit)
497
+ expect(exception.status).to eq(0)
498
+ }
442
499
  end
443
500
 
444
501
  it 'does not recognize a subcommand' do
@@ -459,14 +516,12 @@ describe Twig::Cli do
459
516
  it 'checks for and executes a subcommand if there are any args' do
460
517
  expect(@twig).to receive(:exec_subcommand_if_any).with(['foo']) { exit }
461
518
 
462
- begin
519
+ expect {
463
520
  @twig.read_cli_args!(['foo'])
464
- rescue SystemExit => exception
465
- expected_exception = exception
466
- end
467
-
468
- expect(expected_exception).not_to be_nil
469
- expect(expected_exception.status).to eq(0)
521
+ }.to raise_exception { |exception|
522
+ expect(exception).to be_a(SystemExit)
523
+ expect(exception.status).to eq(0)
524
+ }
470
525
  end
471
526
 
472
527
  it 'does not check for a subcommand if there are no args' do
@@ -513,7 +568,7 @@ describe Twig::Cli do
513
568
  end
514
569
 
515
570
  it 'gets a property for a specified branch' do
516
- expect(@twig).to receive(:all_branch_names).and_return([@branch_name])
571
+ expect(Twig::Branch).to receive(:all_branch_names).and_return([@branch_name])
517
572
  @twig.set_option(:branch, @branch_name)
518
573
  expect(@twig).to receive(:get_branch_property_for_cli).
519
574
  with(@branch_name, @property_name)
@@ -539,7 +594,7 @@ describe Twig::Cli do
539
594
  end
540
595
 
541
596
  it 'sets a property for a specified branch' do
542
- expect(@twig).to receive(:all_branch_names).and_return([@branch_name])
597
+ expect(Twig::Branch).to receive(:all_branch_names).and_return([@branch_name])
543
598
  @twig.set_option(:branch, @branch_name)
544
599
  expect(@twig).to receive(:set_branch_property_for_cli).
545
600
  with(@branch_name, @property_name, @property_value).
@@ -566,7 +621,7 @@ describe Twig::Cli do
566
621
  end
567
622
 
568
623
  it 'unsets a property for a specified branch' do
569
- expect(@twig).to receive(:all_branch_names).and_return([@branch_name])
624
+ expect(Twig::Branch).to receive(:all_branch_names).and_return([@branch_name])
570
625
  @twig.set_option(:branch, @branch_name)
571
626
  expect(@twig).to receive(:unset_branch_property_for_cli).
572
627
  with(@branch_name, @property_name)