git_helper 3.3.1 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +20 -0
  4. data/Guardfile +3 -1
  5. data/README.md +1 -1
  6. data/Rakefile +2 -0
  7. data/bin/git-helper +18 -13
  8. data/lib/git_helper.rb +5 -1
  9. data/lib/git_helper/change_remote.rb +11 -3
  10. data/lib/git_helper/checkout_default.rb +2 -0
  11. data/lib/git_helper/clean_branches.rb +2 -0
  12. data/lib/git_helper/code_request.rb +29 -16
  13. data/lib/git_helper/empty_commit.rb +2 -0
  14. data/lib/git_helper/forget_local_commits.rb +2 -0
  15. data/lib/git_helper/git_config_reader.rb +3 -5
  16. data/lib/git_helper/gitlab_client.rb +2 -0
  17. data/lib/git_helper/highline_cli.rb +3 -1
  18. data/lib/git_helper/local_code.rb +18 -8
  19. data/lib/git_helper/merge_request.rb +86 -66
  20. data/lib/git_helper/new_branch.rb +2 -0
  21. data/lib/git_helper/octokit_client.rb +2 -0
  22. data/lib/git_helper/pull_request.rb +94 -63
  23. data/lib/git_helper/setup.rb +37 -17
  24. data/lib/git_helper/version.rb +3 -1
  25. data/spec/git_helper/change_remote_spec.rb +17 -17
  26. data/spec/git_helper/checkout_default_spec.rb +2 -0
  27. data/spec/git_helper/clean_branches_spec.rb +2 -0
  28. data/spec/git_helper/code_request_spec.rb +2 -0
  29. data/spec/git_helper/empty_commit_spec.rb +2 -0
  30. data/spec/git_helper/forget_local_commits_spec.rb +2 -0
  31. data/spec/git_helper/git_config_reader_spec.rb +4 -2
  32. data/spec/git_helper/gitlab_client_spec.rb +2 -0
  33. data/spec/git_helper/highline_cli_spec.rb +7 -5
  34. data/spec/git_helper/local_code_spec.rb +2 -0
  35. data/spec/git_helper/merge_request_spec.rb +8 -7
  36. data/spec/git_helper/new_branch_spec.rb +2 -0
  37. data/spec/git_helper/octokit_client_spec.rb +2 -0
  38. data/spec/git_helper/pull_request_spec.rb +5 -3
  39. data/spec/git_helper/setup_spec.rb +12 -7
  40. data/spec/spec_helper.rb +3 -1
  41. metadata +17 -3
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GitHelper
2
4
  class GitLabMergeRequest
3
5
  attr_accessor :local_project, :local_branch, :local_code, :cli, :base_branch, :new_mr_title
@@ -9,70 +11,74 @@ module GitHelper
9
11
  @cli = options[:cli]
10
12
  end
11
13
 
14
+ # rubocop:disable Metrics/MethodLength
15
+ # rubocop:disable Metrics/AbcSize
12
16
  def create(options)
13
17
  @base_branch = options[:base_branch]
14
18
  @new_mr_title = options[:new_title]
15
19
 
16
- begin
17
- options = {
18
- source_branch: local_branch,
19
- target_branch: base_branch,
20
- squash: squash_merge_request,
21
- remove_source_branch: remove_source_branch,
22
- description: new_mr_body
23
- }
24
-
25
- puts "Creating merge request: #{new_mr_title}"
26
- mr = gitlab_client.create_merge_request(local_project, new_mr_title, options)
27
-
28
- if mr.diff_refs.base_sha == mr.diff_refs.head_sha
29
- puts "Merge request was created, but no commits have been pushed to GitLab: #{mr.web_url}"
30
- else
31
- puts "Merge request successfully created: #{mr.web_url}"
32
- end
33
- rescue Gitlab::Error::Conflict => e
34
- puts 'Could not create merge request:'
35
- puts ' A merge request already exists for this branch'
36
- rescue Exception => e
37
- puts 'Could not create merge request:'
38
- puts e.message
20
+ options = {
21
+ source_branch: local_branch,
22
+ target_branch: base_branch,
23
+ squash: squash_merge_request,
24
+ remove_source_branch: remove_source_branch,
25
+ description: new_mr_body
26
+ }
27
+
28
+ puts "Creating merge request: #{new_mr_title}"
29
+ mr = gitlab_client.create_merge_request(local_project, new_mr_title, options)
30
+
31
+ if mr.diff_refs.base_sha == mr.diff_refs.head_sha
32
+ puts "Merge request was created, but no commits have been pushed to GitLab: #{mr.web_url}"
33
+ else
34
+ puts "Merge request successfully created: #{mr.web_url}"
39
35
  end
