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.
- checksums.yaml +4 -4
 - data/Gemfile.lock +17 -13
 - data/README.md +27 -33
 - data/Rakefile +1 -37
 - data/bin/git-helper +10 -28
 - data/lib/git_helper.rb +3 -5
 - data/lib/git_helper/change_remote.rb +53 -40
 - data/lib/git_helper/checkout_default.rb +1 -1
 - data/lib/git_helper/clean_branches.rb +1 -4
 - data/lib/git_helper/code_request.rb +95 -0
 - data/lib/git_helper/empty_commit.rb +1 -1
 - data/lib/git_helper/forget_local_commits.rb +7 -0
 - data/lib/git_helper/gitlab_client.rb +0 -1
 - data/lib/git_helper/highline_cli.rb +72 -6
 - data/lib/git_helper/local_code.rb +124 -0
 - data/lib/git_helper/merge_request.rb +57 -126
 - data/lib/git_helper/new_branch.rb +2 -11
 - data/lib/git_helper/octokit_client.rb +0 -1
 - data/lib/git_helper/pull_request.rb +45 -110
 - data/lib/git_helper/version.rb +1 -1
 - data/spec/git_helper/change_remote_spec.rb +173 -0
 - data/spec/git_helper/checkout_default_spec.rb +19 -0
 - data/spec/git_helper/clean_branches_spec.rb +19 -0
 - data/spec/git_helper/code_request_spec.rb +259 -0
 - data/spec/git_helper/empty_commit_spec.rb +19 -0
 - data/spec/git_helper/forget_local_commits_spec.rb +19 -0
 - data/spec/git_helper/git_config_reader_spec.rb +60 -0
 - data/spec/git_helper/gitlab_client_spec.rb +26 -0
 - data/spec/git_helper/highline_cli_spec.rb +215 -0
 - data/spec/git_helper/local_code_spec.rb +231 -0
 - data/spec/git_helper/merge_request_spec.rb +234 -0
 - data/spec/git_helper/new_branch_spec.rb +44 -0
 - data/spec/git_helper/octokit_client_spec.rb +26 -0
 - data/spec/git_helper/pull_request_spec.rb +246 -0
 - data/spec/spec_helper.rb +0 -7
 - metadata +41 -24
 
| 
         @@ -2,24 +2,90 @@ require 'highline' 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module GitHelper
         
     | 
| 
       4 
4 
     | 
    
         
             
              class HighlineCli
         
     | 
| 
       5 
     | 
    
         
            -
                def  
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
      
 5 
     | 
    
         
            +
                def new_branch_name
         
     | 
| 
      
 6 
     | 
    
         
            +
                  ask('New branch name?')
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def process_directory_remotes?(directory)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  answer = ask("Found git directory: #{directory}. Do you wish to proceed in updating #{directory}'s remote URLs? (y/n)")
         
     | 
| 
      
 11 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def conflicting_remote_clarification
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ask('Found git remotes for both GitHub and GitLab. Would you like to proceed with GitLab or GitHub? (github/gitlab)').downcase
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def title
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ask('Title?')
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def base_branch
         
     | 
| 
      
 23 
     | 
    
         
            +
                  ask('Base branch?')
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def code_request_id(request_type)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  ask("#{request_type} Request ID?")
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def accept_autogenerated_title?(autogenerated_title)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  return false unless autogenerated_title
         
     | 
| 
      
 32 
     | 
    
         
            +
                  answer = ask("Accept the autogenerated code request title '#{autogenerated_title}'? (y/n)")
         
     | 
| 
      
 33 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def base_branch_default?(default_branch)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  answer = ask("Is '#{default_branch}' the correct base branch for your new code request? (y/n)")
         
     | 
| 
      
 38 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def squash_merge_request?
         
     | 
| 
      
 42 
     | 
    
         
            +
                  answer = ask('Squash merge request? (y/n)')
         
     | 
| 
      
 43 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def remove_source_branch?
         
     | 
| 
      
 47 
     | 
    
         
            +
                  answer = ask('Remove source branch after merging? (y/n)')
         
     | 
