twig 1.4 → 1.5
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/HISTORY.md +15 -0
- data/README.md +17 -4
- data/bin/twig-gh-open +1 -1
- data/bin/twig-gh-open-issue +1 -1
- data/bin/twig-gh-update +1 -1
- data/bin/twig-help +1 -1
- data/bin/twig-init-completion-bash +22 -3
- data/bin/twig-rebase +1 -1
- data/lib/twig.rb +23 -13
- data/lib/twig/branch.rb +24 -9
- data/lib/twig/cli.rb +84 -25
- data/lib/twig/commit_time.rb +10 -0
- data/lib/twig/display.rb +9 -0
- data/lib/twig/options.rb +88 -46
- data/lib/twig/subcommands.rb +26 -0
- data/lib/twig/system.rb +9 -0
- data/lib/twig/version.rb +1 -1
- data/spec/spec_helper.rb +7 -0
- data/spec/twig/branch_spec.rb +134 -60
- data/spec/twig/cli_spec.rb +247 -156
- data/spec/twig/commit_time_spec.rb +20 -18
- data/spec/twig/display_spec.rb +108 -57
- data/spec/twig/github_spec.rb +90 -73
- data/spec/twig/options_spec.rb +311 -152
- data/spec/twig/subcommands_spec.rb +29 -0
- data/spec/twig/system_spec.rb +36 -0
- data/spec/twig/util_spec.rb +20 -20
- data/spec/twig_spec.rb +103 -76
- data/twig.gemspec +9 -6
- metadata +17 -11
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twig::Subcommands do
|
4
|
+
describe '.all_names' do
|
5
|
+
it 'returns a unique, sorted list of known subcommands' do
|
6
|
+
allow(Twig::Subcommands).to receive(:bin_dir_paths) { %w[foo/bin bar/bin] }
|
7
|
+
expect(Dir).to receive(:glob).with('foo/bin/twig-*').
|
8
|
+
and_yield('foo/bin/twig-subcommand-2').
|
9
|
+
and_yield('foo/bin/twig-subcommand-1')
|
10
|
+
expect(Dir).to receive(:glob).with('bar/bin/twig-*').
|
11
|
+
and_yield('bar/bin/twig-subcommand-1')
|
12
|
+
|
13
|
+
names = Twig::Subcommands.all_names
|
14
|
+
|
15
|
+
expect(names).to eq(%w[subcommand-1 subcommand-2])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns an empty array if no subcommands are found' do
|
19
|
+
allow(Twig::Subcommands).to receive(:bin_dir_paths) { %w[foo/bin bar/bin] }
|
20
|
+
expect(Dir).to receive(:glob).with('foo/bin/twig-*')
|
21
|
+
expect(Dir).to receive(:glob).with('bar/bin/twig-*')
|
22
|
+
|
23
|
+
names = Twig::Subcommands.all_names
|
24
|
+
|
25
|
+
expect(names).to eq([])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twig::System do
|
4
|
+
describe '.windows?' do
|
5
|
+
it 'returns true if `host_os` is `windows`' do
|
6
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').
|
7
|
+
and_return('windows')
|
8
|
+
expect(Twig::System.windows?).to be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns true if `host_os` is `win32`' do
|
12
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').
|
13
|
+
and_return('win32')
|
14
|
+
expect(Twig::System.windows?).to be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns true if `host_os` is Cygwin' do
|
18
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').
|
19
|
+
and_return('cygwin')
|
20
|
+
expect(Twig::System.windows?).to be_true
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns true if `host_os` is MinGW' do
|
24
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').
|
25
|
+
and_return('mingw')
|
26
|
+
expect(Twig::System.windows?).to be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns false if `host_os` is `darwin` (OS X)' do
|
30
|
+
expect(RbConfig::CONFIG).to receive(:[]).with('host_os').
|
31
|
+
and_return('darwin')
|
32
|
+
expect(Twig::System.windows?).to be_false
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/spec/twig/util_spec.rb
CHANGED
@@ -3,37 +3,37 @@ require 'spec_helper'
|
|
3
3
|
describe Twig::Util do
|
4
4
|
describe '.numeric?' do
|
5
5
|
it 'returns true if an object is numeric' do
|
6
|
-
Twig::Util.numeric?(1).
|
7
|
-
Twig::Util.numeric?('1').
|
6
|
+
expect(Twig::Util.numeric?(1)).to be_true
|
7
|
+
expect(Twig::Util.numeric?('1')).to be_true
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'returns false if an object is not numeric' do
|
11
|
-
Twig::Util.numeric?('x').
|
12
|
-
Twig::Util.numeric?([]).
|
13
|
-
Twig::Util.numeric?({}).
|
11
|
+
expect(Twig::Util.numeric?('x')).to be_false
|
12
|
+
expect(Twig::Util.numeric?([])).to be_false
|
13
|
+
expect(Twig::Util.numeric?({})).to be_false
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
describe '.truthy?' do
|
18
18
|
it 'returns true if an object is truthy' do
|
19
|
-
Twig::Util.truthy?('true').
|
20
|
-
Twig::Util.truthy?('TRUE').
|
21
|
-
Twig::Util.truthy?(true).
|
22
|
-
Twig::Util.truthy?('yes').
|
23
|
-
Twig::Util.truthy?('YES').
|
24
|
-
Twig::Util.truthy?('y').
|
25
|
-
Twig::Util.truthy?('Y').
|
26
|
-
Twig::Util.truthy?('on').
|
27
|
-
Twig::Util.truthy?('ON').
|
28
|
-
Twig::Util.truthy?('1').
|
29
|
-
Twig::Util.truthy?(1).
|
19
|
+
expect(Twig::Util.truthy?('true')).to be_true
|
20
|
+
expect(Twig::Util.truthy?('TRUE')).to be_true
|
21
|
+
expect(Twig::Util.truthy?(true)).to be_true
|
22
|
+
expect(Twig::Util.truthy?('yes')).to be_true
|
23
|
+
expect(Twig::Util.truthy?('YES')).to be_true
|
24
|
+
expect(Twig::Util.truthy?('y')).to be_true
|
25
|
+
expect(Twig::Util.truthy?('Y')).to be_true
|
26
|
+
expect(Twig::Util.truthy?('on')).to be_true
|
27
|
+
expect(Twig::Util.truthy?('ON')).to be_true
|
28
|
+
expect(Twig::Util.truthy?('1')).to be_true
|
29
|
+
expect(Twig::Util.truthy?(1)).to be_true
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'returns false if an object is falsy' do
|
33
|
-
Twig::Util.truthy?('false').
|
34
|
-
Twig::Util.truthy?(false).
|
35
|
-
Twig::Util.truthy?('yep').
|
36
|
-
Twig::Util.truthy?('sure, why not').
|
33
|
+
expect(Twig::Util.truthy?('false')).to be_false
|
34
|
+
expect(Twig::Util.truthy?(false)).to be_false
|
35
|
+
expect(Twig::Util.truthy?('yep')).to be_false
|
36
|
+
expect(Twig::Util.truthy?('sure, why not')).to be_false
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
data/spec/twig_spec.rb
CHANGED
@@ -5,20 +5,20 @@ describe Twig do
|
|
5
5
|
describe '.repo?' do
|
6
6
|
it 'is true when the working directory is a git repository' do
|
7
7
|
Dir.chdir(File.dirname(__FILE__)) do
|
8
|
-
Twig.
|
8
|
+
expect(Twig).to be_repo
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'is false when the working directory is not a git repository' do
|
13
13
|
Dir.mktmpdir do |tmpdir|
|
14
14
|
Dir.chdir(tmpdir) do
|
15
|
-
Twig.
|
15
|
+
expect(Twig).not_to be_repo
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'captures stderr' do
|
21
|
-
Twig.
|
21
|
+
expect(Twig).to receive(:run).with(/2>&1/)
|
22
22
|
Twig.repo?
|
23
23
|
end
|
24
24
|
end
|
@@ -26,9 +26,11 @@ describe Twig do
|
|
26
26
|
describe '#initialize' do
|
27
27
|
it 'creates a Twig instance' do
|
28
28
|
twig = Twig.new
|
29
|
-
twig.options.
|
29
|
+
expect(twig.options).to eq(
|
30
|
+
:github_api_uri_prefix => Twig::DEFAULT_GITHUB_API_URI_PREFIX,
|
31
|
+
:github_uri_prefix => Twig::DEFAULT_GITHUB_URI_PREFIX,
|
30
32
|
:header_color => Twig::DEFAULT_HEADER_COLOR
|
31
|
-
|
33
|
+
)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -36,12 +38,12 @@ describe Twig do
|
|
36
38
|
it 'returns the current branch name' do
|
37
39
|
twig = Twig.new
|
38
40
|
branch_name = 'fix_all_the_things'
|
39
|
-
Twig.
|
41
|
+
expect(Twig).to receive(:run).
|
40
42
|
with('git rev-parse --abbrev-ref HEAD').
|
41
43
|
once. # Should memoize
|
42
44
|
and_return(branch_name)
|
43
45
|
|
44
|
-
2.times { twig.current_branch_name.
|
46
|
+
2.times { expect(twig.current_branch_name).to eq(branch_name) }
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -52,35 +54,42 @@ describe Twig do
|
|
52
54
|
fix_some_other_of_the_things
|
53
55
|
fix_nothing
|
54
56
|
]
|
55
|
-
@commit_time_strings = ['2001-01-01', '2002-02-02', '2003-03-03'
|
56
|
-
@commit_time_agos = ['111 days ago', '
|
57
|
+
@commit_time_strings = ['2001-01-01', '2002-02-02', '2003-03-03' ]
|
58
|
+
@commit_time_agos = ['111 days ago', '2 months ago', '3 years, 3 months ago']
|
57
59
|
@command =
|
58
60
|
%{git for-each-ref #{Twig::REF_PREFIX} --format="#{Twig::REF_FORMAT}"}
|
59
61
|
|
60
62
|
@branch_tuples = (0..2).map do |i|
|
61
|
-
|
63
|
+
[
|
64
|
+
@branch_names[i],
|
65
|
+
@commit_time_strings[i],
|
66
|
+
@commit_time_agos[i]
|
67
|
+
].join(Twig::REF_FORMAT_SEPARATOR)
|
62
68
|
end.join("\n")
|
63
69
|
end
|
64
70
|
|
65
71
|
it 'returns an array of branches' do
|
66
|
-
Twig.
|
72
|
+
expect(Twig).to receive(:run).with(@command).and_return(@branch_tuples)
|
67
73
|
twig = Twig.new
|
68
74
|
|
69
75
|
branches = twig.all_branches
|
70
76
|
|
71
|
-
branches[0].name.
|
72
|
-
branches[0].last_commit_time.to_s.
|
73
|
-
|
74
|
-
|
75
|
-
branches[1].
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
expect(branches[0].name).to eq(@branch_names[0])
|
78
|
+
expect(branches[0].last_commit_time.to_s).to match(
|
79
|
+
%r{#{@commit_time_strings[0]} .* \(111d ago\)}
|
80
|
+
)
|
81
|
+
expect(branches[1].name).to eq(@branch_names[1])
|
82
|
+
expect(branches[1].last_commit_time.to_s).to match(
|
83
|
+
%r{#{@commit_time_strings[1]} .* \(2mo ago\)}
|
84
|
+
)
|
85
|
+
expect(branches[2].name).to eq(@branch_names[2])
|
86
|
+
expect(branches[2].last_commit_time.to_s).to match(
|
87
|
+
%r{#{@commit_time_strings[2]} .* \(3y ago\)}
|
88
|
+
)
|
80
89
|
end
|
81
90
|
|
82
91
|
it 'memoizes the result' do
|
83
|
-
Twig.
|
92
|
+
expect(Twig).to receive(:run).with(@command).once.and_return(@branch_tuples)
|
84
93
|
twig = Twig.new
|
85
94
|
|
86
95
|
2.times { twig.all_branches }
|
@@ -108,49 +117,78 @@ describe Twig do
|
|
108
117
|
Twig::Branch.new(branch_names[2], :last_commit_time => commit_times[2]),
|
109
118
|
Twig::Branch.new(branch_names[3], :last_commit_time => commit_times[3])
|
110
119
|
]
|
111
|
-
@twig.
|
120
|
+
allow(@twig).to receive(:all_branches) { @branches }
|
112
121
|
end
|
113
122
|
|
114
123
|
it 'returns all branches' do
|
115
|
-
@twig.branches.
|
124
|
+
expect(@twig.branches).to eq(@branches)
|
116
125
|
end
|
117
126
|
|
118
127
|
it 'returns only branches below a certain age' do
|
119
128
|
@twig.set_option(:max_days_old, 25)
|
120
|
-
|
121
|
-
|
129
|
+
|
130
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
131
|
+
expect(branch_names).to eq([@branches[0].name, @branches[1].name])
|
122
132
|
end
|
123
133
|
|
124
134
|
it 'returns all branches except those matching a name pattern' do
|
125
135
|
@twig.set_option(:property_except, :branch => /fix_some/)
|
126
|
-
|
127
|
-
|
136
|
+
|
137
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
138
|
+
expect(branch_names).to eq([@branches[2].name, @branches[3].name])
|
128
139
|
end
|
129
140
|
|
130
141
|
it 'returns only branches matching a name pattern' do
|
131
142
|
@twig.set_option(:property_only, :branch => /fix_some/)
|
132
|
-
|
133
|
-
|
143
|
+
|
144
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
145
|
+
expect(branch_names).to eq([@branches[0].name, @branches[1].name])
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns a list of branches, most recently modified first' do
|
149
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
150
|
+
|
151
|
+
expect(branch_names).to eq([
|
152
|
+
@branches[0].name,
|
153
|
+
@branches[1].name,
|
154
|
+
@branches[2].name,
|
155
|
+
@branches[3].name
|
156
|
+
])
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'returns a list of branches, least recently modified first' do
|
160
|
+
@twig.set_option(:reverse, true)
|
161
|
+
|
162
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
163
|
+
|
164
|
+
expect(branch_names).to eq([
|
165
|
+
@branches[3].name,
|
166
|
+
@branches[2].name,
|
167
|
+
@branches[1].name,
|
168
|
+
@branches[0].name
|
169
|
+
])
|
134
170
|
end
|
135
171
|
|
136
172
|
context 'with property filtering' do
|
137
173
|
before :each do
|
138
|
-
@branches[0].
|
139
|
-
@branches[1].
|
140
|
-
@branches[2].
|
141
|
-
@branches[3].
|
174
|
+
allow(@branches[0]).to receive(:get_property).with('foo') { 'bar1' }
|
175
|
+
allow(@branches[1]).to receive(:get_property).with('foo') { 'bar2' }
|
176
|
+
allow(@branches[2]).to receive(:get_property).with('foo') { 'baz' }
|
177
|
+
allow(@branches[3]).to receive(:get_property).with('foo') { nil }
|
142
178
|
end
|
143
179
|
|
144
180
|
it 'returns all branches except those matching a property pattern' do
|
145
181
|
@twig.set_option(:property_except, :foo => /bar/)
|
146
|
-
|
147
|
-
|
182
|
+
|
183
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
184
|
+
expect(branch_names).to eq([@branches[2].name, @branches[3].name])
|
148
185
|
end
|
149
186
|
|
150
187
|
it 'returns only branches matching a property pattern' do
|
151
188
|
@twig.set_option(:property_only, :foo => /bar/)
|
152
|
-
|
153
|
-
|
189
|
+
|
190
|
+
branch_names = @twig.branches.map { |branch| branch.name }
|
191
|
+
expect(branch_names).to eq([@branches[0].name, @branches[1].name])
|
154
192
|
end
|
155
193
|
end
|
156
194
|
end
|
@@ -160,9 +198,9 @@ describe Twig do
|
|
160
198
|
twig = Twig.new
|
161
199
|
branch_names = %w[foo bar baz]
|
162
200
|
branches = branch_names.map { |name| Twig::Branch.new(name) }
|
163
|
-
twig.
|
201
|
+
expect(twig).to receive(:all_branches).and_return(branches)
|
164
202
|
|
165
|
-
twig.all_branch_names.
|
203
|
+
expect(twig.all_branch_names).to eq(branch_names)
|
166
204
|
end
|
167
205
|
end
|
168
206
|
|
@@ -174,10 +212,10 @@ describe Twig do
|
|
174
212
|
Twig::CommitTime.new(Time.now, '111 days ago'),
|
175
213
|
Twig::CommitTime.new(Time.now, '222 days ago')
|
176
214
|
]
|
177
|
-
commit_times[0].
|
178
|
-
commit_times[0].
|
179
|
-
commit_times[1].
|
180
|
-
commit_times[1].
|
215
|
+
allow(commit_times[0]).to receive(:to_i) { 2000_01_01 }
|
216
|
+
allow(commit_times[0]).to receive(:to_s) { '2000-01-01' }
|
217
|
+
allow(commit_times[1]).to receive(:to_i) { 2000_01_02 }
|
218
|
+
allow(commit_times[1]).to receive(:to_s) { '2000-01-02' }
|
181
219
|
@branches = [
|
182
220
|
Twig::Branch.new('foo', :last_commit_time => commit_times[0]),
|
183
221
|
Twig::Branch.new('foo', :last_commit_time => commit_times[1])
|
@@ -185,47 +223,36 @@ describe Twig do
|
|
185
223
|
@branch_lines = ['[foo line]', '[bar line]']
|
186
224
|
end
|
187
225
|
|
188
|
-
it 'returns a list of branches
|
189
|
-
@twig.
|
190
|
-
@twig.
|
191
|
-
@twig.
|
226
|
+
it 'returns a formatted list of branches' do
|
227
|
+
expect(@twig).to receive(:branches).at_least(:once).and_return(@branches)
|
228
|
+
expect(@twig).to receive(:branch_list_headers).and_return(@list_headers)
|
229
|
+
expect(@twig).to receive(:branch_list_line).with(@branches[0]).
|
192
230
|
and_return(@branch_lines[0])
|
193
|
-
@twig.
|
231
|
+
expect(@twig).to receive(:branch_list_line).with(@branches[1]).
|
194
232
|
and_return(@branch_lines[1])
|
195
233
|
|
196
234
|
result = @twig.list_branches
|
197
235
|
|
198
|
-
result.
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
it 'returns a list of branches, least recently modified first' do
|
203
|
-
@twig.set_option(:reverse, true)
|
204
|
-
@twig.stub(:branches) { @branches }
|
205
|
-
@twig.stub(:branch_list_headers) { @list_headers }
|
206
|
-
@twig.stub(:branch_list_line).with(@branches[0]) { @branch_lines[0] }
|
207
|
-
@twig.stub(:branch_list_line).with(@branches[1]) { @branch_lines[1] }
|
208
|
-
|
209
|
-
result = @twig.list_branches
|
210
|
-
|
211
|
-
result.should == "\n" + @list_headers +
|
212
|
-
@branch_lines[0] + "\n" + @branch_lines[1]
|
236
|
+
expect(result).to eq(
|
237
|
+
"\n" + @list_headers + @branch_lines[0] +
|
238
|
+
"\n" + @branch_lines[1]
|
239
|
+
)
|
213
240
|
end
|
214
241
|
|
215
242
|
it 'returns a message if all branches were filtered out by options' do
|
216
|
-
@twig.
|
217
|
-
@twig.
|
243
|
+
allow(@twig).to receive(:all_branches) { %w[foo bar] }
|
244
|
+
allow(@twig).to receive(:branches) { [] }
|
218
245
|
|
219
|
-
@twig.list_branches.
|
246
|
+
expect(@twig.list_branches).to include(
|
220
247
|
'There are no branches matching your selected options'
|
221
248
|
)
|
222
249
|
end
|
223
250
|
|
224
251
|
it 'returns a message if the repo has no branches' do
|
225
|
-
@twig.
|
226
|
-
@twig.
|
252
|
+
allow(@twig).to receive(:all_branches) { [] }
|
253
|
+
allow(@twig).to receive(:branches) { [] }
|
227
254
|
|
228
|
-
@twig.list_branches.
|
255
|
+
expect(@twig.list_branches).to include('This repository has no branches')
|
229
256
|
end
|
230
257
|
end
|
231
258
|
|
@@ -238,12 +265,12 @@ describe Twig do
|
|
238
265
|
it 'calls `Twig::Branch#get_property`' do
|
239
266
|
property_name = 'foo'
|
240
267
|
property_value = 'bar'
|
241
|
-
Twig::Branch.
|
242
|
-
@branch.
|
268
|
+
expect(Twig::Branch).to receive(:new).with(@branch.name).and_return(@branch)
|
269
|
+
expect(@branch).to receive(:get_property).with(property_name).
|
243
270
|
and_return(property_value)
|
244
271
|
|
245
272
|
result = @twig.get_branch_property(@branch.name, property_name)
|
246
|
-
result.
|
273
|
+
expect(result).to eq(property_value)
|
247
274
|
end
|
248
275
|
end
|
249
276
|
|
@@ -253,8 +280,8 @@ describe Twig do
|
|
253
280
|
branch = Twig::Branch.new('test')
|
254
281
|
property_name = 'foo'
|
255
282
|
property_value = 'bar'
|
256
|
-
Twig::Branch.
|
257
|
-
branch.
|
283
|
+
expect(Twig::Branch).to receive(:new).with(branch.name).and_return(branch)
|
284
|
+
expect(branch).to receive(:set_property).with(property_name, property_value)
|
258
285
|
|
259
286
|
twig.set_branch_property(branch.name, property_name, property_value)
|
260
287
|
end
|
@@ -265,8 +292,8 @@ describe Twig do
|
|
265
292
|
twig = Twig.new
|
266
293
|
branch = Twig::Branch.new('test')
|
267
294
|
property_name = 'foo'
|
268
|
-
Twig::Branch.
|
269
|
-
branch.
|
295
|
+
expect(Twig::Branch).to receive(:new).with(branch.name).and_return(branch)
|
296
|
+
expect(branch).to receive(:unset_property).with(property_name)
|
270
297
|
|
271
298
|
twig.unset_branch_property(branch.name, property_name)
|
272
299
|
end
|