rubycut-vclog 1.9.4
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/.yardopts +7 -0
- data/History.md +249 -0
- data/License.txt +23 -0
- data/README.md +133 -0
- data/bin/vclog +6 -0
- data/bin/vclog-autotag +6 -0
- data/bin/vclog-bump +6 -0
- data/bin/vclog-formats +6 -0
- data/bin/vclog-news +6 -0
- data/bin/vclog-version +6 -0
- data/lib/vclog.rb +6 -0
- data/lib/vclog.yml +68 -0
- data/lib/vclog/adapters.rb +12 -0
- data/lib/vclog/adapters/abstract.rb +131 -0
- data/lib/vclog/adapters/darcs.rb +93 -0
- data/lib/vclog/adapters/git.rb +190 -0
- data/lib/vclog/adapters/hg.rb +129 -0
- data/lib/vclog/adapters/svn.rb +155 -0
- data/lib/vclog/change.rb +207 -0
- data/lib/vclog/change_point.rb +77 -0
- data/lib/vclog/changelog.rb +233 -0
- data/lib/vclog/cli.rb +8 -0
- data/lib/vclog/cli/abstract.rb +92 -0
- data/lib/vclog/cli/autotag.rb +36 -0
- data/lib/vclog/cli/bump.rb +29 -0
- data/lib/vclog/cli/formats.rb +28 -0
- data/lib/vclog/cli/log.rb +86 -0
- data/lib/vclog/cli/news.rb +29 -0
- data/lib/vclog/cli/version.rb +30 -0
- data/lib/vclog/config.rb +143 -0
- data/lib/vclog/core_ext.rb +11 -0
- data/lib/vclog/heuristics.rb +192 -0
- data/lib/vclog/heuristics/rule.rb +73 -0
- data/lib/vclog/heuristics/type.rb +29 -0
- data/lib/vclog/history_file.rb +69 -0
- data/lib/vclog/metadata.rb +16 -0
- data/lib/vclog/rc.rb +9 -0
- data/lib/vclog/release.rb +67 -0
- data/lib/vclog/repo.rb +298 -0
- data/lib/vclog/report.rb +200 -0
- data/lib/vclog/tag.rb +151 -0
- data/lib/vclog/templates/changelog.ansi.rb +35 -0
- data/lib/vclog/templates/changelog.atom.erb +52 -0
- data/lib/vclog/templates/changelog.gnu.rb +24 -0
- data/lib/vclog/templates/changelog.html.erb +49 -0
- data/lib/vclog/templates/changelog.json.rb +1 -0
- data/lib/vclog/templates/changelog.markdown.rb +30 -0
- data/lib/vclog/templates/changelog.rdoc.rb +30 -0
- data/lib/vclog/templates/changelog.rss.erb +54 -0
- data/lib/vclog/templates/changelog.xml.erb +28 -0
- data/lib/vclog/templates/changelog.xsl +34 -0
- data/lib/vclog/templates/changelog.yaml.rb +1 -0
- data/lib/vclog/templates/history.ansi.rb +57 -0
- data/lib/vclog/templates/history.atom.erb +84 -0
- data/lib/vclog/templates/history.gnu.rb +39 -0
- data/lib/vclog/templates/history.html.erb +60 -0
- data/lib/vclog/templates/history.json.rb +1 -0
- data/lib/vclog/templates/history.markdown.rb +38 -0
- data/lib/vclog/templates/history.rdoc.rb +36 -0
- data/lib/vclog/templates/history.rss.erb +84 -0
- data/lib/vclog/templates/history.xml.erb +43 -0
- data/lib/vclog/templates/history.yaml.rb +1 -0
- data/man/man1/index.txt +9 -0
- data/man/man1/vclog-autotag.1.ronn +29 -0
- data/man/man1/vclog-bump.1.ronn +21 -0
- data/man/man1/vclog-news.1.ronn +25 -0
- data/man/man1/vclog-version.1.ronn +14 -0
- data/man/man1/vclog.1.ronn +49 -0
- data/spec/feature_git_changes.rb +58 -0
- data/spec/feature_git_history.rb +58 -0
- data/spec/feature_hg_changes.rb +58 -0
- data/spec/feature_hg_history.rb +58 -0
- data/spec/featurettes/repo_creation.rb +64 -0
- data/spec/featurettes/shellout.rb +16 -0
- data/test/case_metadata.rb +10 -0
- metadata +265 -0
data/lib/vclog/report.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'erb'
|
3
|
+
#require 'ansi'
|
4
|
+
|
5
|
+
module VCLog
|
6
|
+
|
7
|
+
# The Report class acts a controller for outputing
|
8
|
+
# change log / release history.
|
9
|
+
#
|
10
|
+
class Report
|
11
|
+
|
12
|
+
#
|
13
|
+
# Directory of this file, so as to locate templates.
|
14
|
+
#
|
15
|
+
DIR = File.dirname(__FILE__)
|
16
|
+
|
17
|
+
#
|
18
|
+
# Instance of VCLog::Repo.
|
19
|
+
#
|
20
|
+
attr :repo
|
21
|
+
|
22
|
+
#
|
23
|
+
# OpenStruct of report options.
|
24
|
+
#
|
25
|
+
attr :options
|
26
|
+
|
27
|
+
#
|
28
|
+
# Setup new Reporter instance.
|
29
|
+
#
|
30
|
+
# @param [Repo] repo
|
31
|
+
# An instance of VCLog::Repo.
|
32
|
+
#
|
33
|
+
def initialize(repo, options)
|
34
|
+
@repo = repo
|
35
|
+
|
36
|
+
options[:type] ||= 'changelog'
|
37
|
+
options[:format] ||= 'ansi'
|
38
|
+
|
39
|
+
@options = OpenStruct.new(options)
|
40
|
+
|
41
|
+
@options.level ||= 0
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Returns a Changelog object.
|
46
|
+
#
|
47
|
+
def changelog
|
48
|
+
changes = options.point ? repo.changes : repo.change_points
|
49
|
+
ChangeLog.new(changes).above(options.level)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Compute and return set of releases for +changelog+ changes.
|
54
|
+
#
|
55
|
+
def releases
|
56
|
+
repo.releases(changelog.changes)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Report type.
|
61
|
+
#
|
62
|
+
def type
|
63
|
+
options.type
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Report format.
|
68
|
+
#
|
69
|
+
def format
|
70
|
+
options.format
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# User as given by the command line or from the repo.
|
75
|
+
#
|
76
|
+
def user
|
77
|
+
options.user || repo.user
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Email address as given on the command line or from the repo.
|
82
|
+
#
|
83
|
+
def email
|
84
|
+
options.email || repo.email
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Repo repository URL.
|
89
|
+
#
|
90
|
+
def repository
|
91
|
+
repo.repository
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Repository URL.
|
96
|
+
#
|
97
|
+
# @todo Ensure this is being provided.
|
98
|
+
#
|
99
|
+
def url
|
100
|
+
options.url || repo.repository
|
101
|
+
end
|
102
|
+
|
103
|
+
# TODO
|
104
|
+
def homepage
|
105
|
+
options.homepage
|
106
|
+
end
|
107
|
+
|
108
|
+
# TODO: Let the title be nil and the template can set a default if it needs to.
|
109
|
+
|
110
|
+
#
|
111
|
+
# Report title.
|
112
|
+
#
|
113
|
+
def title
|
114
|
+
return options.title if options.title
|
115
|
+
case type
|
116
|
+
when :history
|
117
|
+
"RELEASE HISTORY"
|
118
|
+
else
|
119
|
+
"CHANGELOG"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# NOTE: ERBs trim_mode is broken --it removes an extra space.
|
124
|
+
# So we can't use it for plain text templates.
|
125
|
+
|
126
|
+
#
|
127
|
+
# Print report.
|
128
|
+
#
|
129
|
+
def print
|
130
|
+
require_formatter(format)
|
131
|
+
|
132
|
+
tmpl_glob = File.join(DIR, 'templates', "#{type}.#{format}.{erb,rb}")
|
133
|
+
tmpl_file = Dir[tmpl_glob].first
|
134
|
+
|
135
|
+
raise "could not find template -- #{type}.#{format}" unless tmpl_file
|
136
|
+
|
137
|
+
tmpl = File.read(tmpl_file)
|
138
|
+
|
139
|
+
case File.extname(tmpl_file)
|
140
|
+
when '.rb'
|
141
|
+
eval(tmpl, binding, tmpl_file)
|
142
|
+
when '.erb'
|
143
|
+
erb = ERB.new(tmpl, nil, '<>')
|
144
|
+
erb.result(binding)
|
145
|
+
else
|
146
|
+
raise "unrecognized template type -- #{tmpl_file}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
#
|
153
|
+
# Depending on the format special libraries may by required.
|
154
|
+
#
|
155
|
+
def require_formatter(format)
|
156
|
+
case format.to_s
|
157
|
+
when 'yaml'
|
158
|
+
require 'yaml'
|
159
|
+
when 'json'
|
160
|
+
require 'json'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# HTML escape.
|
166
|
+
#
|
167
|
+
def h(input)
|
168
|
+
result = input.to_s.dup
|
169
|
+
result.gsub!("&", "&")
|
170
|
+
result.gsub!("<", "<")
|
171
|
+
result.gsub!(">", ">")
|
172
|
+
result.gsub!("'", "'")
|
173
|
+
#result.gsub!("@", "&at;")
|
174
|
+
result.gsub!("\"", """)
|
175
|
+
return result
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
# Convert from RDoc to HTML.
|
180
|
+
#
|
181
|
+
def r(input)
|
182
|
+
rdoc.convert(input)
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# RDoc converter.
|
187
|
+
#
|
188
|
+
# @return [RDoc::Markup::ToHtml] rdoc markup HTML converter.
|
189
|
+
#
|
190
|
+
def rdoc
|
191
|
+
@_rdoc ||= (
|
192
|
+
gem 'rdoc' rescue nil # to ensure latest version
|
193
|
+
require 'rdoc'
|
194
|
+
RDoc::Markup::ToHtml.new
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
data/lib/vclog/tag.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
module VCLog
|
2
|
+
|
3
|
+
#
|
4
|
+
class Tag
|
5
|
+
|
6
|
+
#
|
7
|
+
# Tag's commit id.
|
8
|
+
#
|
9
|
+
attr_accessor :id
|
10
|
+
|
11
|
+
#
|
12
|
+
# Tag name, which in this case is typically a version stamp.
|
13
|
+
#
|
14
|
+
attr_accessor :name
|
15
|
+
|
16
|
+
#
|
17
|
+
# Date tag was made.
|
18
|
+
#
|
19
|
+
attr_accessor :date
|
20
|
+
|
21
|
+
#
|
22
|
+
# Creator to the tag.
|
23
|
+
#
|
24
|
+
attr_accessor :author
|
25
|
+
|
26
|
+
#
|
27
|
+
# Tag message.
|
28
|
+
#
|
29
|
+
attr_accessor :message
|
30
|
+
|
31
|
+
#
|
32
|
+
# Last commit before Tag.
|
33
|
+
#
|
34
|
+
attr_accessor :commit
|
35
|
+
|
36
|
+
#
|
37
|
+
# @todo Hg is using this at the moment but it really shouldn't be here,
|
38
|
+
# since it is take care of by `commit.files`.
|
39
|
+
#
|
40
|
+
attr_accessor :files
|
41
|
+
|
42
|
+
#
|
43
|
+
# Setup new Tag intsance.
|
44
|
+
#
|
45
|
+
# If `:commit` is not provided, it is assume that the underlying SCM
|
46
|
+
# simply creates tags as references to a commit. That is to say the tag
|
47
|
+
# information and the commit information are one and the same. This is
|
48
|
+
# the case for Hg, but not for Git, for instance.
|
49
|
+
#
|
50
|
+
def initialize(data={})
|
51
|
+
@commit = data.delete(:commit) || Change.new(data)
|
52
|
+
|
53
|
+
data.each do |k,v|
|
54
|
+
__send__("#{k}=", v)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Set the tag name.
|
60
|
+
#
|
61
|
+
def name=(name)
|
62
|
+
@name = (name || 'HEAD').strip
|
63
|
+
end
|
64
|
+
|
65
|
+
# Alias for +name+ attribute.
|
66
|
+
alias_method :label, :name
|
67
|
+
alias_method :label=, :name=
|
68
|
+
|
69
|
+
#
|
70
|
+
alias_method :tag, :name
|
71
|
+
alias_method :tag=, :name=
|
72
|
+
|
73
|
+
# Set author name, stripping white space.
|
74
|
+
def author=(author)
|
75
|
+
@author = author.to_s.strip
|
76
|
+
end
|
77
|
+
|
78
|
+
# Alias for +author+ attribute.
|
79
|
+
alias_method :tagger, :author
|
80
|
+
alias_method :tagger=, :author=
|
81
|
+
|
82
|
+
# Alias for +author+ attribute.
|
83
|
+
alias_method :who, :author
|
84
|
+
alias_method :who=, :author=
|
85
|
+
|
86
|
+
#
|
87
|
+
# Set the tag date, converting +date+ to a Time object.
|
88
|
+
#
|
89
|
+
def date=(date)
|
90
|
+
@date = parse_date(date)
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Set the tag message.
|
95
|
+
#
|
96
|
+
def message=(msg)
|
97
|
+
@message = msg.strip
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Alias for +message+.
|
102
|
+
#
|
103
|
+
alias_method :msg, :message
|
104
|
+
alias_method :msg=, :message=
|
105
|
+
|
106
|
+
#
|
107
|
+
# Convert to Hash.
|
108
|
+
#
|
109
|
+
def to_h
|
110
|
+
{
|
111
|
+
'name' => name,
|
112
|
+
'date' => date,
|
113
|
+
'author' => author,
|
114
|
+
'message' => message,
|
115
|
+
'commit' => commit.to_h
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Inspection string for Tag.
|
121
|
+
#
|
122
|
+
def inspect
|
123
|
+
dstr = date ? date.strftime('%Y-%m-%d %H:%M:%S') : '(date?)'
|
124
|
+
"<Tag #{name} #{dstr}>"
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Normal tag order is the reverse typical sorts.
|
129
|
+
#
|
130
|
+
def <=>(other)
|
131
|
+
return -1 if name == 'HEAD'
|
132
|
+
other.name <=> name
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
#
|
138
|
+
#
|
139
|
+
#
|
140
|
+
def parse_date(date)
|
141
|
+
case date
|
142
|
+
when Time
|
143
|
+
date
|
144
|
+
else
|
145
|
+
Time.parse(date.to_s)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ansi'
|
2
|
+
|
3
|
+
out = []
|
4
|
+
|
5
|
+
out << "#{title}\n".ansi(:bold) if title
|
6
|
+
|
7
|
+
changelog.by_date.each do |date, date_changes|
|
8
|
+
|
9
|
+
date_changes.by_author.each do |author, author_changes|
|
10
|
+
|
11
|
+
out << "#{ date } #{ author }\n".ansi(:bold)
|
12
|
+
|
13
|
+
author_changes.sort!{|a,b| b.level <=> a.level}
|
14
|
+
|
15
|
+
author_changes.each do |entry|
|
16
|
+
msg = entry.to_s(:summary=>!options.detail)
|
17
|
+
|
18
|
+
#if !options.summary && entry.type
|
19
|
+
# msg << " [#{ entry.type }]"
|
20
|
+
#end
|
21
|
+
|
22
|
+
msg = msg.ansi(*entry.color) unless entry.color.empty?
|
23
|
+
|
24
|
+
msg << "\n(##{entry.id})" if options.reference
|
25
|
+
|
26
|
+
out << msg.tabto(4).sub(' ',' * ')
|
27
|
+
end
|
28
|
+
|
29
|
+
out << ""
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
out.join("\n") + "\n"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
|
3
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
4
|
+
|
5
|
+
<title><%= title %></title>
|
6
|
+
|
7
|
+
<% if url %><link href="<%= url %>" /><% end %>
|
8
|
+
|
9
|
+
<% if homepage %><link href="<%= homepage %>" /><% end %>
|
10
|
+
|
11
|
+
<id><% if repo.uuid %>urn:uuid:<%= repo.uuid %><% else %><%= repo.repository %><% end %></id>
|
12
|
+
|
13
|
+
<updated><%= Time.now.xmlschema %></updated>
|
14
|
+
|
15
|
+
<author>
|
16
|
+
|
17
|
+
<name><%= user %></name>
|
18
|
+
|
19
|
+
<email><%= email %></email>
|
20
|
+
|
21
|
+
</author>
|
22
|
+
|
23
|
+
<% changelog.changes.sort{|a,b| b.date <=> a.date}.each do |entry| %>
|
24
|
+
|
25
|
+
<entry>
|
26
|
+
|
27
|
+
<title><%= h entry.summary %></title>
|
28
|
+
|
29
|
+
<id><%= url %>#<%= entry.id %></id>
|
30
|
+
|
31
|
+
<author><%= entry.author %></author>
|
32
|
+
|
33
|
+
<updated><%= entry.date.xmlschema %></updated>
|
34
|
+
|
35
|
+
<content type="xhtml">
|
36
|
+
|
37
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
38
|
+
|
39
|
+
<%= entry.message %><br/>
|
40
|
+
|
41
|
+
<%= entry.author %> <%= entry.date.strftime('%Y-%m-%d %H:%M:%S') %>
|
42
|
+
|
43
|
+
</div>
|
44
|
+
|
45
|
+
</content>
|
46
|
+
|
47
|
+
</entry>
|
48
|
+
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
</feed>
|
52
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
out = []
|
2
|
+
|
3
|
+
out << "#{title}\n" if title
|
4
|
+
|
5
|
+
changelog.by_date.each do |date, date_changes|
|
6
|
+
|
7
|
+
date_changes.by_author.each do |author, author_changes|
|
8
|
+
out << "#{ date } #{ author }\n"
|
9
|
+
|
10
|
+
author_changes.each do |entry|
|
11
|
+
msg = entry.to_s(:summary=>!options.detail)
|
12
|
+
|
13
|
+
#msg << " [#{entry.type}]" if entry.type && !options.summary
|
14
|
+
msg << "\n(##{entry.id})" if options.reference
|
15
|
+
|
16
|
+
out << msg.tabto(8).sub(' ',' * ')
|
17
|
+
end
|
18
|
+
|
19
|
+
out << ""
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
out.join("\n") + "\n"
|