Module: Git
- Defined in:
- lib/git.rb
Class Method Summary collapse
-
.all_branches ⇒ Object
Returns an array of all local branch names.
-
.branch_hash(branch) ⇒ Object
Returns the SHA1 hash that the specified branch or symbol points to.
-
.branch_info(branch) ⇒ Object
Returns formatted string containing:.
-
.branches_not_merged_into(branch) ⇒ Object
Returns an array of branches that aren’t merged into the specified branch.
-
.commit_message(ref) ⇒ Object
Returns the commit message from the given commit hash or branch name.
-
.current_branch ⇒ Object
Returns the name of the currently checked out branch, or nil if detached.
-
.delete_current_branch ⇒ Object
Deletes the current branch.
-
.editor ⇒ Object
Returns the editor specified in the user’s gitconfig.
-
.feature_branches(type) ⇒ Object
Returns an array of unmerged feature branches.
-
.get_branch(branch = '') ⇒ Object
Return the specified branch in the feature git config section.
-
.get_description_from_user(initial_message = '') ⇒ Object
Starts an editor with a file.
- .git_dir ⇒ Object
- .has_uncommitted_changes ⇒ Object
- .in_a_repo ⇒ Object
-
.merged_branches(into_branch = 'master') ⇒ Object
Returns an array of all branch names that have have been merged into the specified branch.
- .run_safe(commands) ⇒ Object
- .show_branch_list(options = {}) ⇒ Object
- .show_stashes_saved_on(branch = nil) ⇒ Object
- .stashes ⇒ Object
-
.submodules_update(mode = "") ⇒ Object
Update / initialize submodules from the TLD or return the command that would do so as a string.
-
.switch_branch(branch) ⇒ Object
Switch to the specified branch.
Class Method Details
.all_branches ⇒ Object
Returns an array of all local branch names
86 87 88 89 90 91 92 |
# File 'lib/git.rb', line 86 def self.all_branches() `git for-each-ref --sort=-committerdate --format='%(refname)' refs/heads refs/remotes`. split("\n"). map {|branch| branch.sub(/refs\/\w+\//, '') }. uniq. reject {|branch| branch =~ %r{\w+/HEAD} } end |
.branch_hash(branch) ⇒ Object
Returns the SHA1 hash that the specified branch or symbol points to
115 116 117 |
# File 'lib/git.rb', line 115 def self.branch_hash(branch) `git rev-parse --verify --quiet #{branch.shellescape} 2>/dev/null`.strip end |
.branch_info(branch) ⇒ Object
Returns formatted string containing:
commit_hash Author Name (relative date)
for the specified branch or commit
124 125 126 127 128 129 130 |
# File 'lib/git.rb', line 124 def self.branch_info(branch) # branch info format: hash author (relative date) format = "%h %an %Cgreen(%ar)%Creset" branch_info = `git show -s --pretty=#{format.shellescape} #{branch.shellescape}`.strip simple_branch = branch.sub('origin/', '') sprintf "%-30s %s", simple_branch, branch_info end |
.branches_not_merged_into(branch) ⇒ Object
Returns an array of branches that aren’t merged into the specified branch
58 59 60 |
# File 'lib/git.rb', line 58 def self.branches_not_merged_into(branch) self::all_branches - self::merged_branches(branch) end |
.commit_message(ref) ⇒ Object
Returns the commit message from the given commit hash or branch name
244 245 246 |
# File 'lib/git.rb', line 244 def self.(ref) `git log -1 --format="%B" #{ref.shellescape}`.strip end |
.current_branch ⇒ Object
Returns the name of the currently checked out branch, or nil if detached.
95 96 97 |
# File 'lib/git.rb', line 95 def self.current_branch() `git symbolic-ref -q --short HEAD`.strip end |
.delete_current_branch ⇒ Object
Deletes the current branch. For cleaning up after errors.
100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/git.rb', line 100 def self.delete_current_branch() devBranch = get_branch('development') branch = Git::current_branch if branch == devBranch puts "Cannot remove development branch" exit 1 end Git::switch_branch(devBranch) `git branch -d #{branch.shellescape}`.strip end |
.editor ⇒ Object
Returns the editor specified in the user’s gitconfig.
22 23 24 25 26 27 28 29 |
# File 'lib/git.rb', line 22 def self.editor editor = `git var GIT_EDITOR`.strip unless editor abort "Configure an editor for git:\n" + "git config --global core.editor vim" end return editor end |
.feature_branches(type) ⇒ Object
Returns an array of unmerged feature branches
63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/git.rb', line 63 def self.feature_branches(type) devBranch = get_branch('development') branches = if type == :unmerged self.branches_not_merged_into(devBranch) elsif type == :merged self.merged_branches(devBranch) else raise ArgumentError, 'Must specify :merged or :unmerged in feature_branches.' end branches end |
.get_branch(branch = '') ⇒ Object
Return the specified branch in the feature git config section.
12 13 14 15 16 17 18 19 |
# File 'lib/git.rb', line 12 def self.get_branch(branch = '') specified_branch = `git config feature.#{branch.shellescape}-branch`.strip if specified_branch.empty? || $? != 0 die("No #{branch} branch specified; set it with:\n" + "git config feature.#{branch}-branch \"name-of-branch\"") end return specified_branch end |
.get_description_from_user(initial_message = '') ⇒ Object
Starts an editor with a file. Returns a string with the contents of that file.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/git.rb', line 33 def self.get_description_from_user( = '') require 'tempfile' editor = self::editor file = Tempfile.new('merge-msg') file.print() file.flush if editor == 'vim' params = "'+set ft=gitcommit' '+set textwidth=72'" + " '+setlocal spell spelllang=en_us'" else params = '' end pid = spawn("#{editor} #{params} #{file.path}") Process.wait pid file.rewind commit = file.read file.unlink return commit end |
.git_dir ⇒ Object
248 249 250 |
# File 'lib/git.rb', line 248 def self.git_dir() `git rev-parse --git-dir`.strip end |
.has_uncommitted_changes ⇒ Object
2 3 4 5 |
# File 'lib/git.rb', line 2 def self.has_uncommitted_changes() clean = system("git diff --quiet 2>/dev/null >&2") return !clean end |
.in_a_repo ⇒ Object
7 8 9 |
# File 'lib/git.rb', line 7 def self.in_a_repo return system("git rev-parse") end |
.merged_branches(into_branch = 'master') ⇒ Object
Returns an array of all branch names that have have been merged into the specified branch
79 80 81 82 83 |
# File 'lib/git.rb', line 79 def self.merged_branches(into_branch='master') `git branch --merged #{into_branch.shellescape} -a`. split("\n"). map {|branch| branch.gsub('*','').strip.sub('remotes/','')} end |
.run_safe(commands) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/git.rb', line 132 def self.run_safe(commands) while command = commands.shift safe_command = command.gsub(/[^[:print:]]+/,' ') puts "> " + safe_command unless system(command) puts highlight("\nERROR: failed on #{safe_command}.") puts "\nWould have run:" commands.each do |command| puts "# " + command.gsub(/[^[:print:]]+/,' ') end abort end end end |
.show_branch_list(options = {}) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/git.rb', line 160 def self.show_branch_list( = {}) puts "\nCurrent Branch:" puts "--" * 30 current = Git::current_branch print HIGHLIGHT if current print Git::branch_info(current) else print "(not on any branch!)" end puts HIGHLIGHT_OFF .each do |branch_type, branches| puts "\nAvailable #{branch_type} branches:" puts "--" * 30 if branches && !branches.empty? shown_branches = {} branches.each do |branch| simple_branch = branch.sub('origin/', '') next if shown_branches.has_key?(simple_branch) puts Git::branch_info(branch) shown_branches[simple_branch] = true end else puts "(none)" end end end |
.show_stashes_saved_on(branch = nil) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/git.rb', line 147 def self.show_stashes_saved_on(branch = nil) self.stashes.each do |stash| if !branch || stash[:branch] == branch puts "=" * 40 puts highlight( "There is a stash saved from #{branch} #{stash[:date]}") puts wrap_text(stash[:subject]) puts "see it with >\n git stash show -p " + stash[:ref] puts "apply it with >\n git stash apply " + stash[:ref] end end end |
.stashes ⇒ Object
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/git.rb', line 189 def self.stashes # Do we even have a stash? unless File.exist? '.git/refs/stash' return [] end # format = "relative date|stash ref|commit message" `git log --format="%ar|%gd|%s" -g "refs/stash"`.lines.map do |line| fields = line.split '|', 3 # All stashes have commit messages like "WIP on branch_name: ..." branch = line[/\S+:/] { :date => fields[0], :ref => fields[1], :branch => branch && branch.chop, :subject =>fields[2] } end end |
.submodules_update(mode = "") ⇒ Object
Update / initialize submodules from the TLD or return the command that would do so as a string.
229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/git.rb', line 229 def self.submodules_update(mode = "") # capture only the path, not the newline basedir = `git rev-parse --show-toplevel`.split("\n").first command = "cd #{basedir.shellescape} && git submodule --quiet update --init --recursive" if mode == "get" return command else Git::run_safe([command]) end end |
.switch_branch(branch) ⇒ Object
Switch to the specified branch. Because we use submodules, we have to check for updates to those submodules when we checkout a branch.
args: –clean - remove every unstaged file, including non-existant submodules
217 218 219 220 221 222 223 |
# File 'lib/git.rb', line 217 def self.switch_branch(branch) self.run_safe(["git checkout \"#{branch}\""]) self.submodules_update self.run_safe(["git clean -ffd"]) if ARGV.include?('--clean') self.show_stashes_saved_on(branch) end |