| 
      
 48 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def merge_method(merge_options)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  index = ask_options("Merge method?", merge_options)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  merge_options[index]
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def apply_template?(template_file_name, request_type)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  answer = ask("Apply the #{request_type} request template from #{template_file_name}? (y/n)")
         
     | 
| 
      
 58 
     | 
    
         
            +
                  answer.empty? ? true : !!(answer =~ /^y/i)
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def template_to_apply(template_options, request_type)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  complete_options = template_options << 'None'
         
     | 
| 
      
 63 
     | 
    
         
            +
                  index = ask_options("Which #{request_type} request template should be applied?", complete_options)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  complete_options[index]
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                #######################
         
     | 
| 
      
 68 
     | 
    
         
            +
                ### GENERAL METHODS ###
         
     | 
| 
      
 69 
     | 
    
         
            +
                #######################
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                private def ask(prompt)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  highline_client.ask(prompt) do |conf|
         
     | 
| 
       7 
73 
     | 
    
         
             
                    conf.readline = true
         
     | 
| 
       8 
74 
     | 
    
         
             
                  end.to_s
         
     | 
| 
       9 
75 
     | 
    
         
             
                end
         
     | 
| 
       10 
76 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                def ask_options(prompt, choices)
         
     | 
| 
      
 77 
     | 
    
         
            +
                private def ask_options(prompt, choices)
         
     | 
| 
       12 
78 
     | 
    
         
             
                  choices_as_string_options = ''
         
     | 
| 
       13 
79 
     | 
    
         
             
                  choices.each { |choice| choices_as_string_options << "#{choices.index(choice) + 1}. #{choice}\n" }
         
     | 
| 
       14 
80 
     | 
    
         
             
                  compiled_prompt = "#{prompt}\n#{choices_as_string_options.strip}"
         
     | 
| 
       15 
81 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
      
 82 
     | 
    
         
            +
                  highline_client.ask(compiled_prompt) do |conf|
         
     | 
| 
       17 
83 
     | 
    
         
             
                    conf.readline = true
         
     | 
| 
       18 
84 
     | 
    
         
             
                  end.to_i - 1
         
     | 
| 
       19 
85 
     | 
    
         
             
                end
         
     | 
| 
       20 
86 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                private def  
     | 
| 
       22 
     | 
    
         
            -
                  @ 
     | 
| 
      
 87 
     | 
    
         
            +
                private def highline_client
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @highline_client ||= HighLine.new
         
     | 
| 
       23 
89 
     | 
    
         
             
                end
         
     | 
| 
       24 
90 
     | 
    
         
             
              end
         
     | 
| 
       25 
91 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,124 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module GitHelper
         
     | 
| 
      
 2 
     | 
    
         
            +
              class LocalCode
         
     | 
| 
      
 3 
     | 
    
         
            +
                def checkout_default
         
     | 
| 
      
 4 
     | 
    
         
            +
                  system("git checkout $(git symbolic-ref refs/remotes/origin/HEAD | sed \"s@^refs/remotes/origin/@@\")")
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def forget_local_commits
         
     | 
| 
      
 8 
     | 
    
         
            +
                  system("git pull")
         
     | 
| 
      
 9 
     | 
    
         
            +
                  system("git reset --hard origin/HEAD")
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def empty_commit
         
     | 
| 
      
 13 
     | 
    
         
            +
                  system("git commit --allow-empty -m \"Empty commit\"")
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def clean_branches
         
     | 
| 
      
 17 
     | 
    
         
            +
                  system("git checkout $(git symbolic-ref refs/remotes/origin/HEAD | sed \"s@^refs/remotes/origin/@@\")")
         
     | 
| 
      
 18 
     | 
    
         
            +
                  system("git pull")
         
     | 
| 
      
 19 
     | 
    
         
            +
                  system("git fetch -p")
         
     | 
| 
      
 20 
     | 
    
         
            +
                  system("git branch -vv | grep \"origin/.*: gone]\" | awk '{print \$1}' | grep -v \"*\" | xargs git branch -D")
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def new_branch(branch_name)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  system("git pull")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  system("git branch --no-track #{branch_name}")
         
     | 