36
+ rescue Gitlab::Error::Conflict
37
+ puts 'Could not create merge request:'
38
+ puts ' A merge request already exists for this branch'
39
+ rescue StandardError => e
40
+ puts 'Could not create merge request:'
41
+ puts e.message
40
42
  end
43
+ # rubocop:enable Metrics/AbcSize
44
+ # rubocop:enable Metrics/MethodLength
41
45
 
46
+ # rubocop:disable Metrics/MethodLength
47
+ # rubocop:disable Metrics/AbcSize
42
48
  def merge
43
- begin
44
- mr_id
45
- options = {
46
- should_remove_source_branch: existing_mr.should_remove_source_branch || existing_mr.force_remove_source_branch,
47
- squash: existing_mr.squash,
48
- squash_commit_message: existing_mr.title
49
- }
50
-
51
- puts "Merging merge request: #{mr_id}"
49
+ mr_id
50
+ options = {
51
+ should_remove_source_branch: existing_mr.should_remove_source_branch || existing_mr.force_remove_source_branch,
52
+ squash: existing_mr.squash,
53
+ squash_commit_message: existing_mr.title
54
+ }
55
+
56
+ puts "Merging merge request: #{mr_id}"
57
+ merge = gitlab_client.accept_merge_request(local_project, mr_id, options)
58
+
59
+ if merge.merge_commit_sha.nil?
60
+ options[:squash] = true
52
61
  merge = gitlab_client.accept_merge_request(local_project, mr_id, options)
62
+ end
53
63
 
54
- if merge.merge_commit_sha.nil?
55
- options[:squash] = true
56
- merge = gitlab_client.accept_merge_request(local_project, mr_id, options)
57
- end
58
-
59
- if merge.merge_commit_sha.nil?
60
- puts 'Could not merge merge request:'
61
- puts " #{merge.merge_error}"
62
- else
63
- puts "Merge request successfully merged: #{merge.merge_commit_sha}"
64
- end
65
- rescue Gitlab::Error::MethodNotAllowed => e
66
- puts 'Could not merge merge request:'
67
- puts ' The merge request is not mergeable'
68
- rescue Gitlab::Error::NotFound => e
64
+ if merge.merge_commit_sha.nil?
69
65
  puts 'Could not merge merge request:'
70
- puts " Could not a locate a merge request to merge with ID #{mr_id}"
71
- rescue Exception => e
72
- puts 'Could not merge merge request:'
73
- puts e.message
66
+ puts " #{merge.merge_error}"
67
+ else
68
+ puts "Merge request successfully merged: #{merge.merge_commit_sha}"
74
69
  end
70
+ rescue Gitlab::Error::MethodNotAllowed
71
+ puts 'Could not merge merge request:'
72
+ puts ' The merge request is not mergeable'
73
+ rescue Gitlab::Error::NotFound
74
+ puts 'Could not merge merge request:'
75
+ puts " Could not a locate a merge request to merge with ID #{mr_id}"
76
+ rescue StandardError => e
77
+ puts 'Could not merge merge request:'
78
+ puts e.message
75
79
  end
80
+ # rubocop:enable Metrics/AbcSize
81
+ # rubocop:enable Metrics/MethodLength
76
82
 
77
83
  private def new_mr_body
78
84
  @new_mr_body ||= template_name_to_apply ? local_code.read_template(template_name_to_apply) : ''
@@ -80,27 +86,38 @@ module GitHelper
80
86
 
81
87
  private def template_name_to_apply
82
88
  return @template_name_to_apply if @template_name_to_apply
89
+
83
90
  @template_name_to_apply = nil
84
91
 
