ptlog 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/ptlog.rb +25 -2
- data/lib/ptlog/change_log.rb +9 -112
- data/lib/ptlog/git/lib.rb +10 -0
- data/lib/ptlog/git/tags_list.rb +29 -0
- data/lib/ptlog/pivotal/story.rb +3 -0
- data/lib/ptlog/version.rb +1 -1
- data/lib/ptlog/wrappers/changelog.rb +21 -0
- data/lib/ptlog/wrappers/release.rb +35 -0
- data/templates/changelog.erb +142 -0
- metadata +7 -3
data/lib/ptlog.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require "ptlog/version"
|
2
|
+
require "git"
|
3
|
+
|
2
4
|
|
3
5
|
module PTLog
|
4
6
|
class GeneralError < StandardError; end
|
@@ -10,6 +12,27 @@ module PTLog
|
|
10
12
|
autoload :API, "ptlog/pivotal/api"
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
module Git
|
16
|
+
autoload :Lib, "ptlog/git/lib"
|
17
|
+
end
|
18
|
+
|
19
|
+
module Wrappers
|
20
|
+
autoload :ChangeLog, "ptlog/wrappers/changelog"
|
21
|
+
autoload :Release, "ptlog/wrappers/release"
|
22
|
+
end
|
23
|
+
|
24
|
+
autoload :Release, "ptlog/release"
|
25
|
+
autoload :ChangeLog, "ptlog/change_log"
|
26
|
+
autoload :TagList, "ptlog/git/tags_list"
|
27
|
+
|
28
|
+
def self.root
|
29
|
+
File.expand_path '../..', __FILE__
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.templates
|
33
|
+
File.join root, 'templates'
|
34
|
+
end
|
15
35
|
end
|
36
|
+
|
37
|
+
Git::Lib.send :include, PTLog::Git::Lib
|
38
|
+
|
data/lib/ptlog/change_log.rb
CHANGED
@@ -1,125 +1,22 @@
|
|
1
|
-
require '
|
2
|
-
require 'nokogiri'
|
3
|
-
|
4
|
-
module Git
|
5
|
-
class Lib
|
6
|
-
def ordered_tags
|
7
|
-
command_lines("for-each-ref --sort='*authordate' --format='%(tag)' refs/tags")
|
8
|
-
end
|
9
|
-
def first_commit
|
10
|
-
command("rev-list --max-parents=0 HEAD")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
|
1
|
+
require 'erb'
|
16
2
|
|
17
3
|
module PTLog
|
18
|
-
class
|
19
|
-
|
20
|
-
|
21
|
-
def initialize(git, since)
|
22
|
-
@list = git.lib.ordered_tags
|
23
|
-
@since = since
|
24
|
-
@first_commit = git.lib.first_commit
|
25
|
-
end
|
26
|
-
|
27
|
-
def each(options = {})
|
28
|
-
list_after_item = @list[@list.index(@since), @list.size]
|
29
|
-
|
30
|
-
if block_given?
|
31
|
-
list_after_item.reverse.each { |e| yield(e) }
|
32
|
-
else
|
33
|
-
Enumerator.new(list_after_item.reverse, :each)
|
34
|
-
end
|
4
|
+
class Controller
|
5
|
+
def initialize
|
6
|
+
@changelog = PTLog::Wrappers::ChangeLog.new
|
35
7
|
end
|
36
|
-
|
37
|
-
|
38
|
-
@list[@list.index(name) + 1] || 'HEAD'
|
39
|
-
end
|
40
|
-
|
41
|
-
def prev_to(name)
|
42
|
-
0 < @list.index(name) && @list[@list.index(name) - 1] or @first_commit
|
8
|
+
def get_binding
|
9
|
+
binding
|
43
10
|
end
|
44
11
|
end
|
45
12
|
|
46
13
|
class ChangeLog
|
47
|
-
attr_reader :git, :tags
|
48
|
-
|
49
|
-
def initialize
|
50
|
-
@git ||= Git.open(Dir.getwd)
|
51
|
-
@start = ENV['PTLOG_SINCE'] || git.lib.ordered_tags[-1]
|
52
|
-
@tags = PTLog::TagList.new(@git, @start)
|
53
|
-
end
|
54
|
-
|
55
|
-
def log(from, to)
|
56
|
-
git.log.between(from, to)
|
57
|
-
end
|
58
|
-
|
59
|
-
def stories(from, to)
|
60
|
-
output = {}
|
61
|
-
log(from, to).each do |commit|
|
62
|
-
commit.message.scan(/\#(\d+)/).flatten.each do |num|
|
63
|
-
output[num] ||= []
|
64
|
-
output[num] << commit.message
|
65
|
-
end
|
66
|
-
end
|
67
|
-
output
|
68
|
-
end
|
69
|
-
|
70
14
|
def self.generate
|
71
15
|
raise GeneralError, "You have to specify Pivotal token with export PIVOTAL_TOKEN=xyz" unless ENV.has_key?('PIVOTAL_TOKEN')
|
72
16
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
doc.body do
|
77
|
-
doc.h1 "Change Log @ #{Time.new.utc.strftime('%I:%M%P %D UTC')}"
|
78
|
-
changelog.tags.each do |tag|
|
79
|
-
|
80
|
-
doc.h2 do
|
81
|
-
doc.text "Release #{tag} "
|
82
|
-
doc.span(class: 'date') do
|
83
|
-
doc.text changelog.git.gcommit(tag).date.utc.strftime('(%I:%M%P %D UTC)')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
changelog.stories(changelog.tags.prev_to(tag), tag).each do |num, messages|
|
88
|
-
doc.div(class: 'story') do
|
89
|
-
story = Pivotal::Story.get(num)
|
90
|
-
doc.h3 do
|
91
|
-
if story.valid?
|
92
|
-
doc.a(href: story.url) do
|
93
|
-
doc.span(class: 'num') do
|
94
|
-
doc.text num
|
95
|
-
end
|
96
|
-
end
|
97
|
-
doc.span(class: 'name') do
|
98
|
-
doc.text " "
|
99
|
-
doc.text story.name
|
100
|
-
end
|
101
|
-
else
|
102
|
-
doc.span(class: 'num') do
|
103
|
-
doc.text num
|
104
|
-
end
|
105
|
-
doc.span(class: 'name error') do
|
106
|
-
doc.text " "
|
107
|
-
doc.text story.error
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
doc.ul(class: 'commits') do
|
112
|
-
messages.each do |message|
|
113
|
-
doc.li message
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
@builder.to_html
|
17
|
+
controller = PTLog::Controller.new
|
18
|
+
template = ERB.new IO.read(File.join(PTLog.templates, 'changelog.erb'))
|
19
|
+
template.result(controller.get_binding)
|
123
20
|
end
|
124
21
|
end
|
125
22
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PTLog
|
2
|
+
class TagList
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(git, since)
|
6
|
+
@list = git.lib.ordered_tags + ['HEAD']
|
7
|
+
@since = since
|
8
|
+
@first_commit = git.lib.first_commit
|
9
|
+
end
|
10
|
+
|
11
|
+
def each(options = {})
|
12
|
+
list_after_item = @list[@list.index(@since), @list.size]
|
13
|
+
|
14
|
+
if block_given?
|
15
|
+
list_after_item.reverse.each { |e| yield(e) }
|
16
|
+
else
|
17
|
+
Enumerator.new(list_after_item.reverse, :each)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def next_to(name)
|
22
|
+
@list[@list.index(name) + 1] || 'HEAD'
|
23
|
+
end
|
24
|
+
|
25
|
+
def prev_to(name)
|
26
|
+
0 < @list.index(name) && @list[@list.index(name) - 1] or @first_commit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/ptlog/pivotal/story.rb
CHANGED
@@ -3,7 +3,10 @@ require 'faraday'
|
|
3
3
|
module PTLog
|
4
4
|
module Pivotal
|
5
5
|
class Story
|
6
|
+
attr_reader :num
|
7
|
+
|
6
8
|
def initialize(story_id)
|
9
|
+
@num = story_id
|
7
10
|
@story = Pivotal::API.story(story_id)
|
8
11
|
@labels = @story['labels'].map { |label| label['name'] } if @story['labels'].is_a?(Array)
|
9
12
|
end
|
data/lib/ptlog/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
module PTLog::Wrappers
|
2
|
+
class ChangeLog
|
3
|
+
attr_reader :git, :tags
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@git ||= ::Git.open(Dir.getwd)
|
7
|
+
@start = ENV['PTLOG_SINCE'] || git.lib.ordered_tags.first
|
8
|
+
@tags = PTLog::TagList.new(@git, @start)
|
9
|
+
end
|
10
|
+
|
11
|
+
def date
|
12
|
+
Time.new.utc.strftime('%I:%M%P %D UTC')
|
13
|
+
end
|
14
|
+
|
15
|
+
def releases
|
16
|
+
@tags.map do |tag|
|
17
|
+
PTLog::Wrappers::Release.new(tag, self)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PTLog::Wrappers
|
2
|
+
class Release
|
3
|
+
def initialize(tag, changelog)
|
4
|
+
@tag = tag
|
5
|
+
@initial_commit = changelog.tags.prev_to(tag)
|
6
|
+
@git = changelog.git
|
7
|
+
@commit = @git.gcommit(tag)
|
8
|
+
end
|
9
|
+
|
10
|
+
def title
|
11
|
+
@tag
|
12
|
+
end
|
13
|
+
|
14
|
+
def date
|
15
|
+
@commit.date.utc.strftime('%I:%M%P %D UTC')
|
16
|
+
end
|
17
|
+
|
18
|
+
def stories
|
19
|
+
ids = @git.log.between(@initial_commit, @tag).map do |commit|
|
20
|
+
commit.message.scan(/\#(\d+)/)
|
21
|
+
end
|
22
|
+
ids.flatten.uniq.map{ |num| PTLog::Pivotal::Story.get(num) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def commits(num)
|
26
|
+
@git.log.between(@initial_commit, @tag).select do |commit|
|
27
|
+
commit.message =~ (/\##{num}/)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_binding
|
32
|
+
binding
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>ChangeLog</title>
|
5
|
+
<link href='http://fonts.googleapis.com/css?family=Abel' rel='stylesheet' type='text/css'>
|
6
|
+
|
7
|
+
<style type="text/css">
|
8
|
+
|
9
|
+
@font-face {
|
10
|
+
font-family: sans-serif;
|
11
|
+
font-weight: normal;
|
12
|
+
font-style: normal;
|
13
|
+
}
|
14
|
+
|
15
|
+
@font-face {
|
16
|
+
font-family: sans-serif;
|
17
|
+
font-weight: normal;
|
18
|
+
font-style: normal;
|
19
|
+
}
|
20
|
+
|
21
|
+
body {
|
22
|
+
background-color: #f4f3f0;
|
23
|
+
min-width: 450px;
|
24
|
+
padding: 0;
|
25
|
+
margin: 0;
|
26
|
+
color: #292C2F;
|
27
|
+
font-family: DINPro-Regular, Arial;
|
28
|
+
font-size: 13px;
|
29
|
+
}
|
30
|
+
|
31
|
+
.content {
|
32
|
+
width: 800px;
|
33
|
+
margin: 22px auto;
|
34
|
+
}
|
35
|
+
|
36
|
+
.content-inner {
|
37
|
+
-webkit-border-radius: 5px;
|
38
|
+
-moz-border-radius: 5px;
|
39
|
+
border-radius: 5px;
|
40
|
+
background: white;
|
41
|
+
padding: 1px 30px;
|
42
|
+
-webkit-box-shadow: 0 3px 5px #d4d5d5;
|
43
|
+
-moz-box-shadow: 0 3px 5px #d4d5d5;
|
44
|
+
-o-box-shadow: 0 3px 5px #d4d5d5;
|
45
|
+
box-shadow: 0 3px 5px #d4d5d5;
|
46
|
+
}
|
47
|
+
|
48
|
+
h1, h2 , h3 {
|
49
|
+
font-family: sans-serif;
|
50
|
+
color: #000;
|
51
|
+
line-height: 1.321em;
|
52
|
+
font-weight: normal;
|
53
|
+
margin: 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
h1 {
|
57
|
+
margin-bottom: 10px;
|
58
|
+
font-size: 30px;
|
59
|
+
}
|
60
|
+
|
61
|
+
h2 {
|
62
|
+
margin: 25px 0 10px;
|
63
|
+
font-size: 18px;
|
64
|
+
}
|
65
|
+
|
66
|
+
h3 {
|
67
|
+
font-size: 13px;
|
68
|
+
font-weight: bold;
|
69
|
+
margin-bottom: 5px;
|
70
|
+
padding-left: 15px;
|
71
|
+
}
|
72
|
+
|
73
|
+
a, a:visited, a:link, .num {
|
74
|
+
color: #4781c6;
|
75
|
+
text-decoration: none;
|
76
|
+
}
|
77
|
+
|
78
|
+
a:hover {
|
79
|
+
color: #f2b500;
|
80
|
+
text-decoration: none;
|
81
|
+
}
|
82
|
+
|
83
|
+
ul, li {
|
84
|
+
list-style: none;
|
85
|
+
}
|
86
|
+
|
87
|
+
ul {
|
88
|
+
margin: 0;
|
89
|
+
margin-bottom: 10px;
|
90
|
+
padding-left: 30px;
|
91
|
+
}
|
92
|
+
|
93
|
+
.date {
|
94
|
+
font-size: 13px;
|
95
|
+
font-style: italic;
|
96
|
+
}
|
97
|
+
|
98
|
+
.story {
|
99
|
+
margin-bottom: 25px;
|
100
|
+
}
|
101
|
+
|
102
|
+
</style>
|
103
|
+
|
104
|
+
<link rel="shortcut icon" href="assets/favicon.ico" />
|
105
|
+
</head>
|
106
|
+
|
107
|
+
<body>
|
108
|
+
<div class="content">
|
109
|
+
<h1>Change Log @ <%= @changelog.date %></h1>
|
110
|
+
<div class="content-inner">
|
111
|
+
|
112
|
+
<% for @release in @changelog.releases %>
|
113
|
+
<h2><%= @release.title %> <span class="date">(<%= @release.date %>)</span></h2>
|
114
|
+
|
115
|
+
<% for @story in @release.stories %>
|
116
|
+
<div class="story">
|
117
|
+
|
118
|
+
<% if @story.valid? %>
|
119
|
+
<h3>
|
120
|
+
<a href="<%= @story.url %>"><span class="num"><%= @story.num %></span></a>
|
121
|
+
<span class="name"><%= @story.name %></span>
|
122
|
+
</h3>
|
123
|
+
<% else %>
|
124
|
+
<h3>
|
125
|
+
<span class="num"><%= @story.num %></span>
|
126
|
+
<span class="name"><%= @story.error %></span>
|
127
|
+
</h3>
|
128
|
+
<% end %>
|
129
|
+
|
130
|
+
<ul class="commits">
|
131
|
+
<% for @commit in @release.commits(@story.num) %>
|
132
|
+
<li><%= @commit.message %></li>
|
133
|
+
<% end %>
|
134
|
+
</ul>
|
135
|
+
</div>
|
136
|
+
<% end %>
|
137
|
+
|
138
|
+
<% end %>
|
139
|
+
</div>
|
140
|
+
</div>
|
141
|
+
</body>
|
142
|
+
</html>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ptlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -123,12 +123,17 @@ files:
|
|
123
123
|
- lib/ptlog.rb
|
124
124
|
- lib/ptlog/capistrno.rb
|
125
125
|
- lib/ptlog/change_log.rb
|
126
|
+
- lib/ptlog/git/lib.rb
|
127
|
+
- lib/ptlog/git/tags_list.rb
|
126
128
|
- lib/ptlog/pivotal/api.rb
|
127
129
|
- lib/ptlog/pivotal/story.rb
|
128
130
|
- lib/ptlog/release.rb
|
129
131
|
- lib/ptlog/version.rb
|
132
|
+
- lib/ptlog/wrappers/changelog.rb
|
133
|
+
- lib/ptlog/wrappers/release.rb
|
130
134
|
- ptlog.gemspec
|
131
135
|
- spec/spec_helper.rb
|
136
|
+
- templates/changelog.erb
|
132
137
|
homepage: https://github.com/dml/ptlog
|
133
138
|
licenses:
|
134
139
|
- MIT
|
@@ -156,4 +161,3 @@ specification_version: 3
|
|
156
161
|
summary: Generages changelog based on PivotalTracker stories and Git commits
|
157
162
|
test_files:
|
158
163
|
- spec/spec_helper.rb
|
159
|
-
has_rdoc:
|