| 
      
 26 
     | 
    
         
            +
                  system("git checkout #{branch_name}")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  system("git push --set-upstream origin #{branch_name}")
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def change_remote(remote_name, remote_url)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  `git remote set-url #{remote_name} #{remote_url}`
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def remotes
         
     | 
| 
      
 35 
     | 
    
         
            +
                  `git remote -v`.split("\n")
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def remote_name(remote)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  remote.scan(/([a-zA-z]+)/).first.first
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def ssh_remote?(remote)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  remote.scan(/(git@)/).any?
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def https_remote?(remote)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  remote.scan(/(https:\/\/)/).any?
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def remote_project(remote)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  if https_remote?(remote)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    remote.scan(/https:\/\/[\S]+\/([\S]*).git/).first.first
         
     | 
| 
      
 53 
     | 
    
         
            +
                  elsif ssh_remote?(remote)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    remote.scan(/\/([\S]*).git/).first.first
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def remote_source(remote)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  if https_remote?(remote)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    remote.scan(/https:\/\/([a-zA-z.]+)\//).first.first
         
     | 
| 
      
 61 
     | 
    
         
            +
                  elsif ssh_remote?(remote)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    remote.scan(/git@([a-zA-z.]+):/).first.first
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def github_repo?
         
     | 
| 
      
 67 
     | 
    
         
            +
                  remotes.select { |remote| remote.include?('github') }.any?
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def gitlab_project?
         
     | 
| 
      
 71 
     | 
    
         
            +
                  remotes.select { |remote| remote.include?('gitlab') }.any?
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def project_name
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # Get the repo/project name by looking in the remote URLs for the full name
         
     | 
| 
      
 76 
     | 
    
         
            +
                  `git remote -v`.scan(/\S[\s]*[\S]+.com[\S]{1}([\S]*).git/).first.first
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def branch
         
     | 
| 
      
 80 
     | 
    
         
            +
                  # Get the current branch by looking in the list of branches for the *
         
     | 
| 
      
 81 
     | 
    
         
            +
                  `git branch`.scan(/\*\s([\S]*)/).first.first
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def default_branch
         
     | 
| 
      
 85 
     | 
    
         
            +
                  `git symbolic-ref refs/remotes/origin/HEAD | sed "s@^refs/remotes/origin/@@" | tr -d "\n"`
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def template_options(template_identifiers)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  nested_templates = Dir.glob(
         
     | 
| 
      
 90 
     | 
    
         
            +
                    File.join("**/#{template_identifiers[:nested_directory_name]}", "*.md"),
         
     | 
| 
      
 91 
     | 
    
         
            +
                    File::FNM_DOTMATCH | File::FNM_CASEFOLD
         
     | 
| 
      
 92 
     | 
    
         
            +
                  )
         
     | 
| 
      
 93 
     | 
    
         
            +
                  non_nested_templates = Dir.glob(
         
     | 
| 
      
 94 
     | 
    
         
            +
                    File.join("**", "#{template_identifiers[:non_nested_file_name]}.md"),
         
     | 
| 
      
 95 
     | 
    
         
            +
                    File::FNM_DOTMATCH | File::FNM_CASEFOLD
         
     | 
| 
      
 96 
     | 
    
         
            +
                  )
         
     | 
| 
      
 97 
     | 
    
         
            +
                  nested_templates.concat(non_nested_templates).uniq
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                def read_template(file_name)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  File.open(file_name).read
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                def generate_title(local_branch)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  branch_arr = local_branch.split(local_branch.include?('_') ? '_' : '-')
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  return if branch_arr.empty?
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  if branch_arr.length == 1
         
     | 
| 
      
 110 
     | 
    
         
            +
                    branch_arr.first.capitalize
         
     | 
| 
      
 111 
     | 
    
         
            +
                  elsif branch_arr[0].scan(/([\w]+)/).any? && branch_arr[1].scan(/([\d]+)/).any? # branch includes jira_123 at beginning
         
     | 
| 
      
 112 
     | 
    
         
            +
                    issue = "#{branch_arr[0].upcase}-#{branch_arr[1]}"
         
     | 
| 
      
 113 
     | 
    
         
            +
                    description = branch_arr[2..-1].join(' ')
         
     | 
| 
      
 114 
     | 
    
         
            +
                    "#{issue} #{description.capitalize}"
         
     | 
| 
      
 115 
     | 
    
         
            +
                  elsif branch_arr[0].scan(/([\w]+-[\d]+)/).any? # branch includes string jira-123 at beginning
         
     | 
| 
      
 116 
     | 
    
         
            +
                    issue = branch_arr[0].upcase
         
     | 
| 
      
 117 
     | 
    
         
            +
                    description = branch_arr[1..-1].join(' ')
         
     | 
| 
      
 118 
     | 
    
         
            +
                    "#{issue} #{description.capitalize}"
         
     | 
| 
      
 119 
     | 
    
         
            +
                  else # plain words
         
     | 
| 
      
 120 
     | 
    
         
            +
                    branch_arr[0..-1].join(' ').capitalize
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
              end
         
     | 
| 
      
 124 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,16 +1,24 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require_relative './gitlab_client.rb'
         
     | 
| 
       2 
     | 
    
         
            -
            require_relative './highline_cli.rb'
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
1 
     | 
    
         
             
            module GitHelper
         
     | 
| 
       5 
2 
     | 
    
         
             
              class GitLabMergeRequest
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 3 
     | 
    
         
            +
                attr_accessor :local_project, :local_branch, :local_code, :cli, :base_branch, :new_mr_title
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(options)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @local_project = options[:local_project]
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @local_branch = options[:local_branch]
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @local_code = options[:local_code]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @cli = options[:cli]
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def create(options)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @base_branch = options[:base_branch]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @new_mr_title = options[:new_title]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       7 
16 
     | 
    
         
             
                  begin
         
     | 
| 
       8 
     | 
    
         
            -
                    # Ask these questions right away
         
     | 
| 
       9 
     | 
    
         
            -
                    base_branch
         
     | 
| 
       10 
     | 
    
         
            -
                    new_mr_title
         
     | 
| 
       11 
17 
     | 
    
         
             
                    options = {
         
     | 
| 
       12 
18 
     | 
    
         
             
                      source_branch: local_branch,
         
     | 
| 
       13 
19 
     | 
    
         
             
                      target_branch: base_branch,
         
     | 
| 
      
 20 
     | 
    
         
            +
                      squash: squash_merge_request,
         
     | 
| 
      
 21 
     | 
    
         
            +
                      remove_source_branch: remove_source_branch,
         
     | 
| 
       14 
22 
     | 
    
         
             
                      description: new_mr_body
         
     | 
| 
       15 
23 
     | 
    
         
             
                    }
         
     | 
| 
       16 
24 
     | 
    
         | 
| 
         @@ -33,16 +41,27 @@ module GitHelper 
     | 
|
| 
       33 
41 
     | 
    
         | 
| 
       34 
42 
     | 
    
         
             
                def merge
         
     | 
| 
       35 
43 
     | 
    
         
             
                  begin
         
     | 
| 
       36 
     | 
    
         
            -
                    # Ask these questions right away
         
     | 
| 
       37 
44 
     | 
    
         
             
                    mr_id
         
     | 
| 
       38 
     | 
    
         
            -
                    options = { 
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            +
                    }
         
     | 
| 
       42 
50 
     | 
    
         | 
| 
       43 
51 
     | 
    
         
             
                    puts "Merging merge request: #{mr_id}"
         
     | 
| 
       44 
52 
     | 
    
         
             
                    merge = gitlab_client.accept_merge_request(local_project, mr_id, options)
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 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
         
     | 
| 
       46 
65 
     | 
    
         
             
                  rescue Gitlab::Error::MethodNotAllowed => e
         
     | 
| 
       47 
66 
     | 
    
         
             
                    puts 'Could not merge merge request:'
         
     | 
| 
       48 
67 
     | 
    
         
             
                    puts '  The merge request is not mergeable'
         
     | 
| 
         @@ -55,144 +74,56 @@ module GitHelper 
     | 
|
| 
       55 
74 
     | 
    
         
             
                  end
         
     | 
| 
       56 
75 
     | 
    
         
             
                end
         
     | 
| 
       57 
76 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                private def local_project
         
     | 
| 
       59 
     | 
    
         
            -
                  # Get the project by looking in the remote URLs for the full project name
         
     | 
| 
       60 
     | 
    
         
            -
                  remotes = `git remote -v`
         
     | 
| 
       61 
     | 
    
         
            -
                  return remotes.scan(/\S[\s]*[\S]+.com[\S]{1}([\S]*).git/).first.first
         
     | 
| 
       62 
     | 
    
         
            -
                end
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                private def local_branch
         
     | 
| 
       65 
     | 
    
         
            -
                  # Get the current branch by looking in the list of branches for the *
         
     | 
| 
       66 
     | 
    
         
            -
                  branches = `git branch`
         
     | 
| 
       67 
     | 
    
         
            -
                  return branches.scan(/\*\s([\S]*)/).first.first
         
     | 
| 
       68 
     | 
    
         
            -
                end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                private def read_template
         
     | 
| 
       71 
     | 
    
         
            -
                  if mr_template_options.count == 1
         
     | 
| 
       72 
     | 
    
         
            -
                    apply_template?(mr_template_options.first) ? File.open(mr_template_options.first).read : ''
         
     | 
| 
       73 
     | 
    
         
            -
                  else
         
     | 
| 
       74 
     | 
    
         
            -
                    template_file_name_to_apply = template_to_apply
         
     | 
| 
       75 
     | 
    
         
            -
                    template_file_name_to_apply == "None" ? '' : File.open(template_file_name_to_apply).read
         
     | 
| 
       76 
     | 
    
         
            -
                  end
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                private def mr_id
         
     | 
| 
       80 
     | 
    
         
            -
                  @mr_id ||= cli.ask('Merge Request ID?')
         
     | 
| 
       81 
     | 
    
         
            -
                end
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                private def existing_mr_title
         
     | 
| 
       84 
     | 
    
         
            -
                  @existing_mr_title ||= gitlab_client.merge_request(local_project, mr_id).title
         
     | 
| 
       85 
     | 
    
         
            -
                end
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                private def new_mr_title
         
     | 
| 
       88 
     | 
    
         
            -
                  @new_mr_title ||= accept_autogenerated_title? ? autogenerated_title : cli.ask('Title?')
         
     | 
| 
       89 
     | 
    
         
            -
                end
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
77 
     | 
    
         
             
                private def new_mr_body
         
     | 
| 
       92 
     | 
    
         
            -
                  @new_mr_body ||=  
     | 
| 
      
 78 
     | 
    
         
            +
                  @new_mr_body ||= template_name_to_apply ? local_code.read_template(template_name_to_apply) : ''
         
     | 
| 
       93 
79 
     | 
    
         
             
                end
         
     | 
| 
       94 
80 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
                private def  
     | 
| 
       96 
     | 
    
         
            -
                  @ 
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                private def autogenerated_title
         
     | 
| 
       100 
     | 
    
         
            -
                  @autogenerated_title ||= generate_title
         
     | 
| 
       101 
     | 
    
         
            -
                end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                private def generate_title
         
     | 
| 
       104 
     | 
    
         
            -
                  branch_arr = local_branch.split(local_branch.include?('_') ? '_' : '-')
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                  return if branch_arr.empty?
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                  if branch_arr.length == 1
         
     | 
| 
       109 
     | 
    
         
            -
                    return branch_arr.first.capitalize
         
     | 
| 
       110 
     | 
    
         
            -
                  end
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                  if branch_arr[0].scan(/([\w]+)/).empty? || branch_arr[1].scan(/([\d]+)/).empty?
         
     | 
| 
       113 
     | 
    
         
            -
                    branch_arr[0..-1].join(' ').capitalize
         
     | 
| 
       114 
     | 
    
         
            -
                  else
         
     | 
| 
       115 
     | 
    
         
            -
                    issue = branch_arr[0].upcase
         
     | 
| 
      
 81 
     | 
    
         
            +
                private def template_name_to_apply
         
     | 
| 
      
 82 
     | 
    
         
            +
                  return @template_name_to_apply if @template_name_to_apply
         
     | 
| 
      
 83 
     | 
    
         
            +
                  @template_name_to_apply = nil
         
     | 
| 
       116 
84 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
                  unless mr_template_options.empty?
         
     | 
| 
      
 86 
     | 
    
         
            +
                    if mr_template_options.count == 1
         
     | 
| 
      
 87 
     | 
    
         
            +
                      apply_single_template = cli.apply_template?(mr_template_options.first, 'merge')
         
     | 
| 
      
 88 
     | 
    
         
            +
                      @template_name_to_apply = mr_template_options.first if apply_single_template
         
     | 
| 
       119 
89 
     | 
    
         
             
                    else
         
     | 
| 
       120 
     | 
    
         
            -
                       
     | 
| 
       121 
     | 
    
         
            -
                       
     | 
| 
      
 90 
     | 
    
         
            +
                      response = cli.template_to_apply(mr_template_options, 'merge')
         
     | 
| 
      
 91 
     | 
    
         
            +
                      @template_name_to_apply = response unless response == 'None'
         
     | 
| 
       122 
92 
     | 
    
         
             
                    end
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                    "#{issue} #{description.capitalize}"
         
     | 
| 
       125 
     | 
    
         
            -
                  end
         
     | 
| 
       126 
     | 
    
         
            -
                end
         
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
                private def default_branch
         
     | 
| 
       129 
     | 
    
         
            -
                  return @default_branch if @default_branch
         
     | 
| 
       130 
     | 
    
         
            -
                  page_number = 1
         
     | 
| 
       131 
     | 
    
         
            -
                  counter = 1
         
     | 
| 
       132 
     | 
    
         
            -
                  branches = []
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                  while counter > 0
         
     | 
| 
       135 
     | 
    
         
            -
                    break if default_branch = branches.select { |branch| branch.default }.first
         
     | 
| 
       136 
     | 
    
         
            -
                    page_branches = gitlab_client.branches(local_project, page: page_number, per_page: 100)
         
     | 
| 
       137 
     | 
    
         
            -
                    branches = page_branches
         
     | 
| 
       138 
     | 
    
         
            -
                    counter = page_branches.count
         
     | 
| 
       139 
     | 
    
         
            -
                    page_number += 1
         
     | 
| 
       140 
93 
     | 
    
         
             
                  end
         
     | 
| 
       141 
94 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
                  @ 
     | 
| 
       143 
     | 
    
         
            -
                end
         
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
                private def template_to_apply
         
     | 
| 
       146 
     | 
    
         
            -
                  return @template_to_apply if @template_to_apply
         
     | 
| 
       147 
     | 
    
         
            -
                  complete_options = mr_template_options << 'None'
         
     | 
| 
       148 
     | 
    
         
            -
                  index = cli.ask_options("Which merge request template should be applied?", complete_options)
         
     | 
| 
       149 
     | 
    
         
            -
                  @template_to_apply = complete_options[index]
         
     | 
| 
      
 95 
     | 
    
         
            +
                  @template_name_to_apply
         
     | 
| 
       150 
96 
     | 
    
         
             
                end
         
     | 
| 
       151 
97 
     | 
    
         | 
| 
       152 
98 
     | 
    
         
             
                private def mr_template_options
         
     | 
| 
       153 
     | 
    
         
            -
                   
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
      
 99 
     | 
    
         
            +
                  @mr_template_options ||= local_code.template_options({
         
     | 
| 
      
 100 
     | 
    
         
            +
                                             nested_directory_name: 'merge_request_templates',
         
     | 
| 
      
 101 
     | 
    
         
            +
                                             non_nested_file_name: 'merge_request_template'
         
     | 
| 
      
 102 
     | 
    
         
            +
                                           })
         
     | 
| 
       157 
103 
     | 
    
         
             
                end
         
     | 
| 
       158 
104 
     | 
    
         | 
| 
       159 
     | 
    
         
            -
                private def  
     | 
| 
       160 
     | 
    
         
            -
                   
     | 
| 
       161 
     | 
    
         
            -
                  !!(answer =~ /^y/i)
         
     | 
| 
      
 105 
     | 
    
         
            +
                private def mr_id
         
     | 
| 
      
 106 
     | 
    
         
            +
                  @mr_id ||= cli.code_request_id('Merge')
         
     | 
| 
       162 
107 
     | 
    
         
             
                end
         
     | 
| 
       163 
108 
     | 
    
         | 
| 
       164 
     | 
    
         
            -
                private def  
     | 
| 
       165 
     | 
    
         
            -
                   
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                  if title
         
     | 
| 
       168 
     | 
    
         
            -
                    answer = cli.ask("Accept the autogenerated merge request title '#{title}'? (y/n)")
         
     | 
| 
       169 
     | 
    
         
            -
                    !!(answer =~ /^y/i)
         
     | 
| 
       170 
     | 
    
         
            -
                  else
         
     | 
| 
       171 
     | 
    
         
            -
                    false
         
     | 
| 
       172 
     | 
    
         
            -
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                private def squash_merge_request
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @squash_merge_request ||= cli.squash_merge_request?
         
     | 
| 
       173 
111 
     | 
    
         
             
                end
         
     | 
| 
       174 
112 
     | 
    
         | 
| 
       175 
     | 
    
         
            -
                private def  
     | 
| 
       176 
     | 
    
         
            -
                   
     | 
| 
       177 
     | 
    
         
            -
                  !!(answer =~ /^y/i)
         
     | 
| 
      
 113 
     | 
    
         
            +
                private def remove_source_branch
         
     | 
| 
      
 114 
     | 
    
         
            +
                  @remove_source_branch ||= existing_project.remove_source_branch_after_merge || cli.remove_source_branch?
         
     | 
| 
       178 
115 
     | 
    
         
             
                end
         
     | 
| 
       179 
116 
     | 
    
         | 
| 
       180 
     | 
    
         
            -
                private def  
     | 
| 
       181 
     | 
    
         
            -
                   
     | 
| 
       182 
     | 
    
         
            -
                  !!(answer =~ /^y/i)
         
     | 
| 
      
 117 
     | 
    
         
            +
                private def existing_project
         
     | 
| 
      
 118 
     | 
    
         
            +
                  @existing_project ||= gitlab_client.project(local_project)
         
     | 
| 
       183 
119 
     | 
    
         
             
                end
         
     | 
| 
       184 
120 
     | 
    
         | 
| 
       185 
     | 
    
         
            -
                private def  
     | 
| 
       186 
     | 
    
         
            -
                   
     | 
| 
       187 
     | 
    
         
            -
                  !!(answer =~ /^y/i)
         
     | 
| 
      
 121 
     | 
    
         
            +
                private def existing_mr
         
     | 
| 
      
 122 
     | 
    
         
            +
                  @existing_mr ||= gitlab_client.merge_request(local_project, mr_id)
         
     | 
| 
       188 
123 
     | 
    
         
             
                end
         
     | 
| 
       189 
124 
     | 
    
         | 
| 
       190 
125 
     | 
    
         
             
                private def gitlab_client
         
     | 
| 
       191 
126 
     | 
    
         
             
                  @gitlab_client ||= GitHelper::GitLabClient.new.client
         
     | 
| 
       192 
127 
     | 
    
         
             
                end
         
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
                private def cli
         
     | 
| 
       195 
     | 
    
         
            -
                  @cli ||= GitHelper::HighlineCli.new
         
     | 
| 
       196 
     | 
    
         
            -
                end
         
     | 
| 
       197 
128 
     | 
    
         
             
              end
         
     | 
| 
       198 
129 
     | 
    
         
             
            end
         
     |