git_lib 1.2.0
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.
- checksums.yaml +7 -0
- data/.dependabot/config.yml +10 -0
- data/.github/workflows/gem_release.yml +37 -0
- data/.gitignore +53 -0
- data/.jenkins/Jenkinsfile +72 -0
- data/.jenkins/ruby_build_pod.yml +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +43 -0
- data/.ruby-version +1 -0
- data/Appraisals +13 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +121 -0
- data/README.md +9 -0
- data/Rakefile +17 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_4.gemfile +21 -0
- data/gemfiles/rails_5.gemfile +21 -0
- data/gemfiles/rails_6.gemfile +21 -0
- data/git_lib.gemspec +25 -0
- data/lib/git/git.rb +186 -0
- data/lib/git/git_branch.rb +35 -0
- data/lib/git/git_commit.rb +23 -0
- data/lib/git/git_conflict.rb +29 -0
- data/lib/git/git_error.rb +14 -0
- data/lib/git/git_test_helpers.rb +38 -0
- data/lib/git/version.rb +5 -0
- data/lib/git_lib.rb +7 -0
- data/spec/lib/git/git_branch_spec.rb +57 -0
- data/spec/lib/git/git_conflict_spec.rb +50 -0
- data/spec/lib/git/git_error_spec.rb +19 -0
- data/spec/lib/git/git_spec.rb +436 -0
- data/spec/spec_helper.rb +30 -0
- metadata +100 -0
data/lib/git/version.rb
ADDED
data/lib/git_lib.rb
ADDED
@@ -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
|