git-duet 0.1.1
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/.gitignore +5 -0
- data/.jrubyrc +1 -0
- data/.rbenv-version +1 -0
- data/.rspec +2 -0
- data/.simplecov +5 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +268 -0
- data/Rakefile +10 -0
- data/bin/git-duet +3 -0
- data/bin/git-duet-commit +3 -0
- data/bin/git-duet-install-hook +3 -0
- data/bin/git-duet-pre-commit +3 -0
- data/bin/git-duet-pre-commit-tk +3 -0
- data/bin/git-solo +3 -0
- data/git-duet.gemspec +36 -0
- data/lib/git-duet.rb +1 -0
- data/lib/git/duet.rb +8 -0
- data/lib/git/duet/author_mapper.rb +77 -0
- data/lib/git/duet/cli.rb +119 -0
- data/lib/git/duet/command_methods.rb +109 -0
- data/lib/git/duet/commit_command.rb +76 -0
- data/lib/git/duet/duet_command.rb +49 -0
- data/lib/git/duet/install_hook_command.rb +33 -0
- data/lib/git/duet/key_error.rb +3 -0
- data/lib/git/duet/pre_commit_command.rb +43 -0
- data/lib/git/duet/script_die_error.rb +11 -0
- data/lib/git/duet/solo_command.rb +45 -0
- data/lib/git/duet/version.rb +7 -0
- data/spec/integration/end_to_end_spec.rb +304 -0
- data/spec/lib/git/duet/author_mapper_spec.rb +170 -0
- data/spec/lib/git/duet/cli_spec.rb +46 -0
- data/spec/lib/git/duet/command_methods_spec.rb +51 -0
- data/spec/lib/git/duet/duet_command_spec.rb +88 -0
- data/spec/lib/git/duet/pre_commit_command_spec.rb +36 -0
- data/spec/lib/git/duet/solo_command_spec.rb +115 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/author_mapper_helper.rb +28 -0
- metadata +172 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'git/duet'
|
2
|
+
require 'git/duet/author_mapper'
|
3
|
+
require 'git/duet/command_methods'
|
4
|
+
|
5
|
+
class Git::Duet::SoloCommand
|
6
|
+
include Git::Duet::CommandMethods
|
7
|
+
|
8
|
+
def initialize(soloist, quiet = false, global = false)
|
9
|
+
@soloist = soloist
|
10
|
+
@quiet = !!quiet
|
11
|
+
@global = !!global
|
12
|
+
@author_mapper = Git::Duet::AuthorMapper.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute!
|
16
|
+
set_soloist_as_git_config_user
|
17
|
+
unset_committer_vars
|
18
|
+
report_env_vars
|
19
|
+
write_env_vars
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
attr_accessor :soloist, :author_mapper
|
24
|
+
|
25
|
+
def set_soloist_as_git_config_user
|
26
|
+
exec_check("git config #{@global ? '--global ' : ''}user.name '#{soloist_info[:name]}'")
|
27
|
+
exec_check("git config #{@global ? '--global ' : ''}user.email '#{soloist_info[:email]}'")
|
28
|
+
end
|
29
|
+
|
30
|
+
def unset_committer_vars
|
31
|
+
exec_check("git config #{@global ? '--global ' : ''}--unset-all duet.env.git-committer-name", [0, 5])
|
32
|
+
exec_check("git config #{@global ? '--global ' : ''}--unset-all duet.env.git-committer-email", [0, 5])
|
33
|
+
end
|
34
|
+
|
35
|
+
def var_map
|
36
|
+
{
|
37
|
+
'GIT_AUTHOR_NAME' => soloist_info[:name],
|
38
|
+
'GIT_AUTHOR_EMAIL' => soloist_info[:email]
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def soloist_info
|
43
|
+
@soloist_info ||= author_mapper.map(@soloist).fetch(@soloist)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
describe 'git-duet end to end', :integration => true do
|
4
|
+
EMAIL_LOOKUP_SCRIPT = <<-EOF.gsub(/^ /, '')
|
5
|
+
#!/usr/bin/env ruby
|
6
|
+
addr = {
|
7
|
+
'jd' => 'jane_doe@lookie.me.local',
|
8
|
+
'fb' => 'fb9000@dalek.info.local'
|
9
|
+
}[ARGV.first]
|
10
|
+
puts addr
|
11
|
+
EOF
|
12
|
+
|
13
|
+
def install_hook
|
14
|
+
Dir.chdir(@repo_dir)
|
15
|
+
`git duet-install-hook -q`
|
16
|
+
end
|
17
|
+
|
18
|
+
def uninstall_hook
|
19
|
+
FileUtils.rm_f('.git/hooks/pre-commit')
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_an_edit
|
23
|
+
Dir.chdir(@repo_dir)
|
24
|
+
File.open('file.txt', 'w') { |f| f.puts "foo-#{rand(100000)}" }
|
25
|
+
`git add file.txt`
|
26
|
+
end
|
27
|
+
|
28
|
+
before :all do
|
29
|
+
@startdir = Dir.pwd
|
30
|
+
@tmpdir = Dir.mktmpdir('git-duet-specs')
|
31
|
+
@git_authors = File.join(@tmpdir, '.git-authors')
|
32
|
+
@email_lookup_path = File.join(@tmpdir, 'email-lookup')
|
33
|
+
File.open(@git_authors, 'w') do |f|
|
34
|
+
f.puts YAML.dump(
|
35
|
+
'pairs' => {
|
36
|
+
'jd' => 'Jane Doe',
|
37
|
+
'fb' => 'Frances Bar',
|
38
|
+
'zp' => 'Zubaz Pants'
|
39
|
+
},
|
40
|
+
'email' => {
|
41
|
+
'domain' => 'hamster.info.local'
|
42
|
+
},
|
43
|
+
'email_addresses' => {
|
44
|
+
'jd' => 'jane@hamsters.biz.local'
|
45
|
+
}
|
46
|
+
)
|
47
|
+
end
|
48
|
+
ENV['GIT_DUET_AUTHORS_FILE'] = @git_authors
|
49
|
+
ENV['PATH'] = "#{File.expand_path('../../../bin', __FILE__)}:#{ENV['PATH']}"
|
50
|
+
File.open(@email_lookup_path, 'w') { |f| f.puts EMAIL_LOOKUP_SCRIPT }
|
51
|
+
FileUtils.chmod(0755, @email_lookup_path)
|
52
|
+
@repo_dir = File.join(@tmpdir, 'foo')
|
53
|
+
Dir.chdir(@tmpdir)
|
54
|
+
`git init #{@repo_dir}`
|
55
|
+
end
|
56
|
+
|
57
|
+
after :all do
|
58
|
+
Dir.chdir(@startdir)
|
59
|
+
if ENV['RSPEC_NO_CLEANUP']
|
60
|
+
File.open('integration-end-to-end-test-dir.txt', 'w') { |f| f.puts @tmpdir }
|
61
|
+
else
|
62
|
+
FileUtils.rm_rf(@tmpdir)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when installing the pre-commit hook' do
|
67
|
+
before(:each) { install_hook }
|
68
|
+
after(:each) { uninstall_hook }
|
69
|
+
|
70
|
+
it 'should write the hook to the `pre-commit` hook file' do
|
71
|
+
File.exist?('.git/hooks/pre-commit').should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should make the `pre-commit` hook file executable' do
|
75
|
+
File.executable?('.git/hooks/pre-commit').should be_true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when setting the author via solo' do
|
80
|
+
before :each do
|
81
|
+
Dir.chdir(@repo_dir)
|
82
|
+
`git solo jd -q`
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should set the git user name' do
|
86
|
+
`git config user.name`.chomp.should == 'Jane Doe'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set the git user email' do
|
90
|
+
`git config user.email`.chomp.should == 'jane@hamsters.biz.local'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should cache the git user name as author name' do
|
94
|
+
`git config duet.env.git-author-name`.chomp.should == 'Jane Doe'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should cache the git user email as author email' do
|
98
|
+
`git config duet.env.git-author-email`.chomp.should == 'jane@hamsters.biz.local'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
context 'when an external email lookup is provided' do
|
104
|
+
before :each do
|
105
|
+
@old_email_lookup = ENV.delete('GIT_DUET_EMAIL_LOOKUP_COMMAND')
|
106
|
+
ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND'] = @email_lookup_path
|
107
|
+
end
|
108
|
+
|
109
|
+
after :each do
|
110
|
+
ENV['GIT_DUET_EMAIL_LOOKUP_COMMAND'] = @old_email_lookup
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when setting the author via solo' do
|
114
|
+
before :each do
|
115
|
+
Dir.chdir(@repo_dir)
|
116
|
+
`git solo jd -q`
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should set the author email address given by the external email lookup' do
|
120
|
+
`git config duet.env.git-author-email`.chomp.should == 'jane_doe@lookie.me.local'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when setting author and committer via duet' do
|
125
|
+
before :each do
|
126
|
+
Dir.chdir(@repo_dir)
|
127
|
+
`git duet jd fb -q`
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should set the author email address given by the external email lookup' do
|
131
|
+
`git config duet.env.git-author-email`.chomp.should == 'jane_doe@lookie.me.local'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should set the committer email address given by the external email lookup' do
|
135
|
+
`git config duet.env.git-committer-email`.chomp.should == 'fb9000@dalek.info.local'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when a custom email template is provided' do
|
141
|
+
before :each do
|
142
|
+
authors_cfg = YAML.load_file(@git_authors)
|
143
|
+
@name_suffix = rand(9999)
|
144
|
+
authors_cfg['email_template'] =
|
145
|
+
%Q^<%= '' << author.split.first.downcase << ^ <<
|
146
|
+
%Q^author.split.last[0].chr.downcase << '#{@name_suffix}@mompopshop.local' %>^
|
147
|
+
File.open(@git_authors, 'w') do |f|
|
148
|
+
f.puts YAML.dump(authors_cfg)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
after :each do
|
153
|
+
authors_cfg = YAML.load_file(@git_authors)
|
154
|
+
authors_cfg.delete('email_template')
|
155
|
+
File.open(@git_authors, 'w') do |f|
|
156
|
+
f.puts YAML.dump(authors_cfg)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'after running git-solo' do
|
161
|
+
before :each do
|
162
|
+
Dir.chdir(@repo_dir)
|
163
|
+
`git solo zp -q`
|
164
|
+
make_an_edit
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should use the email template to construct the author email' do
|
168
|
+
`git duet-commit -q -m 'Testing custom email template for author'`
|
169
|
+
`git log -1 --format='%an <%ae>'`.chomp.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should use the email template to construct the committer email' do
|
173
|
+
`git duet-commit -q -m 'Testing custom email template for committer'`
|
174
|
+
`git log -1 --format='%cn <%ce>'`.chomp.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'after running git-duet' do
|
179
|
+
before :each do
|
180
|
+
Dir.chdir(@repo_dir)
|
181
|
+
`git duet zp fb -q`
|
182
|
+
make_an_edit
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should use the email template to construct the author email' do
|
186
|
+
`git duet-commit -q -m 'Testing custom email template for author'`
|
187
|
+
`git log -1 --format='%an <%ae>'`.chomp.should == "Zubaz Pants <zubazp#{@name_suffix}@mompopshop.local>"
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should use the email template to construct the committer email' do
|
191
|
+
`git duet-commit -q -m 'Testing custom email template for committer'`
|
192
|
+
`git log -1 --format='%cn <%ce>'`.chomp.should == "Frances Bar <francesb#{@name_suffix}@mompopshop.local>"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'when setting author and committer via duet' do
|
198
|
+
before :each do
|
199
|
+
Dir.chdir(@repo_dir)
|
200
|
+
`git duet jd fb -q`
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should set the git user name' do
|
204
|
+
`git config user.name`.chomp.should == 'Jane Doe'
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should set the git user email' do
|
208
|
+
`git config user.email`.chomp.should == 'jane@hamsters.biz.local'
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should cache the git committer name' do
|
212
|
+
`git config duet.env.git-committer-name`.chomp.should == 'Frances Bar'
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should cache the git committer email' do
|
216
|
+
`git config duet.env.git-committer-email`.chomp.should == 'f.bar@hamster.info.local'
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'when committing via git-duet-commit' do
|
221
|
+
context 'after running git-duet' do
|
222
|
+
before :each do
|
223
|
+
Dir.chdir(@repo_dir)
|
224
|
+
`git duet jd fb -q`
|
225
|
+
make_an_edit
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should list the alpha of the duet as author in the log' do
|
229
|
+
`git duet-commit -q -m 'Testing set of alpha as author'`
|
230
|
+
`git log -1 --format='%an <%ae>'`.chomp.should == 'Jane Doe <jane@hamsters.biz.local>'
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should list the omega of the duet as committer in the log' do
|
234
|
+
`git duet-commit -q -m 'Testing set of omega as committer'`
|
235
|
+
`git log -1 --format='%cn <%ce>'`.chomp.should == 'Frances Bar <f.bar@hamster.info.local>'
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'with the pre-commit hook in place' do
|
239
|
+
before :each do
|
240
|
+
`git commit -m 'Committing before installing the hook'`
|
241
|
+
@latest_sha1 = `git log -1 --format=%H`.chomp
|
242
|
+
make_an_edit
|
243
|
+
install_hook
|
244
|
+
`git config --unset-all duet.env.mtime`
|
245
|
+
ENV['GIT_DUET_QUIET'] = '1'
|
246
|
+
end
|
247
|
+
|
248
|
+
after :each do
|
249
|
+
uninstall_hook
|
250
|
+
ENV.delete('GIT_DUET_QUIET')
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should fire the hook and reject the commit' do
|
254
|
+
`git duet-commit -q -m 'Testing hook firing'`
|
255
|
+
`git log -1 --format=%H`.chomp.should == @latest_sha1
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
context 'after running git-solo' do
|
261
|
+
before :each do
|
262
|
+
Dir.chdir(@repo_dir)
|
263
|
+
`git solo jd -q`
|
264
|
+
make_an_edit
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'should list the soloist as author in the log' do
|
268
|
+
`git duet-commit -m 'Testing set of soloist as author' 2>/dev/null`
|
269
|
+
`git log -1 --format='%an <%ae>'`.chomp.should == 'Jane Doe <jane@hamsters.biz.local>'
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should list the soloist as committer in the log' do
|
273
|
+
`git duet-commit -m 'Testing set of soloist as committer' 2>/dev/null`
|
274
|
+
`git log -1 --format='%cn <%ce>'`.chomp.should == 'Jane Doe <jane@hamsters.biz.local>'
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'should not include "Signed-off-by" in the commit message' do
|
278
|
+
`git duet-commit -m 'Testing ommitting signoff when only one author' 2>/dev/null`
|
279
|
+
`grep 'Signed-off-by' .git/COMMIT_EDITMSG`.chomp.should == ''
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'with the pre-commit hook in place' do
|
283
|
+
before :each do
|
284
|
+
`git commit -m 'Committing before installing the hook'`
|
285
|
+
@latest_sha1 = `git log -1 --format=%H`.chomp
|
286
|
+
make_an_edit
|
287
|
+
install_hook
|
288
|
+
`git config --unset-all duet.env.mtime`
|
289
|
+
ENV['GIT_DUET_QUIET'] = '1'
|
290
|
+
end
|
291
|
+
|
292
|
+
after :each do
|
293
|
+
uninstall_hook
|
294
|
+
ENV.delete('GIT_DUET_QUIET')
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should fire the hook and reject the commit' do
|
298
|
+
`git duet-commit -q -m 'Testing hook firing'`
|
299
|
+
`git log -1 --format=%H`.chomp.should == @latest_sha1
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'git/duet/author_mapper'
|
2
|
+
|
3
|
+
describe Git::Duet::AuthorMapper do
|
4
|
+
before :each do
|
5
|
+
subject.instance_variable_set(:@cfg, {
|
6
|
+
'authors' => {
|
7
|
+
'jd' => 'Jane Doe; jdoe',
|
8
|
+
'fb' => 'Frances Bar; frances',
|
9
|
+
'qx' => 'Quincy Xavier; qx',
|
10
|
+
'hb' => 'Hampton Bones'
|
11
|
+
},
|
12
|
+
'email' => {
|
13
|
+
'domain' => 'awesometown.me'
|
14
|
+
},
|
15
|
+
'email_addresses' => {
|
16
|
+
'jd' => 'jane@awesome.biz'
|
17
|
+
}
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
after :each do
|
22
|
+
ENV.delete('GIT_DUET_AUTHORS_FILE')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should use an authors file given at initialization' do
|
26
|
+
instance = described_class.new('/blarggie/blarggie/new/friend/.git-authors')
|
27
|
+
instance.authors_file.should == '/blarggie/blarggie/new/friend/.git-authors'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should use the `GIT_DUET_AUTHORS_FILE` if provided' do
|
31
|
+
ENV['GIT_DUET_AUTHORS_FILE'] = '/fizzle/bizzle/.git-authors'
|
32
|
+
instance = described_class.new
|
33
|
+
instance.authors_file.should == '/fizzle/bizzle/.git-authors'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should fall back to using `~/.git-authors` for the author map' do
|
37
|
+
subject.authors_file.should == File.join(ENV['HOME'], '.git-authors')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should map initials to name -> email pairs' do
|
41
|
+
subject.map('jd').fetch('jd').should == {
|
42
|
+
:name => 'Jane Doe',
|
43
|
+
:email => 'jane@awesome.biz'
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should construct default email addresses from first initial and last name plus domain' do
|
48
|
+
subject.map('hb').should == {
|
49
|
+
'hb' => {
|
50
|
+
:name => 'Hampton Bones',
|
51
|
+
:email => 'h.bones@awesometown.me'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should construct email addresses from optional username (if given) plus domain' do
|
57
|
+
subject.map('fb').should == {
|
58
|
+
'fb' => {
|
59
|
+
:name => 'Frances Bar',
|
60
|
+
:email => 'frances@awesometown.me'
|
61
|
+
}
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should use an explicitly-configured email address if given' do
|
66
|
+
subject.map('jd').should == {
|
67
|
+
'jd' => {
|
68
|
+
:name => 'Jane Doe',
|
69
|
+
:email => 'jane@awesome.biz'
|
70
|
+
}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should map any number of initials to name -> email pairs' do
|
75
|
+
subject.map('jd', 'fb', 'qx', 'hb').should == {
|
76
|
+
'jd' => {
|
77
|
+
:name => 'Jane Doe',
|
78
|
+
:email => 'jane@awesome.biz'
|
79
|
+
},
|
80
|
+
'fb' => {
|
81
|
+
:name => 'Frances Bar',
|
82
|
+
:email => 'frances@awesometown.me'
|
83
|
+
},
|
84
|
+
'qx' => {
|
85
|
+
:name => 'Quincy Xavier',
|
86
|
+
:email => 'qx@awesometown.me'
|
87
|
+
},
|
88
|
+
'hb' => {
|
89
|
+
:name => 'Hampton Bones',
|
90
|
+
:email => 'h.bones@awesometown.me'
|
91
|
+
}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when using a `~/.pairs` config' do
|
96
|
+
before :each do
|
97
|
+
subject.stub(:cfg => {
|
98
|
+
'pairs' => {
|
99
|
+
'jd' => 'Jane Doe; jdoe',
|
100
|
+
'fb' => 'Frances Bar; frances',
|
101
|
+
'qx' => 'Quincy Xavier; qx',
|
102
|
+
'hb' => 'Hampton Bones'
|
103
|
+
},
|
104
|
+
'email' => {
|
105
|
+
'domain' => 'awesometown.me'
|
106
|
+
},
|
107
|
+
'email_addresses' => {
|
108
|
+
'jd' => 'jane@awesome.biz'
|
109
|
+
}
|
110
|
+
})
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should map initials to name -> email pairs' do
|
114
|
+
subject.map('jd').fetch('jd').should == {
|
115
|
+
:name => 'Jane Doe',
|
116
|
+
:email => 'jane@awesome.biz'
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should map any number of initials to name -> email pairs' do
|
121
|
+
subject.map('jd', 'fb', 'qx', 'hb').should == {
|
122
|
+
'jd' => {
|
123
|
+
:name => 'Jane Doe',
|
124
|
+
:email => 'jane@awesome.biz'
|
125
|
+
},
|
126
|
+
'fb' => {
|
127
|
+
:name => 'Frances Bar',
|
128
|
+
:email => 'frances@awesometown.me'
|
129
|
+
},
|
130
|
+
'qx' => {
|
131
|
+
:name => 'Quincy Xavier',
|
132
|
+
:email => 'qx@awesometown.me'
|
133
|
+
},
|
134
|
+
'hb' => {
|
135
|
+
:name => 'Hampton Bones',
|
136
|
+
:email => 'h.bones@awesometown.me'
|
137
|
+
}
|
138
|
+
}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'when the authors file does not exist' do
|
143
|
+
let :bad_path do
|
144
|
+
"/its/#{rand(999)}/hosed/#{rand(999)}/captain/#{rand(999)}/.git-authors"
|
145
|
+
end
|
146
|
+
|
147
|
+
subject do
|
148
|
+
described_class.new(bad_path)
|
149
|
+
end
|
150
|
+
|
151
|
+
before :each do
|
152
|
+
subject.instance_variable_set(:@cfg, nil)
|
153
|
+
IO.stub(:read).with(bad_path).and_raise(
|
154
|
+
Errno::ENOENT.new("No such file or directory - #{bad_path}")
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should warn about missing authors file' do
|
159
|
+
STDERR.should_receive(:puts).with(
|
160
|
+
/Missing or corrupt authors file.*#{bad_path}/i
|
161
|
+
)
|
162
|
+
expect { subject.map('zzz') }.to raise_error
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should raise a ScriptDieError' do
|
166
|
+
STDERR.stub(:puts)
|
167
|
+
expect { subject.map('zzz') }.to raise_error(Git::Duet::ScriptDieError)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|