Module: SugarJar::Util
- Included in:
- Commands, RepoConfig
- Defined in:
- lib/sugarjar/util.rb
Overview
Some common methods needed by other classes
Instance Method Summary collapse
- #all_local_branches ⇒ Object
- #all_remote_branches(remote = 'origin') ⇒ Object
- #all_remotes ⇒ Object
- #assert_common_main_branch ⇒ Object
- #assert_in_repo ⇒ Object
- #branch_from_ref(ref, type = :local) ⇒ Object
-
#canonicalize_repo(repo) ⇒ Object
gh utils will default to https, but we should always default to SSH unless otherwise specified since https will cause prompting.
- #checkout_main_branch ⇒ Object
- #color(string, *colors) ⇒ Object
- #current_branch ⇒ Object
- #determine_main_branch(branches) ⇒ Object
- #die(msg) ⇒ Object
- #dirty? ⇒ Boolean
- #extract_org(repo) ⇒ Object
- #extract_repo(repo) ⇒ Object
- #fetch(remote) ⇒ Object
- #fetch_upstream ⇒ Object
- #forked_repo(repo, username) ⇒ Object
- #fprefix(name) ⇒ Object
- #gh_avail? ⇒ Boolean
- #ghcli(*args) ⇒ Object
- #ghcli_nofail(*args) ⇒ Object
- #git(*args) ⇒ Object
- #git_nofail(*args) ⇒ Object
- #in_repo ⇒ Object
- #main_branch ⇒ Object
- #main_remote_branch(remote) ⇒ Object
- #most_main ⇒ Object
- #pastel ⇒ Object
-
#push_org ⇒ Object
Whatever org we push to, regardless of if this is a fork or not.
- #repo_name ⇒ Object
- #repo_root ⇒ Object
- #run_prepush ⇒ Object
- #set_commit_template ⇒ Object
-
#subfeature?(base) ⇒ Boolean
determine if this branch is based on another local branch (i.e. is a subfeature).
- #tracked_branch(fallback: true) ⇒ Object
- #upstream ⇒ Object
- #which(cmd) ⇒ Object
-
#which_nofail(cmd) ⇒ Object
Finds the first entry in the path for a binary and checks to make sure it’s not us.
Instance Method Details
#all_local_branches ⇒ Object
160 161 162 163 164 165 166 167 168 |
# File 'lib/sugarjar/util.rb', line 160 def all_local_branches git( 'branch', '--format', '%(refname)' ).stdout.lines.map do |line| next if line.start_with?('(HEAD detached') branch_from_ref(line.strip) end end |
#all_remote_branches(remote = 'origin') ⇒ Object
150 151 152 153 154 155 156 157 158 |
# File 'lib/sugarjar/util.rb', line 150 def all_remote_branches(remote = 'origin') branches = [] git('branch', '-r', '--format', '%(refname)').stdout.lines.each do |line| next unless line.start_with?("refs/remotes/#{remote}/") branches << branch_from_ref(line.strip, :remote) end branches end |
#all_remotes ⇒ Object
170 171 172 |
# File 'lib/sugarjar/util.rb', line 170 def all_remotes git('remote').stdout.lines.map(&:strip) end |
#assert_common_main_branch ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/sugarjar/util.rb', line 101 def assert_common_main_branch upstream_branch = main_remote_branch(upstream) unless main_branch == upstream_branch die( "The local main branch is '#{main_branch}', but the main branch " + "of the #{upstream} remote is '#{upstream_branch}'. You probably " + "want to rename your local branch by doing:\n\t" + "git branch -m #{main_branch} #{upstream_branch}\n\t" + "git fetch #{upstream}\n\t" + "git branch -u #{upstream}/#{upstream_branch} #{upstream_branch}\n" + "\tgit remote set-head #{upstream} -a", ) end return if upstream_branch == 'origin' origin_branch = main_remote_branch('origin') return if origin_branch == upstream_branch die( "The main branch of your upstream (#{upstream_branch}) and your " + "fork/origin (#{origin_branch}) are not the same. You should go " + "to https://#{@ghhost || 'github.com'}/#{@ghuser}/#{repo_name}/" + 'branches/ and rename the \'default\' branch to ' + "'#{upstream_branch}'. It will then give you some commands to " + 'run to update this clone.', ) end |
#assert_in_repo ⇒ Object
129 130 131 |
# File 'lib/sugarjar/util.rb', line 129 def assert_in_repo die('sugarjar must be run from inside a git repo') unless in_repo end |
#branch_from_ref(ref, type = :local) ⇒ Object
245 246 247 248 249 250 |
# File 'lib/sugarjar/util.rb', line 245 def branch_from_ref(ref, type = :local) # local branches are refs/head/XXXX # remote branches are refs/remotes/<remote>/XXXX base = type == :local ? 2 : 3 ref.split('/')[base..].join('/') end |
#canonicalize_repo(repo) ⇒ Object
gh utils will default to https, but we should always default to SSH unless otherwise specified since https will cause prompting.
34 35 36 37 38 39 40 41 42 |
# File 'lib/sugarjar/util.rb', line 34 def canonicalize_repo(repo) # if they fully-qualified it, we're good return repo if repo.start_with?('http', 'git@') # otherwise, ti's a shortname cr = "git@#{@ghhost || 'github.com'}:#{repo}.git" SugarJar::Log.debug("canonicalized #{repo} to #{cr}") cr end |
#checkout_main_branch ⇒ Object
146 147 148 |
# File 'lib/sugarjar/util.rb', line 146 def checkout_main_branch git('checkout', main_branch) end |
#color(string, *colors) ⇒ Object
252 253 254 255 256 257 258 |
# File 'lib/sugarjar/util.rb', line 252 def color(string, *colors) if @color pastel.decorate(string, *colors) else string end end |
#current_branch ⇒ Object
174 175 176 |
# File 'lib/sugarjar/util.rb', line 174 def current_branch branch_from_ref(git('symbolic-ref', 'HEAD').stdout.strip) end |
#determine_main_branch(branches) ⇒ Object
133 134 135 |
# File 'lib/sugarjar/util.rb', line 133 def determine_main_branch(branches) branches.include?('main') ? 'main' : 'master' end |
#die(msg) ⇒ Object
96 97 98 99 |
# File 'lib/sugarjar/util.rb', line 96 def die(msg) SugarJar::Log.fatal(msg) exit(1) end |
#dirty? ⇒ Boolean
361 362 363 364 |
# File 'lib/sugarjar/util.rb', line 361 def dirty? s = git_nofail('diff', '--quiet') s.error? end |
#extract_org(repo) ⇒ Object
8 9 10 11 12 13 14 15 16 17 |
# File 'lib/sugarjar/util.rb', line 8 def extract_org(repo) if repo.start_with?('http') File.basename(File.dirname(repo)) elsif repo.start_with?('git@') repo.split(':')[1].split('/')[0] else # assume they passed in a ghcli-friendly name repo.split('/').first end end |
#extract_repo(repo) ⇒ Object
19 20 21 |
# File 'lib/sugarjar/util.rb', line 19 def extract_repo(repo) File.basename(repo, '.git') end |
#fetch(remote) ⇒ Object
183 184 185 |
# File 'lib/sugarjar/util.rb', line 183 def fetch(remote) git('fetch', remote) end |
#fetch_upstream ⇒ Object
178 179 180 181 |
# File 'lib/sugarjar/util.rb', line 178 def fetch_upstream us = upstream fetch(us) if us end |
#forked_repo(repo, username) ⇒ Object
23 24 25 26 27 28 29 30 |
# File 'lib/sugarjar/util.rb', line 23 def forked_repo(repo, username) repo = if repo.start_with?('http', 'git@') File.basename(repo) else "#{File.basename(repo)}.git" end "git@#{@ghhost || 'github.com'}:#{username}/#{repo}" end |
#fprefix(name) ⇒ Object
271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/sugarjar/util.rb', line 271 def fprefix(name) return name unless @feature_prefix return name if name.start_with?(@feature_prefix) return name if all_local_branches.include?(name) newname = "#{@feature_prefix}#{name}" SugarJar::Log.debug( "Munging feature name: #{name} -> #{newname} due to feature prefix", ) newname end |
#gh_avail? ⇒ Boolean
267 268 269 |
# File 'lib/sugarjar/util.rb', line 267 def gh_avail? !!which_nofail('gh') end |
#ghcli(*args) ⇒ Object
350 351 352 353 354 |
# File 'lib/sugarjar/util.rb', line 350 def ghcli(*args) s = ghcli_nofail(*args) s.error! s end |
#ghcli_nofail(*args) ⇒ Object
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/sugarjar/util.rb', line 325 def ghcli_nofail(*args) SugarJar::Log.trace("Running: gh #{args.join(' ')}") s = Mixlib::ShellOut.new([which('gh')] + args).run_command if s.error? && s.stderr.include?('gh auth') SugarJar::Log.info( 'gh was run but no github token exists. Will run "gh auth login" ' + "to force\ngh to authenticate...", ) ENV['GITHUB_HOST'] = @ghhost if @ghhost args = [ which('gh'), 'auth', 'login', '-p', 'ssh' ] args + ['--hostname', @ghhost] if @ghhost unless system(which('gh'), 'auth', 'login', '-p', 'ssh') SugarJar::Log.fatal( 'That failed, I will bail out. Hub needs to get a github ' + 'token. Try running "gh auth login" (will list info about ' + 'your account) and try this again when that works.', ) exit(1) end end s end |
#git(*args) ⇒ Object
319 320 321 322 323 |
# File 'lib/sugarjar/util.rb', line 319 def git(*args) s = git_nofail(*args) s.error! s end |
#git_nofail(*args) ⇒ Object
310 311 312 313 314 315 316 317 |
# File 'lib/sugarjar/util.rb', line 310 def git_nofail(*args) if %w{diff log grep branch}.include?(args[0]) && args.none? { |x| x.include?('color') } args << (@color ? '--color' : '--no-color') end SugarJar::Log.trace("Running: git #{args.join(' ')}") Mixlib::ShellOut.new([which('git')] + args).run_command end |
#in_repo ⇒ Object
356 357 358 359 |
# File 'lib/sugarjar/util.rb', line 356 def in_repo s = git_nofail('rev-parse', '--is-inside-work-tree') !s.error? && s.stdout.strip == 'true' end |
#main_branch ⇒ Object
137 138 139 |
# File 'lib/sugarjar/util.rb', line 137 def main_branch @main_branch = determine_main_branch(all_local_branches) end |
#main_remote_branch(remote) ⇒ Object
141 142 143 144 |
# File 'lib/sugarjar/util.rb', line 141 def main_remote_branch(remote) @main_remote_branches[remote] ||= determine_main_branch(all_remote_branches(remote)) end |
#most_main ⇒ Object
211 212 213 214 215 216 217 218 |
# File 'lib/sugarjar/util.rb', line 211 def most_main us = upstream if us "#{us}/#{main_branch}" else main_branch end end |
#pastel ⇒ Object
260 261 262 263 264 265 |
# File 'lib/sugarjar/util.rb', line 260 def pastel @pastel ||= begin require 'pastel' Pastel.new end end |
#push_org ⇒ Object
Whatever org we push to, regardless of if this is a fork or not
240 241 242 243 |
# File 'lib/sugarjar/util.rb', line 240 def push_org url = git('remote', 'get-url', 'origin').stdout.strip extract_org(url) end |
#repo_name ⇒ Object
370 371 372 |
# File 'lib/sugarjar/util.rb', line 370 def repo_name repo_root.split('/').last end |
#repo_root ⇒ Object
366 367 368 |
# File 'lib/sugarjar/util.rb', line 366 def repo_root git('rev-parse', '--show-toplevel').stdout.strip end |
#run_prepush ⇒ Object
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/sugarjar/util.rb', line 85 def run_prepush @repo_config['on_push']&.each do |item| SugarJar::Log.debug("Running on_push check type #{item}") unless send(:run_check, item) SugarJar::Log.info("[prepush]: #{item} #{color('failed', :red)}.") return false end end true end |
#set_commit_template ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/sugarjar/util.rb', line 44 def set_commit_template unless in_repo SugarJar::Log.debug('Skipping set_commit_template: not in repo') return end realpath = if @repo_config['commit_template'].start_with?('/') @repo_config['commit_template'] else "#{repo_root}/#{@repo_config['commit_template']}" end unless File.exist?(realpath) die( "Repo config specifies #{@repo_config['commit_template']} as the " + 'commit template, but that file does not exist.', ) end s = git_nofail('config', '--local', 'commit.template') unless s.error? current = s.stdout.strip if current == @repo_config['commit_template'] SugarJar::Log.debug('Commit template already set correctly') return else SugarJar::Log.warn( "Updating repo-specific commit template from #{current} " + "to #{@repo_config['commit_template']}", ) end end SugarJar::Log.debug( 'Setting repo-specific commit template to ' + "#{@repo_config['commit_template']} per sugarjar repo config.", ) git( 'config', '--local', 'commit.template', @repo_config['commit_template'] ) end |
#subfeature?(base) ⇒ Boolean
determine if this branch is based on another local branch (i.e. is a subfeature). Used to figure out of we should stack the PR
189 190 191 |
# File 'lib/sugarjar/util.rb', line 189 def subfeature?(base) all_local_branches.reject { |x| x == most_main }.include?(base) end |
#tracked_branch(fallback: true) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/sugarjar/util.rb', line 193 def tracked_branch(fallback: true) branch = nil s = git_nofail( 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}' ) if s.error? branch = fallback ? most_main : nil SugarJar::Log.debug("No specific tracked branch, using #{branch}") else branch = s.stdout.strip SugarJar::Log.debug( "Using explicit tracked branch: #{branch}, use " + '`git branch -u` to change', ) end branch end |
#upstream ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/sugarjar/util.rb', line 220 def upstream return @remote if @remote remotes = all_remotes SugarJar::Log.debug("remotes is #{remotes}") if remotes.empty? @remote = nil elsif remotes.length == 1 @remote = remotes[0] elsif remotes.include?('upstream') @remote = 'upstream' elsif remotes.include?('origin') @remote = 'origin' else raise 'Could not determine "upstream" remote to use...' end @remote end |
#which(cmd) ⇒ Object
302 303 304 305 306 307 308 |
# File 'lib/sugarjar/util.rb', line 302 def which(cmd) path = which_nofail(cmd) return path if path SugarJar::Log.fatal("Could not find #{cmd} in your path") exit(1) end |
#which_nofail(cmd) ⇒ Object
Finds the first entry in the path for a binary and checks to make sure it’s not us. Warn if it is us as that won’t work in 2.x
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/sugarjar/util.rb', line 286 def which_nofail(cmd) ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir| p = File.join(dir, cmd) next unless File.exist?(p) && File.executable?(p) if File.basename(File.realpath(p)) == 'sj' SugarJar::Log.error( "'#{cmd}' is linked to 'sj' which is no longer supported.", ) next end return p end false end |