git_helper 1.2.0 → 2.0.2

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +17 -13
  3. data/README.md +27 -33
  4. data/Rakefile +1 -37
  5. data/bin/git-helper +10 -28
  6. data/lib/git_helper.rb +3 -5
  7. data/lib/git_helper/change_remote.rb +53 -40
  8. data/lib/git_helper/checkout_default.rb +1 -1
  9. data/lib/git_helper/clean_branches.rb +1 -4
  10. data/lib/git_helper/code_request.rb +95 -0
  11. data/lib/git_helper/empty_commit.rb +1 -1
  12. data/lib/git_helper/forget_local_commits.rb +7 -0
  13. data/lib/git_helper/gitlab_client.rb +0 -1
  14. data/lib/git_helper/highline_cli.rb +72 -6
  15. data/lib/git_helper/local_code.rb +124 -0
  16. data/lib/git_helper/merge_request.rb +57 -126
  17. data/lib/git_helper/new_branch.rb +2 -11
  18. data/lib/git_helper/octokit_client.rb +0 -1
  19. data/lib/git_helper/pull_request.rb +45 -110
  20. data/lib/git_helper/version.rb +1 -1
  21. data/spec/git_helper/change_remote_spec.rb +173 -0
  22. data/spec/git_helper/checkout_default_spec.rb +19 -0
  23. data/spec/git_helper/clean_branches_spec.rb +19 -0
  24. data/spec/git_helper/code_request_spec.rb +259 -0
  25. data/spec/git_helper/empty_commit_spec.rb +19 -0
  26. data/spec/git_helper/forget_local_commits_spec.rb +19 -0
  27. data/spec/git_helper/git_config_reader_spec.rb +60 -0
  28. data/spec/git_helper/gitlab_client_spec.rb +26 -0
  29. data/spec/git_helper/highline_cli_spec.rb +215 -0
  30. data/spec/git_helper/local_code_spec.rb +231 -0
  31. data/spec/git_helper/merge_request_spec.rb +234 -0
  32. data/spec/git_helper/new_branch_spec.rb +44 -0
  33. data/spec/git_helper/octokit_client_spec.rb +26 -0
  34. data/spec/git_helper/pull_request_spec.rb +246 -0
  35. data/spec/spec_helper.rb +0 -7
  36. metadata +41 -24
