rubycut-vclog 1.9.4
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|