85
- unless mr_template_options.empty?
86
- if mr_template_options.count == 1
87
- apply_single_template = cli.ask_yes_no("Apply the merge request template from #{mr_template_options.first}? (y/n)")
88
- @template_name_to_apply = mr_template_options.first if apply_single_template
89
- else
90
- response = cli.ask_options("Which merge request template should be applied?", mr_template_options << 'None')
91
- @template_name_to_apply = response unless response == 'None'
92
- end
93
- end
92
+ determine_template unless mr_template_options.empty?
94
93
 
95
94
  @template_name_to_apply
96
95
  end
97
96
 
97
+ # rubocop:disable Metrics/MethodLength
98
+ private def determine_template
99
+ if mr_template_options.count == 1
100
+ apply_single_template = cli.ask_yes_no(
101
+ "Apply the merge request template from #{mr_template_options.first}? (y/n)"
102
+ )
103
+ @template_name_to_apply = mr_template_options.first if apply_single_template
104
+ else
105
+ response = cli.ask_options(
106
+ 'Which merge request template should be applied?', mr_template_options << 'None'
107
+ )
108
+ @template_name_to_apply = response unless response == 'None'
109
+ end
110
+ end
111
+ # rubocop:enable Metrics/MethodLength
112
+
98
113
  private def mr_template_options
99
- @mr_template_options ||= local_code.template_options({
100
- template_directory: '.gitlab',
101
- nested_directory_name: 'merge_request_templates',
102
- non_nested_file_name: 'merge_request_template'
103
- })
114
+ @mr_template_options ||= local_code.template_options(
115
+ {
116
+ template_directory: '.gitlab',
117
+ nested_directory_name: 'merge_request_templates',
118
+ non_nested_file_name: 'merge_request_template'
119
+ }
120
+ )
104
121
  end
105
122
 
106
123
  private def mr_id
@@ -112,7 +129,10 @@ module GitHelper
112
129
  end
113
130
 
114
131
  private def remove_source_branch
115
- @remove_source_branch ||= existing_project.remove_source_branch_after_merge || cli.ask_yes_no('Remove source branch after merging? (y/n)')
132
+ @remove_source_branch ||=
133
+ existing_project.remove_source_branch_after_merge || cli.ask_yes_no(
134
+ 'Remove source branch after merging? (y/n)'
135
+ )
116
136
  end
117
137
 
118
138
  private def existing_project
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GitHelper
2
4
  class NewBranch
3
5
  def execute(new_branch_name = nil)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GitHelper
2
4
  class OctokitClient
3
5
  def client
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GitHelper
2
4
  class GitHubPullRequest
3
5
  attr_accessor :local_repo, :local_branch, :local_code, :cli, :base_branch, :new_pr_title
@@ -9,67 +11,79 @@ module GitHelper
9
11
  @cli = options[:cli]
10
12
  end
11
13
 
14
+ # rubocop:disable Metrics/MethodLength
15
+ # rubocop:disable Metrics/AbcSize
12
16
  def create(options)
13
17
  @base_branch = options[:base_branch]
14
18
  @new_pr_title = options[:new_title]
15
19
 
16
- begin
17
- new_pr_body
20
+ new_pr_body
18
21
 
19
- puts "Creating pull request: #{new_pr_title}"
20
- pr = octokit_client.create_pull_request(local_repo, base_branch, local_branch, new_pr_title, new_pr_body)
21
- puts "Pull request successfully created: #{pr.html_url}"
22
- rescue Octokit::UnprocessableEntity => e
23
- puts 'Could not create pull request:'
24
- if e.message.include?('pull request already exists')
25
- puts ' A pull request already exists for this branch'
26
- elsif e.message.include?('No commits between')
27
- puts ' No commits have been pushed to GitHub'
28
- else
29
- puts e.message
30
- end
31
- rescue Exception => e
32
- puts 'Could not create pull request:'
22
+ puts "Creating pull request: #{new_pr_title}"
23
+ pr = octokit_client.create_pull_request(
24
+ local_repo,
25
+ base_branch,
26
+ local_branch,
27
+ new_pr_title,
28
+ new_pr_body
29
+ )
30
+ puts "Pull request successfully created: #{pr.html_url}"
31
+ rescue Octokit::UnprocessableEntity => e
32
+ puts 'Could not create pull request:'
33
+ if e.message.include?('pull request already exists')
34
+ puts ' A pull request already exists for this branch'
35
+ elsif e.message.include?('No commits between')
36
+ puts ' No commits have been pushed to GitHub'
37
+ else
33
38
  puts e.message
