git_lib 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Git
4
+ VERSION = '1.2.0'
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './git/git.rb'
4
+ require_relative './git/git_branch.rb'
5
+ require_relative './git/git_conflict.rb'
6
+ require_relative './git/git_commit.rb'
7
+ require_relative './git/git_error.rb'
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../../../lib/git/git_branch.rb'
5
+
6
+ describe 'Git::GitBranch' do
7
+ it 'can be created' do
8
+ last_modified_date = Time.current
9
+ branch = Git::GitBranch.new('repository_name', 'name', last_modified_date, 'author_name', 'author@email.com')
10
+
11
+ expect(branch.repository_name).to eq('repository_name')
12
+ expect(branch.name).to eq('name')
13
+ expect(branch.last_modified_date).to eq(last_modified_date)
14
+ expect(branch.author_name).to eq('author_name')
15
+ expect(branch.author_email).to eq('author@email.com')
16
+ end
17
+
18
+ it 'implements regexp operator' do
19
+ branch = Git::GitBranch.new('repository_name', 'verylongname', Time.current, 'author_name', 'author@email.com')
20
+
21
+ expect(branch =~ /.*long.*/).to be_truthy
22
+ expect(branch =~ /nomatch/).to be_falsey
23
+ end
24
+
25
+ it 'implements equality operator' do
26
+ last_modified_date = Time.current
27
+ branch_a = Git::GitBranch.new('repository_name', 'name', last_modified_date, 'author_name', 'author@email.com')
28
+
29
+ branch_b = Git::GitBranch.new('repository_name', 'name', last_modified_date, 'author_name', 'author@email.com')
30
+ expect(branch_a).to eq(branch_b)
31
+
32
+ branch_c = Git::GitBranch.new('different', 'name', last_modified_date, 'author_name', 'author@email.com')
33
+ expect(branch_a).not_to eq(branch_c)
34
+
35
+ branch_d = Git::GitBranch.new('repository_name', 'different', last_modified_date, 'author_name', 'author@email.com')
36
+ expect(branch_a).not_to eq(branch_d)
37
+
38
+ branch_e = Git::GitBranch.new('repository_name', 'name', Time.current, 'author_name', 'author@email.com')
39
+ expect(branch_a).not_to eq(branch_e)
40
+
41
+ branch_f = Git::GitBranch.new('repository_name', 'name', last_modified_date, 'different', 'author@email.com')
42
+ expect(branch_a).not_to eq(branch_f)
43
+
44
+ branch_g = Git::GitBranch.new('repository_name', 'name', last_modified_date, 'author_name', 'different@email.com')
45
+ expect(branch_a).not_to eq(branch_g)
46
+ end
47
+
48
+ it 'returns its name when converted to string' do
49
+ branch = Git::GitBranch.new('repository_name', 'name', Time.current, 'author_name', 'author@email.com')
50
+ expect(branch.to_s).to eq('name')
51
+ end
52
+
53
+ it 'parses branch name from ref' do
54
+ expect(Git::GitBranch.name_from_ref('refs/heads/branch_name')).to eq('branch_name')
55
+ expect(Git::GitBranch.name_from_ref('branch_name')).to eq('branch_name')
56
+ end
57
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../../../lib/git/git_conflict.rb'
5
+
6
+ describe 'Git::GitConflict' do
7
+ it 'can be created' do
8
+ conflict = Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', ['file1', 'file2'])
9
+
10
+ expect(conflict.repository_name).to eq('repository_name')
11
+ expect(conflict.branch_a).to eq('branch_a')
12
+ expect(conflict.branch_b).to eq('branch_b')
13
+ expect(conflict.conflicting_files).to eq(['file1', 'file2'])
14
+ end
15
+
16
+ it 'cannot be created without conflicting files' do
17
+ expect { Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', nil) }.to \
18
+ raise_exception(ArgumentError, 'Must specify conflicting file list')
19
+ expect { Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', []) }.to \
20
+ raise_exception(ArgumentError, 'Must specify conflicting file list')
21
+ end
22
+
23
+ it 'implements equality operator' do
24
+ conflict_a = Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', ['file1', 'file2'])
25
+
26
+ conflict_b = Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', ['file1', 'file2'])
27
+ expect(conflict_a).to eq(conflict_b)
28
+
29
+ conflict_c = Git::GitConflict.new('different', 'branch_a', 'branch_b', ['file1', 'file2'])
30
+ expect(conflict_a).not_to eq(conflict_c)
31
+
32
+ conflict_d = Git::GitConflict.new('repository_name', 'different', 'branch_b', ['file1', 'file2'])
33
+ expect(conflict_a).not_to eq(conflict_d)
34
+
35
+ conflict_e = Git::GitConflict.new('repository_name', 'branch_a', 'different', ['file1', 'file2'])
36
+ expect(conflict_a).not_to eq(conflict_e)
37
+
38
+ conflict_f = Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', ['different', 'file2'])
39
+ expect(conflict_a).not_to eq(conflict_f)
40
+ end
41
+
42
+ it 'can determine if it contains the specified branch' do
43
+ conflict = Git::GitConflict.new('repository_name', 'branch_a', 'branch_b', ['file1', 'file2'])
44
+
45
+ expect(conflict.contains_branch('branch_a')).to be_truthy
46
+ expect(conflict.contains_branch('branch_b')).to be_truthy
47
+
48
+ expect(conflict.contains_branch('branch_c')).to be_falsey
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../../../lib/git/git_error.rb'
5
+
6
+ describe 'Git::GitError' do
7
+ it 'can be raised' do
8
+ expect { raise Git::GitError.new('command', 200, 'error_message') }.to \
9
+ raise_exception(Git::GitError, "Git command command failed with exit code 200. Message:\nerror_message")
10
+ end
11
+
12
+ it 'can be printed' do
13
+ begin
14
+ raise Git::GitError.new('command', 200, 'error_message')
15
+ rescue Git::GitError => e
16
+ expect(e.message).to eq("Git command command failed with exit code 200. Message:\nerror_message")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,436 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require_relative '../../../lib/git/git.rb'
5
+
6
+ # rubocop:disable Metrics/LineLength
7
+ describe 'Git::Git' do
8
+ include FakeFS::SpecHelpers
9
+
10
+ def create_mock_open_status(status)
11
+ status_object = double
12
+ allow(status_object).to receive(:success?) { status == 1 }
13
+ allow(status_object).to receive(:to_s) { status.to_s }
14
+ status_object
15
+ end
16
+
17
+ def mock_execute(stdout_andstderr_str, status, execution_count: 1, expected_command: anything)
18
+ # mock the call and repsonse to execute the git command
19
+ expect(Open3).to receive(:capture2e).exactly(execution_count).times do |*args|
20
+ if !expected_command.is_a?(RSpec::Mocks::ArgumentMatchers::AnyArgMatcher) && !expected_command.nil?
21
+ # remove the options hash, we are not going to verify it's contents
22
+ args.reject! { |arg| arg.is_a?(Hash) }
23
+
24
+ # confirm we got the args we expected
25
+ expect(args).to eq(expected_command.split(/ /))
26
+ end
27
+ [stdout_andstderr_str, create_mock_open_status(status)]
28
+ end
29
+ end
30
+
31
+ it 'can be created' do
32
+ git = Git::Git.new('repository_name')
33
+
34
+ expect(git.repository_url).to eq('git@github.com:repository_name.git')
35
+ expect(git.repository_path).to eq('/tmp/git/repository_name')
36
+ end
37
+
38
+ it 'can be created with a different cache path' do
39
+ git = Git::Git.new('repository_name', git_cache_path: './mycache')
40
+
41
+ expect(git.repository_url).to eq('git@github.com:repository_name.git')
42
+ expect(git.repository_path).to eq('./mycache/repository_name')
43
+ end
44
+
45
+ context 'with a git repository' do
46
+ before do
47
+ @git = Git::Git.new('repository_name')
48
+ end
49
+
50
+ it 'can execute a command' do
51
+ mock_execute('sample output', 1)
52
+ expect(@git.execute('sample command')).to eq('sample output')
53
+ end
54
+
55
+ it 'raises GitError when a command fails' do
56
+ mock_execute('sample output', 0)
57
+ expect { @git.execute('sample command') }.to raise_exception(Git::GitError)
58
+ end
59
+
60
+ describe 'clone_repository' do
61
+ it 'can clone into a new directory' do
62
+ response = \
63
+ "Cloning into '#{@git.repository_name}'..." \
64
+ 'remote: Counting objects: 1080, done.' \
65
+ 'remote: Compressing objects: 100% (83/83), done.' \
66
+ 'remote: Total 1080 (delta 34), reused 0 (delta 0), pack-reused 994' \
67
+ 'Receiving objects: 100% (1080/1080), 146.75 KiB | 0 bytes/s, done.' \
68
+ 'Resolving deltas: 100% (641/641), done.' \
69
+ 'Checking connectivity... done.'
70
+ mock_execute(response, 1)
71
+ @git.clone_repository('default_branch')
72
+ end
73
+
74
+ it 'can update a previously cloned repository' do
75
+ expect(@git).to receive(:reset).exactly(1).times
76
+ expect(@git).to receive(:checkout_branch)
77
+ mock_execute('Success', 1, execution_count: 3)
78
+ FileUtils.mkpath(@git.repository_path)
79
+ @git.clone_repository('default_branch')
80
+ end
81
+ end
82
+
83
+ describe 'push' do
84
+ it 'can push a branch' do
85
+ response = \
86
+ 'Counting objects: 20, done.' \
87
+ 'Delta compression using up to 8 threads.' \
88
+ 'Compressing objects: 100% (18/18), done.' \
89
+ 'Writing objects: 100% (20/20), 2.47 KiB | 0 bytes/s, done.' \
90
+ 'Total 20 (delta 11), reused 0 (delta 0)' \
91
+ "To #{@git.repository_url}" \
92
+ '19087ab..9cdd9db master -> master'
93
+ mock_execute(response, 1)
94
+ expect(@git.push).to eq(true)
95
+ end
96
+
97
+ it 'can push a branch using dry run' do
98
+ response = \
99
+ "To #{@git.repository_url}" \
100
+ '19087ab..9cdd9db master -> master'
101
+ mock_execute(response, 1, expected_command: '/usr/bin/git push --dry-run origin')
102
+ expect(@git.push(dry_run: true)).to eq(true)
103
+ end
104
+
105
+ it 'can detect if a push results in a no-op' do
106
+ mock_execute("Everything up-to-date\n", 1)
107
+ expect(@git.push).to eq(false)
108
+ end
109
+ end
110
+
111
+ describe 'checkout_branch' do
112
+ it 'can checkout a branch' do
113
+ expect(@git).to receive(:reset).exactly(2).times
114
+ mock_execute('Success', 1)
115
+ @git.checkout_branch('branch_name')
116
+ end
117
+
118
+ it 'escapes backticks in branch names' do
119
+ expect(@git).to receive(:reset).exactly(2).times
120
+ mock_execute('sample output', 1, expected_command: '/usr/bin/git checkout branch_\\`name')
121
+ @git.checkout_branch('branch_`name')
122
+ end
123
+ end
124
+
125
+ describe 'reset' do
126
+ it 'can reset a branch to HEAD of origin' do
127
+ expect(@git).to receive(:current_branch_name).and_return('master')
128
+ mock_execute("HEAD is now at beb5e09 Merge branch 'master'", 1)
129
+ @git.reset
130
+ end
131
+
132
+ it 'escapes backticks in branch names' do
133
+ expect(@git).to receive(:current_branch_name).and_return('branch_`name')
134
+ mock_execute('sample output', 1, expected_command: '/usr/bin/git reset --hard origin/branch_\\`name')
135
+ @git.reset
136
+ end
137
+ end
138
+
139
+ describe 'get_branch_list' do
140
+ it 'can parse a branch list' do
141
+ mock_execute(
142
+ "origin/test_1~2015-10-19 17:58:24 -0700~Nicholas Ellis~<nellis@invoca.com>\norigin/test_build~2015-10-19 15:03:22 -0700~Bob Smith~<bob@invoca.com>\norigin/test_build_b~2015-10-19 16:52:40 -0700~Nicholas Ellis~<nellis@invoca.com>",
143
+ 1
144
+ )
145
+
146
+ branch_list = []
147
+ branch_list << Git::GitBranch.new(
148
+ 'repository_name',
149
+ 'test_1',
150
+ DateTime.iso8601('2015-10-19T17:58:24-0700'),
151
+ 'Nicholas Ellis',
152
+ 'nellis@invoca.com'
153
+ )
154
+ branch_list << Git::GitBranch.new(
155
+ 'repository_name',
156
+ 'test_build',
157
+ DateTime.iso8601('2015-10-19T15:03:22-0700'),
158
+ 'Bob Smith',
159
+ 'bob@invoca.com'
160
+ )
161
+ branch_list << Git::GitBranch.new(
162
+ 'repository_name',
163
+ 'test_build_b',
164
+ DateTime.iso8601('2015-10-19T16:52:40-0700'),
165
+ 'Nicholas Ellis',
166
+ 'nellis@invoca.com'
167
+ )
168
+
169
+ expect(@git.branch_list).to eq(branch_list)
170
+ end
171
+ end
172
+
173
+ describe 'merge_branches' do
174
+ it 'returns false, with conflicts, if merge is not clean' do
175
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
176
+ mock_execute(
177
+ "From github.com:/Invoca/web\n" \
178
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
179
+ "warning: Cannot merge binary files: test/fixtures/whitepages.sql (HEAD vs. fedc8e0cfa136d5e1f84005ab6d82235122b0006)\n" \
180
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n" \
181
+ "CONFLICT (content): Merge conflict in test/workers/adwords_detail_worker_test.rb\n" \
182
+ "CONFLICT (modify/delete): pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js deleted in fedc8e0cfa136d5e1f84005ab6d82235122b0006 and modified in HEAD. Version HEAD of pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js left in tree.\n" \
183
+ " Auto-merging pegasus/backdraft/dist/pegasus_dashboard.js\n" \
184
+ "Automatic merge failed; fix conflicts and then commit the result.\n",
185
+ 0
186
+ )
187
+
188
+ conflict = Git::GitConflict.new(
189
+ 'repository_name',
190
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
191
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size',
192
+ ['test/workers/adwords_detail_worker_test.rb', 'pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js']
193
+ )
194
+ expect(
195
+ @git.merge_branches(
196
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
197
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size'
198
+ )
199
+ ).to eq([false, conflict])
200
+ end
201
+
202
+ it 'aborts unsuccessful merge if requested' do
203
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
204
+ mock_execute(
205
+ "From github.com:/Invoca/web\n" \
206
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
207
+ "warning: Cannot merge binary files: test/fixtures/whitepages.sql (HEAD vs. fedc8e0cfa136d5e1f84005ab6d82235122b0006)\n" \
208
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n" \
209
+ "CONFLICT (content): Merge conflict in test/workers/adwords_detail_worker_test.rb\n" \
210
+ "CONFLICT (modify/delete): pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js deleted in fedc8e0cfa136d5e1f84005ab6d82235122b0006 and modified in HEAD. Version HEAD of pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js left in tree.\n" \
211
+ " Auto-merging pegasus/backdraft/dist/pegasus_dashboard.js\n" \
212
+ 'Automatic merge failed; fix conflicts and then commit the result.',
213
+ 0
214
+ )
215
+ expect(@git).to receive(:reset)
216
+
217
+ conflict = Git::GitConflict.new(
218
+ 'repository_name',
219
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
220
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size',
221
+ [
222
+ 'test/workers/adwords_detail_worker_test.rb',
223
+ 'pegasus/backdraft/pegasus_dashboard/spec/views/call_cost_tile_spec.js'
224
+ ]
225
+ )
226
+ expect(
227
+ @git.merge_branches(
228
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
229
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size',
230
+ keep_changes: false
231
+ )
232
+ ).to eq([false, conflict])
233
+ end
234
+
235
+ it 'aborts successful merge if requested' do
236
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
237
+ mock_execute(
238
+ "From github.com:/Invoca/web\n" \
239
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
240
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n" \
241
+ " Auto-merging pegasus/backdraft/dist/pegasus_dashboard.js\n",
242
+ 1
243
+ )
244
+ expect(@git).to receive(:reset)
245
+
246
+ expect(
247
+ @git.merge_branches(
248
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
249
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size',
250
+ keep_changes: false
251
+ )
252
+ ).to eq([true, nil])
253
+ end
254
+
255
+ it 'returns true, with no conflicts, if merge is clean' do
256
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
257
+ mock_execute(
258
+ "From github.com:/Invoca/web\n" \
259
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
260
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n" \
261
+ " Auto-merging pegasus/backdraft/dist/pegasus_dashboard.js\n",
262
+ 1
263
+ )
264
+
265
+ expect(
266
+ @git.merge_branches(
267
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
268
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size'
269
+ )
270
+ ).to eq([true, nil])
271
+ end
272
+
273
+ it 'returns false, with no conflicts, if nothing is merged' do
274
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
275
+ mock_execute(
276
+ "From github.com:mikeweaver/git-conflict-detector\n" \
277
+ " * branch master -> FETCH_HEAD\n" \
278
+ "Already up-to-date.\n",
279
+ 1
280
+ )
281
+ expect(
282
+ @git.merge_branches(
283
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
284
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size'
285
+ )
286
+ ).to eq([false, nil])
287
+ end
288
+
289
+ it 'checks out branch if needed' do
290
+ expect(@git).to receive(:current_branch_name).and_return('not_the_right_branch')
291
+ expect(@git).to receive(:checkout_branch)
292
+ mock_execute(
293
+ "From github.com:mikeweaver/git-conflict-detector\n" \
294
+ " * branch master -> FETCH_HEAD\n" \
295
+ "Already up-to-date.\n",
296
+ 1
297
+ )
298
+ expect(
299
+ @git.merge_branches(
300
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
301
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size'
302
+ )
303
+ ).to eq([false, nil])
304
+ end
305
+
306
+ it 'merges a tag, if requested' do
307
+ expect(@git).to receive(:current_branch_name).and_return('91/eb/WEB-1723_Ringswitch_DB_Conn_Loss')
308
+ mock_execute(
309
+ "From github.com:/Invoca/web\n" \
310
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
311
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n" \
312
+ " Auto-merging pegasus/backdraft/dist/pegasus_dashboard.js\n",
313
+ 1
314
+ )
315
+
316
+ expect(
317
+ @git.merge_branches(
318
+ '91/eb/WEB-1723_Ringswitch_DB_Conn_Loss',
319
+ '85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size',
320
+ source_tag_name: 'tag_name'
321
+ )
322
+ ).to eq([true, nil])
323
+ end
324
+
325
+ it 'escapes backticks and spaces in branch names but not commit messages' do
326
+ expect(@git).to receive(:current_branch_name).and_return('target`name')
327
+ mock_execute(
328
+ "From github.com:/Invoca/web\n" \
329
+ " * branch 85/t/trello_adwords_dashboard_tiles_auto_adjust_font_size -> FETCH_HEAD\n" \
330
+ "Auto-merging test/workers/adwords_detail_worker_test.rb\n",
331
+ 1,
332
+ expected_command: '/usr/bin/git merge --no-edit -m "commit `message" origin/source\\`name\ space'
333
+ )
334
+
335
+ @git.merge_branches(
336
+ 'target`name',
337
+ 'source`name space',
338
+ commit_message: 'commit `message'
339
+ )
340
+ end
341
+ end
342
+
343
+ describe 'lookup_tag' do
344
+ it 'can lookup a tag' do
345
+ mock_execute("tag-exists\n", 1)
346
+ expect(@git.lookup_tag('tag-e*')).to eq('tag-exists')
347
+ end
348
+
349
+ it 'raises when the tag cannot be found' do
350
+ mock_execute('fatal: No names found, cannot describe anything.', 0)
351
+ expect { @git.lookup_tag('does-not-exist') }.to raise_exception(Git::GitError)
352
+ end
353
+ end
354
+
355
+ describe 'file_diff_branch_with_ancestor' do
356
+ it 'can diff the branch' do
357
+ mock_execute("file1.txt\nfile2.txt\n", 1)
358
+ expect(@git.file_diff_branch_with_ancestor('branch', 'ancestor_branch')).to eq(['file1.txt', 'file2.txt'])
359
+ end
360
+
361
+ it 'can handle an up to date branch' do
362
+ mock_execute('', 1)
363
+ expect(@git.file_diff_branch_with_ancestor('branch', 'ancestor_branch')).to eq([])
364
+ end
365
+
366
+ it 'escapes backticks in branch names' do
367
+ mock_execute(
368
+ "file1.txt\nfile2.txt\n",
369
+ 1,
370
+ expected_command: '/usr/bin/git diff --name-only $(git merge-base origin/ancestor\\`_branch origin/branch\\`name)..origin/branch\\`name'
371
+ )
372
+ @git.file_diff_branch_with_ancestor('branch`name', 'ancestor`_branch')
373
+ end
374
+ end
375
+
376
+ describe 'commit_diff_refs' do
377
+ it 'can diff a branch' do
378
+ mocked_output = ["efd778098239838c165ffab2f12ad293f32824c8\tAuthor 1\tauthor1@email.com\t2016-07-14T10:09:45-07:00\tMerge branch 'production'\n",
379
+ "667f3e5347c48c04663209682642fd8d6d93fde2\tAuthor 2\tauthor2@email.com\t2016-07-14T16:46:35-07:00\tMerge pull request #5584 from Owner/repo/dimension_repair\n"].join
380
+ expected_array = [Git::GitCommit.new('efd778098239838c165ffab2f12ad293f32824c8', "Merge branch 'production'", nil, 'Author 1', 'author1@email.com'),
381
+ Git::GitCommit.new('667f3e5347c48c04663209682642fd8d6d93fde2', 'Merge pull request #5584 from Owner/repo/dimension_repair', nil, 'Author 2', 'author2@email.com')]
382
+ mock_execute(
383
+ mocked_output,
384
+ 1,
385
+ expected_command: "/usr/bin/git log --format=%H\t%an\t%ae\t%aI\t%s --no-color origin/ancestor_branch..origin/branch"
386
+ )
387
+ expect(@git.commit_diff_refs('branch', 'ancestor_branch')).to eq(expected_array)
388
+ end
389
+
390
+ it 'can handle a comparison with no changes' do
391
+ mock_execute('', 1)
392
+ expect(@git.commit_diff_refs('branch', 'ancestor_branch')).to eq([])
393
+ end
394
+
395
+ it 'can fetch before doing the comparison' do
396
+ mock_execute('', 1)
397
+ expect(@git).to receive(:fetch_all)
398
+ expect(@git.commit_diff_refs('branch', 'ancestor_branch', fetch: true)).to eq([])
399
+ end
400
+
401
+ it 'can diff a sha with a branch' do
402
+ mock_execute(
403
+ '',
404
+ 1,
405
+ expected_command: "/usr/bin/git log --format=%H\t%an\t%ae\t%aI\t%s --no-color origin/ancestor_branch..e2a7e607745d63da4d7f8486e0619e91a410f796"
406
+ )
407
+ @git.commit_diff_refs('e2a7e607745d63da4d7f8486e0619e91a410f796', 'ancestor_branch')
408
+ end
409
+
410
+ it 'can diff a sha with a sha' do
411
+ mock_execute(
412
+ '',
413
+ 1,
414
+ expected_command: "/usr/bin/git log --format=%H\t%an\t%ae\t%aI\t%s --no-color c5e8de4eb36a2d1b9f66543966ede9ce9cc28a89..e2a7e607745d63da4d7f8486e0619e91a410f796"
415
+ )
416
+ @git.commit_diff_refs('e2a7e607745d63da4d7f8486e0619e91a410f796', 'c5e8de4eb36a2d1b9f66543966ede9ce9cc28a89')
417
+ end
418
+
419
+ it 'escapes backticks in ref names' do
420
+ mock_execute(
421
+ '',
422
+ 1,
423
+ expected_command: "/usr/bin/git log --format=%H\t%an\t%ae\t%aI\t%s --no-color origin/ancestor\\`_branch..origin/branch\\`name"
424
+ )
425
+ @git.commit_diff_refs('branch`name', 'ancestor`_branch')
426
+ end
427
+ end
428
+
429
+ describe 'get_current_branch_name' do
430
+ it 'can get the branch name' do
431
+ mock_execute("path/branch\n", 1)
432
+ expect(@git.current_branch_name).to eq('path/branch')
433
+ end
434
+ end
435
+ end
436
+ end