/
git.rb
150 lines (133 loc) · 4.63 KB
/
git.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
module Git
def self.has_uncommitted_changes()
clean = system("git diff --quiet 2>/dev/null >&2")
return !clean
end
def self.development_branch
dev_branch = `git config feature.development-branch`.strip
if !dev_branch || $? != 0
$stderr.puts "No development branch specified"
$stderr.puts " set it with: git config feature.development-branch master"
exit 1;
end
dev_branch
end
# Returns an array of branches that aren't merged into the specifeid branch
def self.branches_not_merged_into(branch)
self::all_branches - self::merged_branches(branch)
end
# Returns an array of unmerged hotfix branches
def self.hotfix_branches(type)
branches = if type == :unmerged
self.branches_not_merged_into('stable')
elsif type == :merged
self.merged_branches('stable')
end
branches.select {|branch| branch.include?('hotfix-') }
end
# Returns an array of unmerged feature branches
def self.feature_branches(type)
branches = if type == :unmerged
self.branches_not_merged_into('master')
elsif type == :merged
self.merged_branches('master')
end
branches.reject {|branch| branch.include?('hotfix-') }
end
# Returns an array of all branch names that have have been merged into the
# specified branch
def self.merged_branches(into_branch='master')
`git branch --merged #{into_branch} -a`.
split("\n").
map {|branch| branch.gsub('*','').strip.sub('remotes/','')}
end
# Returns an array of all local branch names
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
end
# returns the name of th currently checked out brnach, or nil if detached.
def self.current_branch()
ref = `git symbolic-ref -q HEAD`.strip
ref.split('/').last
end
# returns the SHA1 hash that the specified branch or symbol points to
def self.branch_hash(branch)
`git rev-parse --verify --quiet "#{branch}" 2>/dev/null`.strip
end
# Return formatted string containing:
# commit_hash Authoe Name (relative date)
# for the specifeid branch or commit
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}" #{branch}`.strip
simple_branch = branch.sub('origin/', '')
sprintf "%-30s %s", simple_branch, branch_info
end
def self.run_safe(command)
puts "> #{command}"
result = system(command)
raise "Git command failed, aborting." if (!result)
end
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
def self.show_branch_list(options = {})
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
options.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
def self.stashes
# 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
##
# Returns the commit message from the given commit hash or branch name
#
def self.commit_message(ref)
`git log -1 --format="%B" #{ref}`.strip
end
end