34
39
  end
40
+ rescue StandardError => e
41
+ puts 'Could not create pull request:'
42
+ puts e.message
35
43
  end
44
+ # rubocop:enable Metrics/AbcSize
45
+ # rubocop:enable Metrics/MethodLength
36
46
 
47
+ # rubocop:disable Metrics/MethodLength
48
+ # rubocop:disable Metrics/AbcSize
37
49
  def merge
38
- begin
39
- pr_id
40
- merge_method
41
-
42
- puts "Merging pull request: #{pr_id}"
43
- merge = octokit_client.merge_pull_request(local_repo, pr_id, existing_pr.title, { merge_method: merge_method })
44
- puts "Pull request successfully merged: #{merge.sha}"
45
- rescue Octokit::UnprocessableEntity => e
46
- puts 'Could not merge pull request:'
47
- puts e.message
48
- rescue Octokit::NotFound => e
49
- puts 'Could not merge pull request:'
50
- puts " Could not a locate a pull request to merge with ID #{pr_id}"
51
- rescue Octokit::MethodNotAllowed => e
52
- puts 'Could not merge pull request:'
53
- if e.message.include?('405 - Required status check')
54
- puts ' A required status check has not passed'
55
- elsif e.message.include?('405 - Base branch was modified')
56
- puts ' The base branch has been modified'
57
- elsif e.message.include?('405 - Pull Request is not mergeable')
58
- puts ' The pull request is not mergeable'
59
- elsif e.message.include?('405 - Rebase merges are not allowed on this repository')
60
- puts ' Rebase merges are not allowed on this repository'
61
- elsif e.message.include?('405 - Merge commits are not allowed on this repository')
62
- puts ' Merge commits are not allowed on this repository'
63
- elsif e.message.include?('405 - Squash commits are not allowed on this repository')
64
- puts ' Squash merges are not allowed on this repository'
65
- else
66
- puts e.message
67
- end
68
- rescue Exception => e
69
- puts 'Could not merge pull request:'
50
+ pr_id
51
+ merge_method
52
+
53
+ puts "Merging pull request: #{pr_id}"
54
+ merge = octokit_client.merge_pull_request(
55
+ local_repo,
56
+ pr_id,
57
+ existing_pr.title,
58
+ { merge_method: merge_method }
59
+ )
60
+ puts "Pull request successfully merged: #{merge.sha}"
61
+ rescue Octokit::NotFound
62
+ puts 'Could not merge pull request:'
63
+ puts " Could not a locate a pull request to merge with ID #{pr_id}"
64
+ rescue Octokit::MethodNotAllowed => e
65
+ puts 'Could not merge pull request:'
66
+ if e.message.include?('405 - Required status check')
67
+ puts ' A required status check has not passed'
68
+ elsif e.message.include?('405 - Base branch was modified')
69
+ puts ' The base branch has been modified'
70
+ elsif e.message.include?('405 - Pull Request is not mergeable')
71
+ puts ' The pull request is not mergeable'
72
+ elsif e.message.include?('405 - Rebase merges are not allowed on this repository')
73
+ puts ' Rebase merges are not allowed on this repository'
74
+ elsif e.message.include?('405 - Merge commits are not allowed on this repository')
75
+ puts ' Merge commits are not allowed on this repository'
76
+ elsif e.message.include?('405 - Squash commits are not allowed on this repository')
77
+ puts ' Squash merges are not allowed on this repository'
78
+ else
70
79
  puts e.message
71
80
  end
81
+ rescue StandardError => e
82
+ puts 'Could not merge pull request:'
83
+ puts e.message
72
84
  end
85
+ # rubocop:enable Metrics/AbcSize
86
+ # rubocop:enable Metrics/MethodLength
73
87
 
