-
Notifications
You must be signed in to change notification settings - Fork 3
/
git-shame
executable file
·109 lines (92 loc) · 3 KB
/
git-shame
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
#!/usr/bin/env ruby
require "optparse"
color_value = nil
def get_setting(name)
IO.popen("git config --get " + name) { |pipe|
return pipe.read.strip
}
end
['color.shame', 'color.ui'].each { |name|
setting = get_setting name
puts name, setting
case setting
when 'always'
color_value = true
when 'false', 'never'
color_value = false
when 'auto', 'true'
color_value = STDOUT.tty?
when ''
next
else
puts 'Unknown color setting "' + setting + '" for "' + name + '"; falling back to "auto"'
color_value = STDOUT.tty?
end
break
}
options = {
color: color_value,
remote: "origin",
show_commands: false,
show_merged: true,
show_report: true,
show_unmerged: true,
users: nil,
}
OptionParser.new do |opts|
opts.banner = "Usage: #{$0} --[no-]color --remote [REMOTE] --[no-]show-merged --[no-]show-unmerged"
opts.on("--[no-]color") { |o| options[:color] = o }
opts.on("--remote [REMOTE]") { |o| options[:remote] = o }
opts.on("--[no-]show-commands") { |o| options[:show_commands] = o }
opts.on("--[no-]show-merged") { |o| options[:show_merged] = o }
opts.on("--[no-]show-report") { |o| options[:show_report] = o }
opts.on("--[no-]show-unmerged") { |o| options[:show_unmerged] = o }
opts.on("--users x,y,z", Array) { |o| options[:users] = o }
end.parse!
remote_match = %r{^\s+#{Regexp::quote(options[:remote])}/\S+$}
begin
require "colored" if options[:color]
rescue LoadError
options[:color] = false
end
unless options[:color]
class String
%w(blue green magenta red yellow).each do |color|
define_method(color.to_sym) { self }
end
end
end
branches = {}
$merged_branches = {}
IO.popen("git branch -r --no-color --merged", "r").grep(remote_match).map { |b| b.sub(%r{\s+}, %q{}).chomp }.each do |branch|
$merged_branches[branch] = true
end
def is_merged? (branch)
$merged_branches.has_key?(branch) && $merged_branches[branch];
end
IO.popen("git branch -r --no-color", "r").grep(remote_match).map { |b| b.chomp.sub(/^\s+/, %q{}) }.each do |branch|
committer, rel_commit_date, timestamp = `git log -1 --format='%ce%n%cr%n%ct' #{branch}`.chomp.split(/\n/)
next if options[:users] && ! options[:users].include?(committer)
is_merged = is_merged?(branch)
if (is_merged && options[:show_merged]) || (! is_merged && options[:show_unmerged])
branches[committer] ||= []
branches[committer] << [ branch, rel_commit_date, timestamp, is_merged?(branch) ]
end
end
if options[:show_report]
branches.keys.sort { |a,b| branches[b].length <=> branches[a].length }.each do |k|
v = branches[k]
print "#{k}:\n".yellow
v.sort { |a,b| a[2] <=> b[2] }.map { |b|
b[0].green + " (last commit " + b[1] + ", " + (b[3] ? "merged".magenta : "NOT MERGED".red) + ')'
}.each { |branch| print "\t#{branch}\n" }
print "\n"
end
end
if options[:show_commands]
branches.each_value do |v|
v.map { |b| b[0].sub(%r{^#{Regexp::quote(options[:remote])}/}, %q{}) }.each do |branch|
print "git push #{options[:remote]} :#{branch}\n"
end
end
end