Class: GitReview::Local
- Inherits:
-
Object
- Object
- GitReview::Local
- Includes:
- Internals
- Defined in:
- lib/git-review/local.rb
Overview
The local repository is where the git-review command is being called by default. It is (supposedly) able to handle systems other than Github. TODO: remove Github-dependency
Instance Attribute Summary collapse
-
#config ⇒ Object
Returns the value of attribute config.
Class Method Summary collapse
-
.instance ⇒ Object
acts like a singleton class but it’s actually not use ::GitReview::Local.instance everywhere except in tests.
Instance Method Summary collapse
-
#add_pull_refspec ⇒ Object
add remote.origin.fetch to check out pull request locally see https://help.github.com/articles/checking-out-pull-requests-locally.
-
#all_branches ⇒ Array<String>
All existing branches.
-
#branch_exists?(location, branch_name) ⇒ Boolean
Whether a branch exists in a specified location.
-
#clean_all ⇒ Object
clean all obsolete branches.
-
#clean_single(number, force = false) ⇒ Object
clean a single request’s obsolete branch.
- #config_list ⇒ Object
-
#delete_branch(branch_name) ⇒ Object
delete local and remote branches that match a given name.
-
#delete_local_branch(branch_name) ⇒ Object
delete local branch if it exists.
-
#delete_remote_branch(branch_name) ⇒ Object
delete remote branch if it exists.
- #github ⇒ Object
-
#head ⇒ String
The head string used for pull requests.
-
#initialize ⇒ Local
constructor
A new instance of Local.
- #load_config ⇒ Object
-
#merged?(sha) ⇒ Boolean
Whether a specified commit has already been merged.
-
#on_feature_branch? ⇒ Boolean
Whether already on a feature branch.
-
#protected_branches ⇒ Array<String>
All open requests’ branches shouldn’t be deleted.
-
#review_branches ⇒ Array<String>
All review branches with ‘review_’ prefix.
-
#source ⇒ String
Combine source repo and branch.
-
#source_branch ⇒ String
The current source branch.
-
#source_repo ⇒ String
The source repo.
-
#target ⇒ String
Combine target repo and branch.
-
#target_branch ⇒ String
The name of the target branch.
-
#target_repo(upstream = false) ⇒ String
if to send a pull request to upstream repo, get the parent as target.
-
#uncommitted_changes? ⇒ Boolean
Whether there are local changes not committed.
-
#unmerged_commits?(branch_name, verbose = true) ⇒ Boolean
Whether there are unmerged commits on the local or remote branch.
Constructor Details
#initialize ⇒ Local
Returns a new instance of Local.
18 19 20 21 22 23 24 25 26 |
# File 'lib/git-review/local.rb', line 18 def initialize # find root git directory if currently in subdirectory if git_call('rev-parse --show-toplevel').strip.empty? raise ::GitReview::InvalidGitRepositoryError else add_pull_refspec load_config end end |
Instance Attribute Details
#config ⇒ Object
Returns the value of attribute config.
10 11 12 |
# File 'lib/git-review/local.rb', line 10 def config @config end |
Class Method Details
.instance ⇒ Object
acts like a singleton class but it’s actually not use ::GitReview::Local.instance everywhere except in tests
14 15 16 |
# File 'lib/git-review/local.rb', line 14 def self.instance @instance ||= new end |
Instance Method Details
#add_pull_refspec ⇒ Object
add remote.origin.fetch to check out pull request locally see https://help.github.com/articles/checking-out-pull-requests-locally
198 199 200 201 202 |
# File 'lib/git-review/local.rb', line 198 def add_pull_refspec refspec = '+refs/pull/*/head:refs/remotes/origin/pr/*' fetch_config = "config --local --add remote.origin.fetch #{refspec}" git_call(fetch_config, false) unless config_list.include?(refspec) end |
#all_branches ⇒ Array<String>
Returns all existing branches.
29 30 31 |
# File 'lib/git-review/local.rb', line 29 def all_branches git_call('branch -a').split("\n").collect { |s| s.strip } end |
#branch_exists?(location, branch_name) ⇒ Boolean
Returns whether a branch exists in a specified location.
97 98 99 100 101 |
# File 'lib/git-review/local.rb', line 97 def branch_exists?(location, branch_name) return false unless [:remote, :local].include?(location) prefix = location == :remote ? 'remotes/origin/' : '' all_branches.include?(prefix + branch_name) end |
#clean_all ⇒ Object
clean all obsolete branches
64 65 66 67 68 69 |
# File 'lib/git-review/local.rb', line 64 def clean_all (review_branches - protected_branches).each do |branch_name| # only clean up obsolete branches. delete_branch(branch_name) unless unmerged_commits?(branch_name, false) end end |
#clean_single(number, force = false) ⇒ Object
clean a single request’s obsolete branch
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/git-review/local.rb', line 47 def clean_single(number, force=false) request = github.pull_request(source_repo, number) if request && request.state == 'closed' # ensure there are no unmerged commits or '--force' flag has been set branch_name = request.head.ref if unmerged_commits?(branch_name) && !force puts "Won't delete branches that contain unmerged commits." puts "Use '--force' to override." else delete_branch(branch_name) end end rescue Octokit::NotFound false end |
#config_list ⇒ Object
217 218 219 |
# File 'lib/git-review/local.rb', line 217 def config_list git_call('config --list', false) end |
#delete_branch(branch_name) ⇒ Object
delete local and remote branches that match a given name
73 74 75 76 |
# File 'lib/git-review/local.rb', line 73 def delete_branch(branch_name) delete_local_branch(branch_name) delete_remote_branch(branch_name) end |
#delete_local_branch(branch_name) ⇒ Object
delete local branch if it exists.
80 81 82 83 84 |
# File 'lib/git-review/local.rb', line 80 def delete_local_branch(branch_name) if branch_exists?(:local, branch_name) git_call("branch -D #{branch_name}", true) end end |
#delete_remote_branch(branch_name) ⇒ Object
delete remote branch if it exists.
88 89 90 91 92 |
# File 'lib/git-review/local.rb', line 88 def delete_remote_branch(branch_name) if branch_exists?(:remote, branch_name) git_call("push origin :#{branch_name}", true) end end |
#github ⇒ Object
221 222 223 |
# File 'lib/git-review/local.rb', line 221 def github @github ||= ::GitReview::Github.instance end |
#head ⇒ String
Returns the head string used for pull requests.
183 184 185 186 |
# File 'lib/git-review/local.rb', line 183 def head # in the form of 'user:branch' "#{github.github.login}:#{source_branch}" end |
#load_config ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/git-review/local.rb', line 204 def load_config @config = {} config_list.split("\n").each do |line| key, value = line.split(/=/, 2) if @config[key] && @config[key] != value @config[key] = [@config[key]].flatten << value else @config[key] = value end end @config end |
#merged?(sha) ⇒ Boolean
Returns whether a specified commit has already been merged.
141 142 143 |
# File 'lib/git-review/local.rb', line 141 def merged?(sha) not git_call("rev-list #{sha} ^HEAD 2>&1").split("\n").size > 0 end |
#on_feature_branch? ⇒ Boolean
Returns whether already on a feature branch.
189 190 191 192 193 194 |
# File 'lib/git-review/local.rb', line 189 def on_feature_branch? # If current and target are the same, we are not on a feature branch. # If they are different, but we are on master, we should still to switch # to a separate branch (since master makes for a poor feature branch). source_branch != target_branch && source_branch != 'master' end |
#protected_branches ⇒ Array<String>
Returns all open requests’ branches shouldn’t be deleted.
34 35 36 |
# File 'lib/git-review/local.rb', line 34 def protected_branches github.current_requests.collect { |r| r.head.ref } end |
#review_branches ⇒ Array<String>
Returns all review branches with ‘review_’ prefix.
39 40 41 42 43 44 |
# File 'lib/git-review/local.rb', line 39 def review_branches all_branches.collect { |branch| # only use uniq branch names (no matter if local or remote) branch.split('/').last if branch.include?('review_') }.compact.uniq end |
#source ⇒ String
Returns combine source repo and branch.
156 157 158 |
# File 'lib/git-review/local.rb', line 156 def source "#{source_repo}/#{source_branch}" end |
#source_branch ⇒ String
Returns the current source branch.
151 152 153 |
# File 'lib/git-review/local.rb', line 151 def source_branch git_call('branch').chomp.match(/\*(.*)/)[0][2..-1] end |
#source_repo ⇒ String
Returns the source repo.
146 147 148 |
# File 'lib/git-review/local.rb', line 146 def source_repo github.source_repo end |
#target ⇒ String
Returns combine target repo and branch.
178 179 180 |
# File 'lib/git-review/local.rb', line 178 def target "#{target_repo}/#{target_branch}" end |
#target_branch ⇒ String
Returns the name of the target branch.
161 162 163 164 |
# File 'lib/git-review/local.rb', line 161 def target_branch # TODO: Manually override this and set arbitrary branches ENV['TARGET_BRANCH'] || 'master' end |
#target_repo(upstream = false) ⇒ String
if to send a pull request to upstream repo, get the parent as target
168 169 170 171 172 173 174 175 |
# File 'lib/git-review/local.rb', line 168 def target_repo(upstream=false) # TODO: Manually override this and set arbitrary repositories if upstream github.repository(source_repo).parent.full_name else source_repo end end |
#uncommitted_changes? ⇒ Boolean
Returns whether there are local changes not committed.
104 105 106 |
# File 'lib/git-review/local.rb', line 104 def uncommitted_changes? !git_call('diff HEAD').empty? end |
#unmerged_commits?(branch_name, verbose = true) ⇒ Boolean
Returns whether there are unmerged commits on the local or remote branch.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/git-review/local.rb', line 112 def unmerged_commits?(branch_name, verbose=true) locations = [] locations << '' if branch_exists?(:local, branch_name) locations << 'origin/' if branch_exists?(:remote, branch_name) locations = locations.repeated_permutation(2).to_a if locations.empty? puts 'Nothing to do. All cleaned up already.' if verbose return false end # compare remote and local branch with remote and local master responses = locations.collect { |loc| git_call "cherry #{loc.first}#{target_branch} #{loc.last}#{branch_name}" } # select commits (= non empty, not just an error message and not only # duplicate commits staring with '-'). unmerged_commits = responses.reject { |response| response.empty? or response.include?('fatal: Unknown commit') or response.split("\n").reject { |x| x.index('-') == 0 }.empty? } # if the array ain't empty, we got unmerged commits if unmerged_commits.empty? false else puts "Unmerged commits on branch '#{branch_name}'." true end end |