@@ -0,0 +1,231 @@
1
+ require 'spec_helper'
2
+ require 'git_helper'
3
+
4
+ describe GitHelper::LocalCode do
5
+ let(:response) { double(:response, readline: true, to_i: 5) }
6
+ let(:local_codeent) { double(:local_code, ask: response) }
7
+ let(:ssh_remote) { 'origin\tgit@github.com:emmasax4/git_helper.git (fetch)' }
8
+ let(:https_remote) { 'origin\thttps://github.com/emmasax4/git_helper.git (fetch)' }
9
+ let(:github_remotes) { ['origin\tgit@github.com:emmasax4/git_helper.git (fetch)', 'origin\thttps://github.com/emmasax4/git_helper.git (fetch)' ] }
10
+ let(:gitlab_remotes) { ['origin\tgit@gitlab.com:emmasax4/git_helper.git (fetch)', 'origin\thttps://gitlab.com/emmasax4/git_helper.git (fetch)' ] }
11
+
12
+
13
+ subject { GitHelper::LocalCode.new }
14
+
15
+ before do
16
+ allow(subject).to receive(:system).and_return(nil)
17
+ end
18
+
19
+ describe '#checkout_default' do
20
+ it 'should make a system call' do
21
+ expect(subject).to receive(:system)
22
+ subject.checkout_default
23
+ end
24
+ end
25
+
26
+ describe '#forget_local_commits' do
27
+ it 'should make a system call' do
28
+ expect(subject).to receive(:system).exactly(2).times
29
+ subject.forget_local_commits
30
+ end
31
+
32
+ it 'should return nil' do
33
+ expect(subject.forget_local_commits).to eq(nil)
34
+ end
35
+ end
36
+
37
+ describe '#empty_commit' do
38
+ it 'should make a system call' do
39
+ expect(subject).to receive(:system)
40
+ subject.empty_commit
41
+ end
42
+ end
43
+
44
+ describe '#clean_branches' do
45
+ it 'should make a system call' do
46
+ expect(subject).to receive(:system).exactly(4).times
47
+ subject.clean_branches
48
+ end
49
+ end
50
+
51
+ describe '#new_branch' do
52
+ it 'should make a system call' do
53
+ expect(subject).to receive(:system).exactly(4).times
54
+ subject.new_branch('branch_name')
55
+ end
56
+ end
57
+
58
+ describe '#change_remote' do
59
+ it 'should return a string' do
60
+ expect(subject.change_remote('name', 'url')).to be_a(String)
61
+ end
62
+ end
63
+
64
+ describe '#remotes' do
65
+ it 'should return an array of strings' do
66
+ expect(subject.remotes).to be_a(Array)
67
+ expect(subject.remotes.first).to be_a(String)
68
+ end
69
+ end
70
+
71
+ describe '#remote_name' do
72
+ it 'should be a string' do
73
+ expect(subject.remote_name(ssh_remote)).to be_a(String)
74
+ end
75
+ end
76
+
77
+ describe '#ssh_remote' do
78
+ it 'should come out true if ssh' do
79
+ expect(subject.ssh_remote?(ssh_remote)).to eq(true)
80
+ end
81
+
82
+ it 'should come out false if https' do
83
+ expect(subject.ssh_remote?(https_remote)).to eq(false)
84
+ end
85
+ end
86
+
87
+ describe '#https_remote' do
88
+ it 'should come out false if ssh' do
89
+ expect(subject.https_remote?(ssh_remote)).to eq(false)
90
+ end
91
+
92
+ it 'should come out true if https' do
93
+ expect(subject.https_remote?(https_remote)).to eq(true)
94
+ end
95
+ end
96
+
97
+ describe '#remote_project' do
98
+ it 'should return just the plain project if ssh' do
99
+ expect(subject.remote_project(ssh_remote)).to eq('git_helper')
100
+ end
101
+
102
+ it 'should return just the plain project if https' do
103
+ expect(subject.remote_project(https_remote)).to eq('git_helper')
104
+ end
105
+ end
106
+
107
+ describe '#remote_source' do
108
+ it 'should return just the plain project if ssh' do
109
+ expect(subject.remote_source(ssh_remote)).to eq('github.com')
110
+ end
111
+
112
+ it 'should return just the plain project if https' do
113
+ expect(subject.remote_source(https_remote)).to eq('github.com')
114
+ end
115
+ end
116
+
117
+ describe '#github_repo' do
118
+ it 'should return true if github' do
119
+ allow(subject).to receive(:remotes).and_return(github_remotes)
120
+ expect(subject.github_repo?).to eq(true)
121
+ end
122
+
123
+ it 'should return false if gitlab' do
124
+ allow(subject).to receive(:remotes).and_return(gitlab_remotes)
125
+ expect(subject.github_repo?).to eq(false)
126
+ end
127
+ end
128
+
129
+ describe '#gitlab_project' do
130
+ it 'should return true if gitlab' do
131
+ allow(subject).to receive(:remotes).and_return(gitlab_remotes)
132
+ expect(subject.gitlab_project?).to eq(true)
133
+ end
134
+
135
+ it 'should return false if github' do
136
+ allow(subject).to receive(:remotes).and_return(github_remotes)
137
+ expect(subject.gitlab_project?).to eq(false)
138
+ end
139
+ end
140
+
141
+ describe '#project_name' do
142
+ it 'should return a string' do
143
+ expect(subject.project_name).to be_a(String)
144
+ end
145
+
146
+ it 'should equal this project name' do
147
+ allow_any_instance_of(String).to receive(:scan).and_return([['emmasax4/git_helper']])
148
+ expect(subject.project_name).to eq('emmasax4/git_helper')
149
+ end
150
+ end
151
+
152
+ describe '#branch' do
153
+ it 'should return a string' do
154
+ expect(subject.branch).to be_a(String)
155
+ end
156
+ end
157
+
158
+ describe '#default_branch' do
159
+ it 'should return a string' do
160
+ expect(subject.default_branch).to be_a(String)
161
+ end
162
+ end
163
+
164
+ describe '#template_options' do
165
+ let(:template_identifiers) do
166
+ {
167
+ nested_directory_name: 'PULL_REQUEST_TEMPLATE',
168
+ non_nested_file_name: 'pull_request_template'
169
+ }
170
+ end
171
+
172
+ it 'should return an array' do
173
+ expect(subject.template_options(template_identifiers)).to be_a(Array)
174
+ end
175
+
176
+ it 'should call Dir.glob and File.join' do
177
+ expect(Dir).to receive(:glob).and_return(['.github/pull_request_template.md']).at_least(:once)
178
+ expect(File).to receive(:join).at_least(:once)
179
+ subject.template_options(template_identifiers)
180
+ end
181
+ end
182
+
183
+ describe '#read_template' do
184
+ it 'should call File.open' do
185
+ expect(File).to receive(:open).and_return(double(read: true))
186
+ subject.read_template('.gitignore')
187
+ end
188
+ end
189
+
190
+ describe '#generate_title' do
191
+ it 'should return a title based on the branch' do
192
+ branch = 'jira-123-test-branch'
193
+ expect(subject.generate_title(branch)).to eq('JIRA-123 Test branch')
194
+ end
195
+
196
+ it 'should return a title based on the branch' do
197
+ branch = 'jira_123_test_branch'
198
+ expect(subject.generate_title(branch)).to eq('JIRA-123 Test branch')
199
+ end
200
+
201
+ it 'should return a title based on the branch' do
202
+ branch = 'jira-123_test_branch'
203
+ expect(subject.generate_title(branch)).to eq('JIRA-123 Test branch')
204
+ end
205
+
206
+ it 'should return a title based on the branch' do
207
+ branch = 'test_branch'
208
+ expect(subject.generate_title(branch)).to eq('Test branch')
209
+ end
210
+
211
+ it 'should return a title based on the branch' do
212
+ branch = 'test-branch'
213
+ expect(subject.generate_title(branch)).to eq('Test branch')
214
+ end
215
+
216
+ it 'should return a title based on the branch' do
217
+ branch = 'test'
218
+ expect(subject.generate_title(branch)).to eq('Test')
219
+ end
220
+
221
+ it 'should return a title based on the branch' do
222
+ branch = 'some_other_words_in_this_test_branch'
223
+ expect(subject.generate_title(branch)).to eq('Some other words in this test branch')
224
+ end
225
+
226
+ it 'should return a title based on the branch' do
227
+ branch = 'some-other-words-in-this-test-branch'
228
+ expect(subject.generate_title(branch)).to eq('Some other words in this test branch')
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,234 @@
1
+ require 'spec_helper'
2
+ require 'git_helper'
3
+
4
+ describe GitHelper::GitLabMergeRequest do
5
+ let(:local_code) { double(:local_code, read_template: 'template') }
6
+ let(:highline_cli) { double(:highline_cli) }
7
+ let(:gitlab_client_client) { double(:gitlab_client_client, project: :project, merge_request: :merge_request, create_merge_request: :created) }
8
+ let(:gitlab_client) { double(:gitlab_client, client: gitlab_client_client) }
9
+ let(:options) do
10
+ {
11
+ local_project: 'emmasax4/git_helper',
12
+ local_branch: 'main',
13
+ local_code: local_code,
14
+ cli: highline_cli
15
+ }
16
+ end
17
+
18
+ subject { GitHelper::GitLabMergeRequest.new(options) }
19
+
20
+ before do
21
+ allow(GitHelper::GitLabClient).to receive(:new).and_return(gitlab_client)
22
+ end
23
+
24
+ describe '#create' do
25
+ it 'should call the gitlab client to create' do
26
+ allow(subject).to receive(:squash_merge_request).and_return(true)
27
+ allow(subject).to receive(:remove_source_branch).and_return(false)
28
+ allow(subject).to receive(:new_mr_body).and_return('')
29
+ expect(gitlab_client_client).to receive(:create_merge_request)
30
+ subject.create({base_branch: 'base', new_title: 'title'})
31
+ end
32
+
33
+ it 'should call various other methods' do
34
+ expect(subject).to receive(:squash_merge_request).and_return(true)
35
+ expect(subject).to receive(:remove_source_branch).and_return(false)
36
+ expect(subject).to receive(:new_mr_body).and_return('')
37
+ allow(gitlab_client_client).to receive(:create_merge_request)
38
+ subject.create({base_branch: 'base', new_title: 'title'})
39
+ end
40
+
41
+ it 'should catch the raised error if the creation does not work' do
42
+ allow(subject).to receive(:squash_merge_request).and_return(true)
43
+ allow(subject).to receive(:remove_source_branch).and_return(false)
44
+ allow(subject).to receive(:new_mr_body).and_return('')
45
+ allow(gitlab_client_client).to receive(:create_merge_request).and_raise(StandardError)
46
+ expect(subject.create({base_branch: 'base', new_title: 'title'})).to eq(nil)
47
+ end
48
+ end
49
+
50
+ describe '#merge' do
51
+ it 'should call the gitlab client to merge' do
52
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
53
+ allow(subject).to receive(:mr_id).and_return(123)
54
+ expect(gitlab_client_client).to receive(:accept_merge_request)
55
+ subject.merge
56
+ end
57
+
58
+ it 'should call various other methods' do
59
+ expect(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title')).at_least(:once)
60
+ expect(subject).to receive(:mr_id).and_return(123).at_least(:once)
61
+ allow(gitlab_client_client).to receive(:accept_merge_request)
62
+ subject.merge
63
+ end
64
+
65
+ it 'should catch the raised error if the merge does not work' do
66
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
67
+ allow(subject).to receive(:mr_id).and_return(123)
68
+ allow(gitlab_client_client).to receive(:accept_merge_request).and_raise(StandardError)
69
+ expect(subject.merge).to eq(nil)
70
+ end
71
+
72
+ it 'should try to merge multiple times if the first merge errors' do
73
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
74
+ allow(subject).to receive(:mr_id).and_return(123)
75
+ expect(gitlab_client_client).to receive(:accept_merge_request).and_return(double(merge_commit_sha: nil)).exactly(2).times
76
+ expect(subject.merge).to eq(nil)
77
+ end
78
+ end
79
+
80
+ describe '#new_mr_body' do
81
+ it 'should call the local code if the template to apply exists' do
82
+ allow(subject).to receive(:template_name_to_apply).and_return('')
83
+ expect(local_code).to receive(:read_template)
84
+ subject.send(:new_mr_body)
85
+ end
86
+
87
+ it 'should not call the local code if the template is nil' do
88
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
89
+ expect(local_code).not_to receive(:read_template)
90
+ subject.send(:new_mr_body)
91
+ end
92
+
93
+ it 'should return an empty string if the template is nil' do
94
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
95
+ expect(subject.send(:new_mr_body)).to eq('')
96
+ end
97
+ end
98
+
99
+ describe '#template_name_to_apply' do
100
+ context 'if MR template options are empty' do
101
+ it 'should return nil' do
102
+ allow(subject).to receive(:mr_template_options).and_return([])
103
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
104
+ end
105
+ end
106
+
107
+ context 'if there is one template option' do
108
+ it 'should call the CLI to ask about a single template' do
109
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
110
+ expect(highline_cli).to receive(:apply_template?).and_return(true)
111
+ subject.send(:template_name_to_apply)
112
+ end
113
+
114
+ it 'should return the single template if the user says yes' do
115
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
116
+ allow(highline_cli).to receive(:apply_template?).and_return(true)
117
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
118
+ end
119
+
120
+ it 'should return nil if the user says no' do
121
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
122
+ allow(highline_cli).to receive(:apply_template?).and_return(false)
123
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
124
+ end
125
+ end
126
+
127
+ context 'if there are multiple template options' do
128
+ it 'should call the CLI to ask which of multiple templates to apply' do
129
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
130
+ expect(highline_cli).to receive(:template_to_apply).and_return('template1')
131
+ subject.send(:template_name_to_apply)
132
+ end
133
+
134
+ it 'should return the answer template if the user says yes' do
135
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
136
+ allow(highline_cli).to receive(:template_to_apply).and_return('template1')
137
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
138
+ end
139
+
140
+ it 'should return nil if the user says no' do
141
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
142
+ allow(highline_cli).to receive(:template_to_apply).and_return('None')
143
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
144
+ end
145
+ end
146
+ end
147
+
148
+ describe '#mr_template_options' do
149
+ it 'should call the local code' do
150
+ expect(local_code).to receive(:template_options)
151
+ subject.send(:mr_template_options)
152
+ end
153
+ end
154
+
155
+ describe '#mr_id' do
156
+ it 'should ask the CLI for the code request ID' do
157
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
158
+ subject.send(:mr_id)
159
+ end
160
+
161
+ it 'should equal an integer' do
162
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
163
+ expect(subject.send(:mr_id)).to eq(123)
164
+ end
165
+ end
166
+
167
+ describe '#squash_merge_request' do
168
+ it 'should ask the CLI for the code request ID' do
169
+ expect(highline_cli).to receive(:squash_merge_request?).and_return(true)
170
+ subject.send(:squash_merge_request)
171
+ end
172
+
173
+ it 'should be a boolean' do
174
+ expect(highline_cli).to receive(:squash_merge_request?).and_return(false)
175
+ expect([true, false]).to include(subject.send(:squash_merge_request))
176
+ end
177
+ end
178
+
179
+ describe '#remove_source_branch' do
180
+ before do
181
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: nil))
182
+ end
183
+
184
+ context 'when the existing project has no setting' do
185
+ it 'should ask the CLI for the code request ID' do
186
+ expect(highline_cli).to receive(:remove_source_branch?).and_return(true)
187
+ subject.send(:remove_source_branch)
188
+ end
189
+
190
+ it 'should be a boolean' do
191
+ allow(highline_cli).to receive(:remove_source_branch?).and_return(false)
192
+ expect([true, false]).to include(subject.send(:remove_source_branch))
193
+ end
194
+ end
195
+
196
+ it 'should ask the existing project' do
197
+ expect(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: true))
198
+ subject.send(:remove_source_branch)
199
+ end
200
+
201
+ it "should return the existing project's setting if it exists" do
202
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: true))
203
+ expect(subject.send(:remove_source_branch)).to eq(true)
204
+ end
205
+
206
+ it "should return the existing project's setting if it exists" do
207
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: false))
208
+ allow(highline_cli).to receive(:remove_source_branch?).and_return(true)
209
+ expect(subject.send(:remove_source_branch)).to eq(true)
210
+ end
211
+ end
212
+
213
+ describe '#existing_project' do
214
+ it 'should call the gitlab client' do
215
+ expect(gitlab_client_client).to receive(:project).and_return(:project)
216
+ subject.send(:existing_project)
217
+ end
218
+ end
219
+
220
+ describe '#existing_mr' do
221
+ it 'should call the gitlab client' do
222
+ allow(highline_cli).to receive(:code_request_id).and_return(123)
223
+ expect(gitlab_client_client).to receive(:merge_request).and_return(:merge_request)
224
+ subject.send(:existing_mr)
225
+ end
226
+ end
227
+
228
+ describe '#gitlab_client' do
229
+ it 'should call the gitlab client' do
230
+ expect(GitHelper::GitLabClient).to receive(:new).and_return(gitlab_client)
231
+ subject.send(:gitlab_client)
232
+ end
233
+ end
234
+ end