74
88
  private def new_pr_body
75
89
  @new_pr_body ||= template_name_to_apply ? local_code.read_template(template_name_to_apply) : ''
@@ -77,27 +91,38 @@ module GitHelper
77
91
 
78
92
  private def template_name_to_apply
79
93
  return @template_name_to_apply if @template_name_to_apply
94
+
80
95
  @template_name_to_apply = nil
81
96
 
82
- unless pr_template_options.empty?
83
- if pr_template_options.count == 1
84
- apply_single_template = cli.ask_yes_no("Apply the pull request template from #{pr_template_options.first}? (y/n)")
85
- @template_name_to_apply = pr_template_options.first if apply_single_template
86
- else
87
- response = cli.ask_options("Which pull request template should be applied?", pr_template_options << 'None')
88
- @template_name_to_apply = response unless response == 'None'
89
- end
90
- end
97
+ determine_template unless pr_template_options.empty?
91
98
 
92
99
  @template_name_to_apply
93
100
  end
94
101
 
102
+ # rubocop:disable Metrics/MethodLength
103
+ private def determine_template
104
+ if pr_template_options.count == 1
105
+ apply_single_template = cli.ask_yes_no(
106
+ "Apply the pull request template from #{pr_template_options.first}? (y/n)"
107
+ )
108
+ @template_name_to_apply = pr_template_options.first if apply_single_template
109
+ else
110
+ response = cli.ask_options(
111
+ 'Which pull request template should be applied?', pr_template_options << 'None'
112
+ )
113
+ @template_name_to_apply = response unless response == 'None'
114
+ end
115
+ end
116
+ # rubocop:enable Metrics/MethodLength
117
+
95
118
  private def pr_template_options
96
- @pr_template_options ||= local_code.template_options({
97
- template_directory: '.github',
98
- nested_directory_name: 'PULL_REQUEST_TEMPLATE',
99
- non_nested_file_name: 'pull_request_template'
100
- })
119
+ @pr_template_options ||= local_code.template_options(
120
+ {
121
+ template_directory: '.github',
122
+ nested_directory_name: 'PULL_REQUEST_TEMPLATE',
123
+ non_nested_file_name: 'pull_request_template'
124
+ }
125
+ )
101
126
  end
102
127
 
103
128
  private def pr_id
@@ -105,11 +130,17 @@ module GitHelper
105
130
  end
106
131
 
107
132
  private def merge_method
108
- @merge_method ||= merge_options.length == 1 ? merge_options.first : cli.ask_options('Merge method?', merge_options)
133
+ @merge_method ||=
134
+ if merge_options.length == 1
135
+ merge_options.first
136
+ else
137
+ cli.ask_options('Merge method?', merge_options)
138
+ end
109
139
  end
110
140
 
111
141
  private def merge_options
112
142
  return @merge_options if @merge_options
143
+
113
144
  merge_options = []
114
145
  merge_options << 'merge' if existing_project.allow_merge_commit
115
146
  merge_options << 'squash' if existing_project.allow_squash_merge
@@ -1,25 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GitHelper
2
4
  class Setup
3
5
  def execute
6
+ execute_config_file
7
+ execute_plugins
8
+ end
9
+
10
+ private def execute_config_file
4
11
  if config_file_exists?
5
- answer = highline.ask_yes_no("It looks like the #{config_file} file already exists. Do you wish to replace it? (y/n)")
12
+ answer = highline.ask_yes_no(
13
+ "It looks like the #{config_file} file already exists. Do you wish to replace it? (y/n)"
14
+ )
6
15
  puts
7
16
  else
8
17
  answer = true
9
18
  end
10
19
 
11
20
  create_or_update_config_file if answer
21
+ end
12
22
 
23
+ private def execute_plugins
13
24
  answer = highline.ask_yes_no(
14
- "Do you wish to set up the Git Helper plugins? (y/n) (This process will " \
15
- "attempt to use your GitHub personal access token to authenticate)"
25
+ 'Do you wish to set up the Git Helper plugins? (y/n) (This process will ' \
26
+ 'attempt to use your GitHub personal access token to authenticate)'
16
27
  )
17
28
 
