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
@@ -0,0 +1,77 @@
|
|
1
|
+
module VCLog
|
2
|
+
|
3
|
+
# The Change class models an entry in a change log.
|
4
|
+
#
|
5
|
+
class ChangePoint
|
6
|
+
|
7
|
+
# Type of change, as assigned by hueristics.
|
8
|
+
attr_accessor :type
|
9
|
+
|
10
|
+
# The priority level of this change, as assigned by hueristics.
|
11
|
+
# This can be `nil`, as Heuristics will always make sure a
|
12
|
+
# commit has an inteer level before going out to template.
|
13
|
+
attr_accessor :level
|
14
|
+
|
15
|
+
# The descriptive label of this change, as assigned by hueristics.
|
16
|
+
attr_accessor :label
|
17
|
+
|
18
|
+
# ANSI color to apply. Actually this can be a list
|
19
|
+
# of any support ansi gem terms, but usually it's
|
20
|
+
# just the color term, such as `:red`.
|
21
|
+
attr_accessor :color
|
22
|
+
|
23
|
+
#
|
24
|
+
def initialize(change, message)
|
25
|
+
@change = change
|
26
|
+
@message = message.strip
|
27
|
+
|
28
|
+
@label = nil
|
29
|
+
@level = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Change from which point is derived.
|
33
|
+
attr :change
|
34
|
+
|
35
|
+
# The point's message.
|
36
|
+
attr_accessor :message
|
37
|
+
alias_method :msg, :message
|
38
|
+
alias_method :msg=, :message=
|
39
|
+
|
40
|
+
# Delegate missing methods to +change+.
|
41
|
+
def method_missing(s,*a,&b)
|
42
|
+
if @change.respond_to?(s)
|
43
|
+
@change.send(s,*a,&b)
|
44
|
+
else
|
45
|
+
p caller
|
46
|
+
super(s,*a,&b)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Change points do not have sub-points.
|
51
|
+
def points
|
52
|
+
[]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Apply heuristic rules to change.
|
56
|
+
def apply_heuristics(heuristics)
|
57
|
+
heuristics.apply(self)
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
def to_h
|
62
|
+
{ 'author' => change.author,
|
63
|
+
'date' => change.date,
|
64
|
+
'id' => change.id,
|
65
|
+
'message' => message,
|
66
|
+
'type' => type
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
def to_s(*)
|
72
|
+
message
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'vclog/core_ext'
|
2
|
+
require 'vclog/change'
|
3
|
+
|
4
|
+
module VCLog
|
5
|
+
|
6
|
+
# A ChangeLog encapsulates a list of Change objects.
|
7
|
+
#
|
8
|
+
class ChangeLog
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
#DIR = File.dirname(__FILE__)
|
13
|
+
|
14
|
+
#
|
15
|
+
# Seconds in a day.
|
16
|
+
#
|
17
|
+
DAY = 24*60*60
|
18
|
+
|
19
|
+
#
|
20
|
+
# Array of Change or ChangePoint instances.
|
21
|
+
#
|
22
|
+
attr :changes
|
23
|
+
|
24
|
+
#
|
25
|
+
# Setup new ChangeLog instance.
|
26
|
+
#
|
27
|
+
# @param [Array<Change>] changes
|
28
|
+
# An array of Change objects.
|
29
|
+
#
|
30
|
+
def initialize(changes=nil)
|
31
|
+
@changes = []
|
32
|
+
@changes = changes if changes
|
33
|
+
end
|
34
|
+
|
35
|
+
#def changes=(changes)
|
36
|
+
# @changes = []
|
37
|
+
# changes.each do |change|
|
38
|
+
# case change
|
39
|
+
# when Change
|
40
|
+
# @changes << change
|
41
|
+
# else
|
42
|
+
# @changes << Change.new(change)
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#end
|
46
|
+
|
47
|
+
# Add a change entry to the log.
|
48
|
+
def change(data={})
|
49
|
+
@changes << Change.new(data)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Sort changes in place.
|
54
|
+
#
|
55
|
+
def sort!(&block)
|
56
|
+
changes.sort!(&block)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Iterate over each change.
|
61
|
+
#
|
62
|
+
def each(&block)
|
63
|
+
changes.each(&block)
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Is the changelog void of any changes?
|
68
|
+
#
|
69
|
+
def empty?
|
70
|
+
changes.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Return the number of changes in the changelog.
|
75
|
+
#
|
76
|
+
def size
|
77
|
+
changes.size
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# And a change to the changelog.
|
82
|
+
#
|
83
|
+
def <<(entry)
|
84
|
+
case entry
|
85
|
+
when Change, ChangePoint
|
86
|
+
@changes << entry
|
87
|
+
else
|
88
|
+
#raise "Not a Change ro ChangePoint instance - #{entry.inspect}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Return a new changelog with entries having a level higer or
|
94
|
+
# equal to the given level.
|
95
|
+
#
|
96
|
+
def above(level)
|
97
|
+
above = changes.select{ |entry| entry.level >= level }
|
98
|
+
self.class.new(above)
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Return a new changelog with entries occuring after the
|
103
|
+
# given date limit.
|
104
|
+
#
|
105
|
+
def after(date_limit)
|
106
|
+
after = changes.select{ |entry| entry.date > date_limit + DAY }
|
107
|
+
self.class.new(after)
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Return a new changelog with entries occuring before the
|
112
|
+
# given date limit.
|
113
|
+
#
|
114
|
+
def before(date_limit)
|
115
|
+
before = changes.select{ |entry| entry.date <= date_limit + DAY }
|
116
|
+
self.class.new(before)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return a new changelog with entries that have a specified type.
|
120
|
+
# TODO: Be able to specify which types to include or omit.
|
121
|
+
#def typed
|
122
|
+
# self.class.new(changes.select{ |e| e.type })
|
123
|
+
#end
|
124
|
+
|
125
|
+
#
|
126
|
+
def by_type
|
127
|
+
mapped = {}
|
128
|
+
changes.each do |entry|
|
129
|
+
mapped[entry.type] ||= self.class.new
|
130
|
+
mapped[entry.type] << entry
|
131
|
+
end
|
132
|
+
mapped
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
def by_author
|
137
|
+
mapped = {}
|
138
|
+
changes.each do |entry|
|
139
|
+
mapped[entry.author] ||= self.class.new
|
140
|
+
mapped[entry.author] << entry
|
141
|
+
end
|
142
|
+
mapped
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
def by_date
|
147
|
+
mapped = {}
|
148
|
+
changes.each do |entry|
|
149
|
+
mapped[entry.date.strftime('%Y-%m-%d')] ||= self.class.new
|
150
|
+
mapped[entry.date.strftime('%Y-%m-%d')] << entry
|
151
|
+
end
|
152
|
+
mapped = mapped.to_a.sort{ |a,b| b[0] <=> a[0] }
|
153
|
+
mapped
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
#def by_date
|
158
|
+
# mapped = {}
|
159
|
+
# changes.each do |entry|
|
160
|
+
# mapped[entry.date.strftime('%Y-%m-%d')] ||= self.class.new
|
161
|
+
# mapped[entry.date.strftime('%Y-%m-%d')] << entry
|
162
|
+
# end
|
163
|
+
# mapped
|
164
|
+
#end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Convert to list of hash.
|
168
|
+
#
|
169
|
+
# @return [Array<Hash>]
|
170
|
+
#
|
171
|
+
# @todo Not a Hash! Need to rename method.
|
172
|
+
#
|
173
|
+
def to_h
|
174
|
+
map{ |change| change.to_h }
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
# TODO: THIS IS HERE AS A REMINDER ABOUT TEH XSL TEMPLATE.
|
184
|
+
# WHAT TO DO WITH IT?
|
185
|
+
|
186
|
+
=begin
|
187
|
+
###################
|
188
|
+
# Save Chaqngelog #
|
189
|
+
###################
|
190
|
+
|
191
|
+
# Save changelog as file in specified format.
|
192
|
+
def save(file, format=:gnu, *args)
|
193
|
+
case format.to_sym
|
194
|
+
when :xml
|
195
|
+
text = to_xml
|
196
|
+
#save_xsl(file)
|
197
|
+
when :html
|
198
|
+
text = to_html(*args)
|
199
|
+
when :rel
|
200
|
+
text = to_rel(file, *args)
|
201
|
+
when :yaml
|
202
|
+
text = to_yaml(file)
|
203
|
+
when :json
|
204
|
+
text = to_json(file)
|
205
|
+
else
|
206
|
+
text = to_gnu
|
207
|
+
end
|
208
|
+
|
209
|
+
FileUtils.mkdir_p(File.dirname(file))
|
210
|
+
|
211
|
+
different = true
|
212
|
+
if File.exist?(file)
|
213
|
+
different = (File.read(file) != text)
|
214
|
+
end
|
215
|
+
|
216
|
+
File.open(file, 'w') do |f|
|
217
|
+
f << text
|
218
|
+
end if different
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
def save_xsl(file)
|
223
|
+
#xslfile = file.chomp(File.extname(file)) + '.xsl'
|
224
|
+
xslfile = File.join(File.dirname(file), 'log.xsl')
|
225
|
+
unless File.exist?(xslfile)
|
226
|
+
FileUtils.mkdir_p(File.dirname(xslfile))
|
227
|
+
File.open(xslfile, 'w') do |f|
|
228
|
+
f << DEFAULT_LOG_XSL
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
=end
|
233
|
+
|
data/lib/vclog/cli.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'vclog'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module VCLog
|
5
|
+
|
6
|
+
module CLI
|
7
|
+
|
8
|
+
#
|
9
|
+
def self.register
|
10
|
+
@register ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
# Abstract base class for all command classes.
|
14
|
+
#
|
15
|
+
class Abstract
|
16
|
+
|
17
|
+
#
|
18
|
+
def self.run(argv)
|
19
|
+
new.run(argv)
|
20
|
+
rescue => err
|
21
|
+
if $DEBUG
|
22
|
+
raise err
|
23
|
+
else
|
24
|
+
puts err.message
|
25
|
+
exit -1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def self.inherited(subclass)
|
31
|
+
CLI.register << subclass
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
def self.terms
|
36
|
+
[name.split('::').last.downcase]
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
def initialize
|
41
|
+
@options = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
def options
|
46
|
+
@options
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
def parser(&block)
|
51
|
+
parser = OptionParser.new(&block)
|
52
|
+
|
53
|
+
parser.separator " "
|
54
|
+
parser.separator "SYSTEM OPTIONS:"
|
55
|
+
parser.on('--debug', 'show debugging information') do
|
56
|
+
$DEBUG = true
|
57
|
+
end
|
58
|
+
parser.on('--help' , '-h', 'display this help information') do
|
59
|
+
puts parser
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
parser
|
63
|
+
end
|
64
|
+
|
65
|
+
# Run the command.
|
66
|
+
def run(argv=nil)
|
67
|
+
argv ||= ARGV.dup
|
68
|
+
|
69
|
+
parser.parse!(argv)
|
70
|
+
|
71
|
+
@arguments = argv
|
72
|
+
|
73
|
+
root = Dir.pwd # TODO: find root
|
74
|
+
|
75
|
+
@repo = VCLog::Repo.new(root, options)
|
76
|
+
|
77
|
+
execute
|
78
|
+
end
|
79
|
+
|
80
|
+
# Repo is set in #run.
|
81
|
+
def repo
|
82
|
+
@repo
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
attr :arguments
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'vclog/cli/abstract'
|
2
|
+
|
3
|
+
module VCLog::CLI
|
4
|
+
|
5
|
+
#
|
6
|
+
class Autotag < Abstract
|
7
|
+
|
8
|
+
#
|
9
|
+
def self.terms
|
10
|
+
['autotag']
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
def parser
|
15
|
+
super do |opt|
|
16
|
+
opt.banner = "Usage: vclog autotag"
|
17
|
+
opt.separator(" ")
|
18
|
+
opt.separator("DESCRIPTION:")
|
19
|
+
opt.separator(" Ensure each entry in History has been tagged.")
|
20
|
+
opt.separator(" ")
|
21
|
+
opt.separator("SPECIAL OPTIONS:")
|
22
|
+
opt.on('--prefix', '-p', 'tag label prefix'){ options[:prefix] = true }
|
23
|
+
opt.on('--file' , '-f FILE', 'specify history file'){ options[:history_file] = file }
|
24
|
+
opt.on('--force' , '-y', 'perform tagging without confirmation'){ options[:force] = true }
|
25
|
+
opt.on('--dryrun', '-n', 'run in dryrun mode'){ $DRYRUN = true }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def execute
|
31
|
+
repo.autotag(options[:prefix])
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|