-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathgit_log_commit.rb
122 lines (106 loc) · 3.38 KB
/
git_log_commit.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
module Vector
class GitLogCommit
class << self
def fetch_since!(last_version)
range = "v#{last_version}..."
commit_log = `git log #{range} --cherry-pick --right-only --no-merges --pretty=format:'%H\t%s\t%aN\t%ad'`.chomp
commit_lines = commit_log.split("\n").reverse
commit_lines.collect do |commit_line|
hash = parse_commit_line!(commit_line)
new(hash)
end
end
def from_file!(path)
contents = File.read(path)
contents.split("\n").collect do |line|
hash = parse_commit_line!(line)
new(hash)
end
end
private
# This is used for the `files_count`, `insertions_count`, and `deletions_count`
# attributes. It helps to communicate stats and the depth of changes in our
# release notes.
def get_commit_stats(sha)
`git show --shortstat --oneline #{sha}`.split("\n").last
end
def parse_commit_line!(commit_line)
# Parse the full commit line
line_parts = commit_line.split("\t")
sha = line_parts.fetch(0)
message = line_parts.fetch(1)
author = line_parts.fetch(2)
date = Time.parse(line_parts.fetch(3)).utc
attributes =
{
"sha" => sha,
"author" => author,
"date" => date,
"message" => message
}
# Parse the stats
stats = get_commit_stats(attributes.fetch("sha"))
if /^\W*\p{Digit}+ files? changed,/.match(stats)
stats_attributes = parse_commit_stats!(stats)
attributes.merge!(stats_attributes)
end
attributes
end
# Parses the data from `#get_commit_stats`.
def parse_commit_stats!(stats)
attributes = {}
stats.split(", ").each do |stats_part|
stats_part.strip!
key =
case stats_part
when /insertions?/
"insertions_count"
when /deletions?/
"deletions_count"
when /files? changed/
"files_count"
else
raise "Invalid commit stat: #{stats_part}"
end
count = stats_part.match(/^(?<count>[0-9]*) /)[:count].to_i
attributes[key] = count
end
attributes["insertions_count"] ||= 0
attributes["deletions_count"] ||= 0
attributes["files_count"] ||= 0
attributes
end
end
attr_reader :author,
:date,
:deletions_count,
:files_count,
:insertions_count,
:message,
:raw,
:sha
def initialize(hash)
@author = hash.fetch("author")
@date = hash.fetch("date")
@deletions_count = hash.fetch("deletions_count", 0)
@files_count = hash.fetch("files_count", 0)
@insertions_count = hash.fetch("insertions_count", 0)
@message = hash.fetch("message")
@sha = hash.fetch("sha")
end
def to_h
{
"author" => author,
"date" => date,
"deletions_count" => deletions_count,
"files_count" => files_count,
"insertions_count" => insertions_count,
"message" => message,
"sha" => sha
}
end
def to_raw
"#{sha}\t#{message}\t#{author}\t#{date.strftime("%a %b %d %H:%M:%S %Y %z")}"
end
end
end