Class: Dev::Git
- Defined in:
- lib/firespring_dev_commands/git.rb,
lib/firespring_dev_commands/git/info.rb
Overview
Class for performing git functions
Defined Under Namespace
Constant Summary collapse
- DEFAULT_MAIN_BRANCH =
The default base branch to use
'master'.freeze
Instance Attribute Summary collapse
-
#info ⇒ Object
Returns the value of attribute info.
-
#main_branch ⇒ Object
Returns the value of attribute main_branch.
-
#original_branches ⇒ Object
Populates and returns a hash containing the original version of branches.
-
#release_branches ⇒ Object
Returns the value of attribute release_branches.
-
#staging_branch ⇒ Object
Returns the value of attribute staging_branch.
Class Method Summary collapse
-
.config {|@config| ... } ⇒ Object
(also: configure)
Instantiates a new top level config object if one hasn’t already been created Yields that config object to any given block Returns the resulting config object.
-
.version ⇒ Object
Returns the version of the git executable running on the system.
Instance Method Summary collapse
-
#add(*paths, dir: default_project_dir, raise_errors: false) ⇒ Object
Add the given paths to git Defaults to the current directory optionally raise errors.
-
#branch_exists?(project_dir, branch_name) ⇒ Boolean
Returns true if the remote branch exists, false otherwise.
-
#branch_name(dir: default_project_dir) ⇒ Object
Returns the branch name associated with the given repository Defaults to the current directory.
-
#center_pad(string = '', pad: '-', len: 80) ⇒ Object
deprecated
Deprecated.
Please use Common#center_pad instead
-
#changes(dir: default_project_dir) ⇒ Object
Print the changes on the given repo Defaults to the current directory.
-
#changes_slow(dir: default_project_dir) ⇒ Object
Print the changes on the given repo using the ruby built-in method…
-
#check_version ⇒ Object
Checks the min and max version against the current git version if they have been configured.
-
#checkout(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Checks out the given branch in the given repo Defaults to the current directory optionally raise errors.
-
#checkout_all(branch) ⇒ Object
Checks out the given branch in all repositories with some additional formatting.
-
#clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil, depth: nil) ⇒ Object
Clones the repo_name into the dir Optionally specify a repo_org Optionally specify a branch to check out (defaults to the repository default branch).
-
#clone_repos ⇒ Object
Clones all repositories.
-
#create_branch(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Create the given branch in the given repo Defaults to the current directory optionally raise errors.
-
#current_branches ⇒ Object
Returns a hash of each project repo and the branch that is currently checked out.
-
#default_project_dir ⇒ Object
Returns the first configured project dire.
-
#indent(string, padding: ' ') ⇒ Object
Split on newlines and add additional padding.
-
#initialize(main_branch: self.class.config.main_branch, staging_branch: self.class.config.staging_branch, info: self.class.config.info) ⇒ Git
constructor
A new instance of Git.
-
#merge(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Merge the given branch into the given repo Defaults to the current directory optionally raise errors.
-
#merge_all(branch) ⇒ Object
Merge the branch into all repositories.
-
#project_dirs ⇒ Object
Returns all git paths configured in our info.
-
#pull(dir: default_project_dir, raise_errors: false) ⇒ Object
Pull the given repo Defaults to the current directory optionally raise errors.
-
#pull_all ⇒ Object
Pull the latest in all repositories.
-
#push(dir: default_project_dir, raise_errors: false) ⇒ Object
Push the given repo Defaults to the current directory optionally raise errors.
-
#push_all ⇒ Object
Push to remote in all repositories.
-
#repos_with_changes ⇒ Object
Returns the name of any repositories which have changes.
-
#reset(dir: default_project_dir) ⇒ Object
Runs a git reset on the given repo Defaults to the current directory.
-
#reset_all ⇒ Object
Runs a git reset on all given repositories with some additional formatting.
-
#ssh_repo_url(name, org) ⇒ Object
Builds an ssh repo URL using the org and repo name given.
-
#status(dir: default_project_dir) ⇒ Object
Prints the results of the status command Currently running “git status” instead of using the library because it doesn’t do well formatting the output.
-
#status_all ⇒ Object
Prints the status of multiple repository directories and displays the results in a nice format.
Constructor Details
#initialize(main_branch: self.class.config.main_branch, staging_branch: self.class.config.staging_branch, info: self.class.config.info) ⇒ Git
Returns a new instance of Git.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/firespring_dev_commands/git.rb', line 42 def initialize( main_branch: self.class.config.main_branch, staging_branch: self.class.config.staging_branch, info: self.class.config.info ) @main_branch = main_branch raise 'main branch must be configured' if main_branch.to_s.empty? @staging_branch = staging_branch || main_branch @info = Array(info) raise 'git repositories must be configured' if @info.empty? || !@info.all?(Dev::Git::Info) check_version end |
Instance Attribute Details
#info ⇒ Object
Returns the value of attribute info.
40 41 42 |
# File 'lib/firespring_dev_commands/git.rb', line 40 def info @info end |
#main_branch ⇒ Object
Returns the value of attribute main_branch.
40 41 42 |
# File 'lib/firespring_dev_commands/git.rb', line 40 def main_branch @main_branch end |
#original_branches ⇒ Object
Populates and returns a hash containing the original version of branches
77 78 79 |
# File 'lib/firespring_dev_commands/git.rb', line 77 def original_branches @original_branches end |
#release_branches ⇒ Object
Returns the value of attribute release_branches.
40 41 42 |
# File 'lib/firespring_dev_commands/git.rb', line 40 def release_branches @release_branches end |
#staging_branch ⇒ Object
Returns the value of attribute staging_branch.
40 41 42 |
# File 'lib/firespring_dev_commands/git.rb', line 40 def staging_branch @staging_branch end |
Class Method Details
.config {|@config| ... } ⇒ Object Also known as: configure
Instantiates a new top level config object if one hasn’t already been created Yields that config object to any given block Returns the resulting config object
25 26 27 28 29 |
# File 'lib/firespring_dev_commands/git.rb', line 25 def config @config ||= Config.new yield(@config) if block_given? @config end |
.version ⇒ Object
Returns the version of the git executable running on the system
35 36 37 |
# File 'lib/firespring_dev_commands/git.rb', line 35 def version @version ||= ::Git::Lib.new(nil, nil).current_command_version.join('.') end |
Instance Method Details
#add(*paths, dir: default_project_dir, raise_errors: false) ⇒ Object
Add the given paths to git Defaults to the current directory optionally raise errors
268 269 270 271 272 273 274 275 276 277 |
# File 'lib/firespring_dev_commands/git.rb', line 268 def add(*paths, dir: default_project_dir, raise_errors: false) g = ::Git.open(dir) indent g.add(paths) true rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#branch_exists?(project_dir, branch_name) ⇒ Boolean
Returns true if the remote branch exists, false otherwise
104 105 106 |
# File 'lib/firespring_dev_commands/git.rb', line 104 def branch_exists?(project_dir, branch_name) ::Git.ls_remote(project_dir)['remotes']["origin/#{branch_name}"] end |
#branch_name(dir: default_project_dir) ⇒ Object
Returns the branch name associated with the given repository Defaults to the current directory
96 97 98 99 100 101 |
# File 'lib/firespring_dev_commands/git.rb', line 96 def branch_name(dir: default_project_dir) return unless File.exist?(dir) g = ::Git.open(dir) g.current_branch || "HEAD detached at #{g.object('HEAD').sha[0..7]}" end |
#center_pad(string = '', pad: '-', len: 80) ⇒ Object
Please use Common#center_pad instead
Center the string and pad on either side with the given padding character
440 441 442 443 |
# File 'lib/firespring_dev_commands/git.rb', line 440 def center_pad(string = '', pad: '-', len: 80) warn '[DEPRECATION] `Dev::Git#center_pad` is deprecated. Please use `Dev::Common#center_pad` instead.' Dev::Common.new.center_pad(string, pad:, len:) end |
#changes(dir: default_project_dir) ⇒ Object
Print the changes on the given repo Defaults to the current directory
144 145 146 147 148 |
# File 'lib/firespring_dev_commands/git.rb', line 144 def changes(dir: default_project_dir) return unless File.exist?(dir) Dir.chdir(dir) { `git status --porcelain | grep -v '^?'` }.split("\n").map(&:strip) end |
#changes_slow(dir: default_project_dir) ⇒ Object
Print the changes on the given repo using the ruby built-in method… which seems REALLY slow compared to the porcelain version Defaults to the current directory
152 153 154 155 156 157 158 159 |
# File 'lib/firespring_dev_commands/git.rb', line 152 def changes_slow(dir: default_project_dir) return unless File.exist?(dir) s = ::Git.open(dir).status s.added.keys.map { |it| " A #{it}" } + s.changed.keys.map { |it| " M #{it}" } + s.deleted.keys.map { |it| " D #{it}" } end |
#check_version ⇒ Object
Checks the min and max version against the current git version if they have been configured
58 59 60 61 62 63 64 |
# File 'lib/firespring_dev_commands/git.rb', line 58 def check_version min_version = self.class.config.min_version raise "requires git version >= #{min_version} (found #{self.class.version})" if min_version && !Dev::Common.new.version_greater_than(min_version, self.class.version) max_version = self.class.config.max_version raise "requires git version < #{max_version} (found #{self.class.version})" if max_version && Dev::Common.new.version_greater_than(max_version, self.class.version) end |
#checkout(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Checks out the given branch in the given repo Defaults to the current directory optionally raise errors
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/firespring_dev_commands/git.rb', line 207 def checkout(branch, dir: default_project_dir, raise_errors: false) raise 'branch is required' if branch.to_s.strip.empty? return unless File.exist?(dir) # Make sure the original branch hash has been created before we change anything original_branches g = ::Git.open(dir) g.fetch('origin', prune: true) # If the branch we are checking out doesn't exist, check out either the staging branch or the main branch actual_branch = branch unless branch_exists?(dir, branch) actual_branch = [staging_branch, main_branch].uniq.find { |it| branch_exists?(dir, it) } puts "Branch #{branch} not found, checking out #{actual_branch} instead".light_yellow end indent g.checkout(actual_branch) indent g.pull('origin', actual_branch) true rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#checkout_all(branch) ⇒ Object
Checks out the given branch in all repositories with some additional formatting
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/firespring_dev_commands/git.rb', line 187 def checkout_all(branch) @success = true puts puts "Checking out #{branch} in each repo".light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) puts Dev::Common.new.center_pad(repo_basename).light_green @success &= checkout(branch, dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts raise "Failed checking out branch #{branch} one or more repositories" unless @success end |
#clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil, depth: nil) ⇒ Object
Clones the repo_name into the dir Optionally specify a repo_org Optionally specify a branch to check out (defaults to the repository default branch)
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/firespring_dev_commands/git.rb', line 411 def clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil, depth: nil) if Dir.exist?("#{dir}/.git") puts "#{dir} already cloned".light_green return end FileUtils.mkdir_p(dir.to_s) puts "Cloning #{dir} from #{ssh_repo_url(repo_name, repo_org)}".light_yellow opts = {} opts[:branch] = branch unless branch.to_s.strip.empty? opts[:depth] = depth unless depth.to_s.strip.empty? g = ::Git.clone(ssh_repo_url(repo_name, repo_org), dir, opts) g.fetch('origin', prune: true) end |
#clone_repos ⇒ Object
Clones all repositories
404 405 406 |
# File 'lib/firespring_dev_commands/git.rb', line 404 def clone_repos info.each { |it| clone_repo(dir: it.path, repo_name: it.name) } end |
#create_branch(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Create the given branch in the given repo Defaults to the current directory optionally raise errors
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/firespring_dev_commands/git.rb', line 237 def create_branch(branch, dir: default_project_dir, raise_errors: false) raise 'branch is required' if branch.to_s.strip.empty? raise "refusing to create protected branch '#{branch}'" if %w(master develop).any?(branch.to_s.strip) return unless File.exist?(dir) # Make sure the original branch hash has been created before we change anything original_branches g = ::Git.open(dir) g.fetch('origin', prune: true) puts "Fetching the latest changes for base branch \"#{staging_branch}\"" g.checkout(staging_branch) g.pull('origin', staging_branch) puts "Creating branch #{branch}, pushing to origin, and updating remote tracking" g.branch(branch).checkout g.push('origin', branch) g.config("branch.#{branch}.remote", 'origin') g.config("branch.#{branch}.merge", "refs/heads/#{branch}") puts rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#current_branches ⇒ Object
Returns a hash of each project repo and the branch that is currently checked out
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/firespring_dev_commands/git.rb', line 82 def current_branches {}.tap do |hsh| project_dirs.each do |project_dir| next unless File.exist?(project_dir) Dir.chdir(project_dir) do hsh[project_dir] = branch_name(dir: project_dir) end end end end |
#default_project_dir ⇒ Object
Returns the first configured project dire
72 73 74 |
# File 'lib/firespring_dev_commands/git.rb', line 72 def default_project_dir project_dirs.first end |
#indent(string, padding: ' ') ⇒ Object
Split on newlines and add additional padding
434 435 436 |
# File 'lib/firespring_dev_commands/git.rb', line 434 def indent(string, padding: ' ') string.to_s.split("\n").each { |line| puts "#{padding}#{line}" } end |
#merge(branch, dir: default_project_dir, raise_errors: false) ⇒ Object
Merge the given branch into the given repo Defaults to the current directory optionally raise errors
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/firespring_dev_commands/git.rb', line 302 def merge(branch, dir: default_project_dir, raise_errors: false) raise 'branch is required' if branch.to_s.strip.empty? return unless File.exist?(dir) # Make sure the original branch hash has been created before we change anything original_branches g = ::Git.open(dir) g.fetch('origin', prune: true) raise 'branch does not exist' unless branch_exists?(dir, branch) # No need to merge into ourself current_branch = branch_name(dir:) return true if current_branch == branch indent "Merging #{branch} into #{current_branch}" indent g.merge(branch) true rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#merge_all(branch) ⇒ Object
Merge the branch into all repositories
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/firespring_dev_commands/git.rb', line 280 def merge_all(branch) @success = true puts puts "Merging #{branch} into each repo".light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) puts Dev::Common.new.center_pad(repo_basename).light_green @success &= merge(branch, dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts raise "Failed merging branch #{branch} in one or more repositories" unless @success push_all end |
#project_dirs ⇒ Object
Returns all git paths configured in our info
67 68 69 |
# File 'lib/firespring_dev_commands/git.rb', line 67 def project_dirs @project_dirs ||= @info.map(&:path).sort end |
#pull(dir: default_project_dir, raise_errors: false) ⇒ Object
Pull the given repo Defaults to the current directory optionally raise errors
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/firespring_dev_commands/git.rb', line 348 def pull(dir: default_project_dir, raise_errors: false) return unless File.exist?(dir) g = ::Git.open(dir) g.fetch('origin', prune: true) branch = branch_name(dir:) indent "Pulling branch #{branch} from origin" indent g.pull('origin', branch) true rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#pull_all ⇒ Object
Pull the latest in all repositories
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/firespring_dev_commands/git.rb', line 328 def pull_all @success = true puts puts 'Pulling current branch into each repo'.light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) puts Dev::Common.new.center_pad(repo_basename).light_green @success &= pull(dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts raise 'Failed pulling branch in one or more repositories' unless @success end |
#push(dir: default_project_dir, raise_errors: false) ⇒ Object
Push the given repo Defaults to the current directory optionally raise errors
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/firespring_dev_commands/git.rb', line 386 def push(dir: default_project_dir, raise_errors: false) return unless File.exist?(dir) g = ::Git.open(dir) g.fetch('origin', prune: true) branch = branch_name(dir:) indent "Pushing branch #{branch} to origin" indent g.push('origin', branch) true rescue ::Git::GitExecuteError => e raise e if raise_errors print_errors(e.) false end |
#push_all ⇒ Object
Push to remote in all repositories
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'lib/firespring_dev_commands/git.rb', line 366 def push_all @success = true puts puts 'Pushing current branch into each repo'.light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) puts Dev::Common.new.center_pad(repo_basename).light_green @success &= push(dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts raise 'Failed pushing branch in one or more repositories' unless @success end |
#repos_with_changes ⇒ Object
Returns the name of any repositories which have changes
138 139 140 |
# File 'lib/firespring_dev_commands/git.rb', line 138 def repos_with_changes info.filter_map { |it| it.name unless changes(dir: it.path).empty? } end |
#reset(dir: default_project_dir) ⇒ Object
Runs a git reset on the given repo Defaults to the current directory
179 180 181 182 183 184 |
# File 'lib/firespring_dev_commands/git.rb', line 179 def reset(dir: default_project_dir) return unless File.exist?(dir) g = ::Git.open(dir) indent g.reset_hard end |
#reset_all ⇒ Object
Runs a git reset on all given repositories with some additional formatting
162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/firespring_dev_commands/git.rb', line 162 def reset_all puts puts 'Resetting each repo'.light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) header = "#{repo_basename} (#{original_branches[project_dir]})" puts Dev::Common.new.center_pad(header).light_green reset(dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts end |
#ssh_repo_url(name, org) ⇒ Object
Builds an ssh repo URL using the org and repo name given
429 430 431 |
# File 'lib/firespring_dev_commands/git.rb', line 429 def ssh_repo_url(name, org) "[email protected]:#{org}/#{name}.git" end |
#status(dir: default_project_dir) ⇒ Object
Prints the results of the status command Currently running “git status” instead of using the library because it doesn’t do well formatting the output
129 130 131 132 133 134 135 |
# File 'lib/firespring_dev_commands/git.rb', line 129 def status(dir: default_project_dir) return unless File.exist?(dir) # NOTE: git library doesn't have a good "status" analog. So just run the standard "git" one # splitting and puts'ing to prefix each line with spaces... Dir.chdir(dir) { indent `git status` } end |
#status_all ⇒ Object
Prints the status of multiple repository directories and displays the results in a nice format
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/firespring_dev_commands/git.rb', line 109 def status_all @success = true puts puts 'Getting status in each repo'.light_yellow if project_dirs.length > 1 project_dirs.each do |project_dir| next unless File.exist?(project_dir) repo_basename = File.basename(File.realpath(project_dir)) header = "#{repo_basename} (#{original_branches[project_dir]})" puts Dev::Common.new.center_pad(header).light_green @success &= status(dir: project_dir) puts Dev::Common.new.center_pad.light_green end puts raise 'Failed getting status on one or more repositories' unless @success end |