18
- if answer
19
- create_or_update_plugin_files
20
- puts "\nNow add this line to your ~/.bash_profile:\n export PATH=/path/to/computer/home/.git_helper/plugins:$PATH"
21
- puts "\nDone!"
22
- end
29
+ return unless answer
30
+
31
+ create_or_update_plugin_files
32
+ puts "\nNow add this line to your ~/.bash_profile:\n" \
33
+ ' export PATH=/path/to/computer/home/.git_helper/plugins:$PATH'
34
+ puts "\nDone!"
23
35
  end
24
36
 
25
37
  private def create_or_update_config_file
@@ -30,28 +42,32 @@ module GitHelper
30
42
  end
31
43
 
32
44
  private def config_file_exists?
33
- File.exists?(config_file)
45
+ File.exist?(config_file)
34
46
  end
35
47
 
48
+ # rubocop:disable Metrics/MethodLength
36
49
  private def generate_file_contents
37
- file_contents = ''
50
+ file_contents = ''.dup
38
51
 
39
- if highline.ask_yes_no("Do you wish to set up GitHub credentials? (y/n)")
52
+ if highline.ask_yes_no('Do you wish to set up GitHub credentials? (y/n)')
40
53
  file_contents << ":github_user: #{ask_question('GitHub username?')}\n"
41
- file_contents << ":github_token: " \
54
+ file_contents << ':github_token: ' \
42
55
  "#{ask_question('GitHub personal access token? (Navigate to https://github.com/settings/tokens ' \
43
56
  'to create a new personal access token)')}\n"
44
57
  end
45
58
 
46
59
  if highline.ask_yes_no("\nDo you wish to set up GitLab credentials? (y/n)")
47
60
  file_contents << ":gitlab_user: #{ask_question('GitLab username?')}\n"
48
- file_contents << ":gitlab_token: " \
49
- "#{ask_question('GitLab personal access token? (Navigate to https://gitlab.com/-/profile/personal_access_tokens ' \
50
- 'to create a new personal access token)')}\n"
61
+ file_contents << ':gitlab_token: ' \
62
+ "#{ask_question(
63
+ 'GitLab personal access token? (Navigate to https://gitlab.com/-/profile/personal_access_tokens' \
64
+ ' to create a new personal access token)'
65
+ )}\n"
51
66
  end
52
67
 
53
68
  file_contents.strip
54
69
  end
70
+ # rubocop:enable Metrics/MethodLength
55
71
 
56
72
  private def ask_question(prompt)
57
73
  answer = highline.ask("\n#{prompt}")
@@ -64,14 +80,16 @@ module GitHelper
64
80
  end
65
81
  end
66
82
 
83
+ # rubocop:disable Metrics/MethodLength
84
+ # rubocop:disable Metrics/AbcSize
67
85
  private def create_or_update_plugin_files
68
- plugins_dir = "#{Dir.pwd.scan(/\A\/[\w]*\/[\w]*\//).first}/.git_helper/plugins"
86
+ plugins_dir = "#{Dir.pwd.scan(%r{\A/\w*/\w*/}).first}.git_helper/plugins"
69
87
  plugins_url = 'https://api.github.com/repos/emmahsax/git_helper/contents/plugins'
70
88
  header = 'Accept: application/vnd.github.v3.raw'
71
89
  token = git_config_reader.github_token
72
90
  user = git_config_reader.github_user
73
91
 
74
- Dir.mkdir(plugins_dir) unless File.exists?(plugins_dir)
92
+ Dir.mkdir(plugins_dir) unless File.exist?(plugins_dir)
75
93
 
76
94
  all_plugins = JSON.parse(`curl -s -u #{user}:#{token} -H "#{header}" -L "#{plugins_url}"`)
77
95
 
@@ -80,6 +98,8 @@ module GitHelper
80
98
  File.open("#{plugins_dir}/#{plugin['name']}", 'w') { |file| file.puts plugin_content }
81
99
  end
82
100
  end
101
+ # rubocop:enable Metrics/MethodLength
102
+ # rubocop:enable Metrics/AbcSize
83
103
 
84
104
  private def config_file
85
105
  git_config_reader.git_config_file_path