twig 1.5 → 1.6

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.
@@ -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)