vclog 1.8.2 → 1.9.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.
Files changed (78) hide show
  1. data/.ruby +4 -3
  2. data/.yardopts +7 -0
  3. data/HISTORY.rdoc +207 -0
  4. data/README.rdoc +44 -27
  5. data/bin/vclog +4 -2
  6. data/bin/vclog-autotag +6 -0
  7. data/bin/vclog-bump +6 -0
  8. data/bin/vclog-formats +6 -0
  9. data/bin/vclog-version +6 -0
  10. data/lib/vclog.rb +1 -1
  11. data/lib/vclog.yml +58 -0
  12. data/lib/vclog/adapters.rb +2 -1
  13. data/lib/vclog/adapters/abstract.rb +87 -232
  14. data/lib/vclog/adapters/darcs.rb +72 -67
  15. data/lib/vclog/adapters/git.rb +166 -140
  16. data/lib/vclog/adapters/hg.rb +98 -62
  17. data/lib/vclog/adapters/svn.rb +116 -113
  18. data/lib/vclog/change.rb +110 -81
  19. data/lib/vclog/change_point.rb +77 -0
  20. data/lib/vclog/changelog.rb +58 -296
  21. data/lib/vclog/cli.rb +6 -70
  22. data/lib/vclog/cli/abstract.rb +64 -81
  23. data/lib/vclog/cli/autotag.rb +1 -3
  24. data/lib/vclog/cli/bump.rb +3 -4
  25. data/lib/vclog/cli/formats.rb +4 -4
  26. data/lib/vclog/cli/log.rb +86 -0
  27. data/lib/vclog/cli/version.rb +3 -3
  28. data/lib/vclog/{facets.rb → core_ext.rb} +0 -0
  29. data/lib/vclog/heuristics.rb +112 -38
  30. data/lib/vclog/heuristics/rule.rb +52 -12
  31. data/lib/vclog/heuristics/{label.rb → type.rb} +2 -2
  32. data/lib/vclog/history_file.rb +2 -2
  33. data/lib/vclog/metadata.rb +13 -1
  34. data/lib/vclog/release.rb +26 -12
  35. data/lib/vclog/repo.rb +191 -27
  36. data/lib/vclog/report.rb +187 -0
  37. data/lib/vclog/tag.rb +66 -39
  38. data/lib/vclog/templates/changelog.ansi.rb +9 -26
  39. data/lib/vclog/templates/changelog.atom.erb +3 -3
  40. data/lib/vclog/templates/changelog.gnu.rb +4 -11
  41. data/lib/vclog/templates/changelog.html.erb +11 -2
  42. data/lib/vclog/templates/changelog.markdown.rb +4 -4
  43. data/lib/vclog/templates/changelog.rdoc.rb +4 -4
  44. data/lib/vclog/templates/changelog.rss.erb +2 -6
  45. data/lib/vclog/templates/changelog.xml.erb +14 -2
  46. data/lib/vclog/templates/history.ansi.rb +10 -17
  47. data/lib/vclog/templates/history.atom.erb +4 -4
  48. data/lib/vclog/templates/history.gnu.rb +5 -7
  49. data/lib/vclog/templates/history.html.erb +11 -4
  50. data/lib/vclog/templates/history.json.rb +1 -1
  51. data/lib/vclog/templates/history.markdown.rb +5 -7
  52. data/lib/vclog/templates/history.rdoc.rb +5 -9
  53. data/lib/vclog/templates/history.rss.erb +3 -5
  54. data/lib/vclog/templates/history.xml.erb +15 -3
  55. data/lib/vclog/templates/history.yaml.rb +1 -1
  56. data/man/man1/vclog-autotag.1 +1 -1
  57. data/man/man1/vclog-autotag.1.html +1 -1
  58. data/man/man1/vclog-bump.1 +1 -1
  59. data/man/man1/vclog-bump.1.html +1 -1
  60. data/man/man1/vclog-version.1 +1 -1
  61. data/man/man1/vclog-version.1.html +1 -1
  62. data/man/man1/vclog.1 +25 -13
  63. data/man/man1/vclog.1.html +29 -20
  64. data/man/man1/vclog.1.ronn +31 -18
  65. data/test/unit/case_metadata.rb +1 -1
  66. metadata +48 -34
  67. data/lib/vclog/cli/changelog.rb +0 -33
  68. data/lib/vclog/cli/help.rb +0 -42
  69. data/lib/vclog/cli/history.rb +0 -39
  70. data/lib/vclog/formatter.rb +0 -123
  71. data/lib/vclog/history.rb +0 -131
  72. data/lib/vclog/kernel.rb +0 -12
  73. data/man/man1/vclog-changelog.1 +0 -47
  74. data/man/man1/vclog-changelog.1.html +0 -123
  75. data/man/man1/vclog-changelog.1.ronn +0 -39
  76. data/man/man1/vclog-history.1 +0 -44
  77. data/man/man1/vclog-history.1.html +0 -122
  78. data/man/man1/vclog-history.1.ronn +0 -38
@@ -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
@@ -1,28 +1,31 @@
1
- module VCLog
1
+ require 'vclog/core_ext'
2
+ require 'vclog/change'
2
3
 
3
- require 'vclog/facets'
4
- require 'vclog/change'
4
+ module VCLog
5
5
 
6
- # Supports output formats:
7
- #
8
- # xml
9
- # html
10
- # yaml
11
- # json
12
- # text
6
+ # A ChangeLog encapsulates a list of Change objects.
13
7
  #
14
8
  class ChangeLog
15
9
 
16
10
  include Enumerable
17
11
 
18
- DIR = File.dirname(__FILE__)
12
+ #DIR = File.dirname(__FILE__)
19
13
 
14
+ #
20
15
  # Seconds in a day.
16
+ #
21
17
  DAY = 24*60*60
22
18
 
19
+ #
20
+ # Array of Change or ChangePoint instances.
23
21
  #
24
22
  attr :changes
25
23
 
24
+ #
25
+ # Setup new ChangeLog instance.
26
+ #
27
+ # @param [Array<Change>] changes
28
+ # An array of Change objects.
26
29
  #
27
30
  def initialize(changes=nil)
28
31
  @changes = []
@@ -36,62 +39,89 @@ module VCLog
36
39
  # when Change
37
40
  # @changes << change
38
41
  # else
39
- # @changes << Change.new(*change)
42
+ # @changes << Change.new(change)
40
43
  # end
41
44
  # end
42
45
  #end
43
46
 
44
47
  # Add a change entry to the log.
45
- def change(rev, date, who, note, type=nil)
46
- @changes << Change.new(rev, date, who, note, type)
48
+ def change(data={})
49
+ @changes << Change.new(data)
47
50
  end
48
51
 
52
+ #
53
+ # Sort changes in place.
49
54
  #
50
55
  def sort!(&block)
51
56
  changes.sort!(&block)
52
57
  end
53
58
 
59
+ #
60
+ # Iterate over each change.
54
61
  #
55
62
  def each(&block)
56
63
  changes.each(&block)
57
64
  end
58
65
 
66
+ #
67
+ # Is the changelog void of any changes?
59
68
  #
60
69
  def empty?
61
70
  changes.empty?
62
71
  end
63
72
 
73
+ #
74
+ # Return the number of changes in the changelog.
64
75
  #
65
76
  def size
66
77
  changes.size
67
78
  end
68
79
 
80
+ #
81
+ # And a change to the changelog.
69
82
  #
70
83
  def <<(entry)
71
- raise unless Change===entry
72
- @changes << 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
73
90
  end
74
91
 
75
- # Return a new changelog with entries that have a specified type.
76
- # TODO: Be able to specify which types to include or omit.
77
- #def typed
78
- # self.class.new(changes.select{ |e| e.type })
79
- #end
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
80
100
 
101
+ #
81
102
  # Return a new changelog with entries occuring after the
82
103
  # given date limit.
104
+ #
83
105
  def after(date_limit)
84
106
  after = changes.select{ |entry| entry.date > date_limit + DAY }
85
107
  self.class.new(after)
86
108
  end
87
109
 
110
+ #
88
111
  # Return a new changelog with entries occuring before the
89
112
  # given date limit.
113
+ #
90
114
  def before(date_limit)
91
115
  before = changes.select{ |entry| entry.date <= date_limit + DAY }
92
116
  self.class.new(before)
93
117
  end
94
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
+
95
125
  #
96
126
  def by_type
97
127
  mapped = {}
@@ -133,173 +163,15 @@ module VCLog
133
163
  # mapped
134
164
  #end
135
165
 
136
- def to_h
137
- map{ |change| change.to_h }
138
- end
139
-
140
-
141
- # O U T P U T F O R M A T S
142
-
143
- #
144
-
145
- # def to_gnu(rev=false)
146
- # x = []
147
- # by_date.each do |date, date_changes|
148
- # date_changes.by_author.each do |author, author_changes|
149
- # x << %[#{date} #{author}\n]
150
- # #author_changes = author_changes.sort{|a,b| b.date <=> a.date}
151
- # author_changes.each do |entry|
152
- # if entry.type
153
- # msg = "#{entry.message} [#{entry.type}]".tabto(10)
154
- # else
155
- # msg = "#{entry.message}".tabto(10)
156
- # end
157
- # msg << " (#{entry.revision})" if rev
158
- # msg[8] = '*'
159
- # x << msg
160
- # end
161
- # end
162
- # x << "\n"
163
- # end
164
- # return x.join("\n")
165
- # end
166
-
167
- =begin
168
166
  #
169
-
170
- def to_gnu(rev=false)
171
- tmp = File.read(File.join(DIR, 'templates', 'changelog.gnu'))
172
- erb = ERB.new(tmp)
173
- erb.result(binding)
174
- end
175
-
167
+ # Convert to list of hash.
176
168
  #
177
-
178
- def to_yaml
179
- require 'yaml'
180
- changes.to_yaml
181
- end
182
-
169
+ # @return [Array<Hash>]
183
170
  #
184
-
185
- def to_json
186
- require 'json'
187
- changes.to_json
188
- end
189
- =end
190
-
191
- =begin
171
+ # @todo Not a Hash! Need to rename method.
192
172
  #
193
- alias_method :to_s, :to_gnu
194
-
195
- # Translate changelog into a XML document.
196
-
197
- def to_xml(xsl=nil)
198
- tmp = File.read(File.join(DIR, 'templates', 'changelog.xml'))
199
- erb = ERB.new(tmp)
200
- erb.result(binding)
201
- end
202
-
203
- # Create an HTML formated changelog.
204
- # +css+ reference defaults to 'log.css'
205
-
206
- def to_html(css=nil)
207
- tmp = File.read(File.join(DIR, 'templates', 'changelog.html'))
208
- erb = ERB.new(tmp)
209
- erb.result(binding)
210
- end
211
-
212
- # Translate history into a RDoc formatted document.
213
-
214
- def to_rdoc(rev=false)
215
- tmp = File.read(File.join(DIR, 'templates', 'changelog.rdoc'))
216
- erb = ERB.new(tmp)
217
- erb.result(binding)
218
- end
219
-
220
- # Translate history into a Markdown formatted document.
221
-
222
- def to_markdown(rev=false)
223
- tmp = File.read(File.join(DIR, 'templates', 'changelog.markdown'))
224
- erb = ERB.new(tmp)
225
- erb.result(binding)
226
- end
227
- =end
228
-
229
- =begin
230
- # Create an XML formated changelog.
231
- # +xsl+ reference defaults to 'log.xsl'
232
- def to_xml(xsl=nil)
233
- xsl = 'log.xsl' if xsl.nil?
234
- x = []
235
- x << %[<?xml version="1.0"?>]
236
- x << %[<?xml-stylesheet href="#{xsl}" type="text/xsl" ?>] if xsl
237
- x << %[<log>]
238
- changes.sort{|a,b| b.date <=> a.date}.each do |entry|
239
- x << %[<entry>]
240
- x << %[ <date>#{entry.date}</date>]
241
- x << %[ <author>#{escxml(entry.author)}</author>]
242
- x << %[ <revision>#{escxml(entry.revision)}</revision>]
243
- x << %[ <type>#{escxml(entry.type)}</type>]
244
- x << %[ <message>#{escxml(entry.message)}</message>]
245
- x << %[</entry>]
246
- end
247
- x << %[</log>]
248
- return x.join("\n")
249
- end
250
- =end
251
-
252
- =begin
253
- def to_html(css=nil)
254
- css = 'log.css' if css.nil?
255
- x = []
256
- x << %[<html>]
257
- x << %[<head>]
258
- x << %[ <title>ChangeLog</title>]
259
- x << %[ <style>]
260
- x << %[ body{font-family: sans-serif;}]
261
- x << %[ .changelog{width:800px;margin:0 auto;}]
262
- x << %[ li{padding: 10px;}]
263
- x << %[ .date{font-weight: bold; color: gray; float: left; padding: 0 5px;}]
264
- x << %[ .author{color: red;}]
265
- x << %[ .message{padding: 5 0; font-weight: bold;}]
266
- x << %[ .revision{font-size: 0.8em;}]
267
- x << %[ </style>]
268
- x << %[ <link rel="stylesheet" href="#{css}" type="text/css">] if css
269
- x << %[</head>]
270
- x << %[<body>]
271
- x << %[ <div class="changelog">]
272
- x << %[ <h1>ChangeLog</h1>]
273
- x << %[ <ul class="log">]
274
- changes.sort{|a,b| b.date <=> a.date}.each do |entry|
275
- x << %[ <li class="entry">]
276
- x << %[ <div class="date">#{entry.date}</div>]
277
- x << %[ <div class="author">#{escxml(entry.author)}</div>]
278
- x << %[ <div class="type">#{escxml(entry.type)}</div>]
279
- x << %[ <div class="message">#{escxml(entry.message)}</div>]
280
- x << %[ <div class="revision">##{escxml(entry.revision)}</div>]
281
- x << %[ </li>]
282
- end
283
- x << %[ </ul>]
284
- x << %[ </div>]
285
- x << %[</body>]
286
- x << %[</html>]
287
- return x.join("\n")
288
- end
289
- =end
290
-
291
- private
292
-
293
- #
294
- def h(input)
295
- result = input.to_s.dup
296
- result.gsub!("&", "&amp;")
297
- result.gsub!("<", "&lt;")
298
- result.gsub!(">", "&gt;")
299
- result.gsub!("'", "&apos;")
300
- #result.gsub!("@", "&at;")
301
- result.gsub!("\"", "&quot;")
302
- return result
173
+ def to_h
174
+ map{ |change| change.to_h }
303
175
  end
304
176
 
305
177
  end
@@ -308,118 +180,8 @@ end
308
180
 
309
181
 
310
182
 
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
- =begin
319
- #
320
- def format_rel(file, current_version=nil, current_release=nil, rev=false)
321
- log = []
322
- # collect releases already listed in changelog file
323
- rels = releases(file)
324
- # add current verion to release list (if given)
325
- previous_version = rels[0][0]
326
- if current_version < previous_version
327
- raise ArgumentError, "Release version is less than previous version (#{previous_version})."
328
- end
329
- #case current_version
330
- #when 'major'
331
- # v = previous_verison.split(/\W/)
332
- # v[0] = v[0].succ
333
- # current_version = v.join('.')
334
- #when 'minor'
335
- # v = previous_verison.split(/\W/)
336
- # v[1] = v[1].succ
337
- # current_version = v.join('.')
338
- # end
339
- #end
340
- rels << [current_version, current_release || Time.now]
341
- # make sure all release date are Time objects
342
- rels = rels.collect{ |v,d| [v, Time===d ? d : Time.parse(d)] }
343
- # only uniq releases
344
- rels = rels.uniq
345
- # sort by release date
346
- rels = rels.to_a.sort{ |a,b| a[1] <=> b[1] }
347
- # organize into deltas
348
- deltas, last = [], nil
349
- rels.each do |rel|
350
- deltas << [last, rel]
351
- last = rel
352
- end
353
- # gather changes for each delta and build log
354
- deltas.each do |gt, lt|
355
- if gt
356
- gt_vers, gt_date = *gt
357
- lt_vers, lt_date = *lt
358
- #gt_date = Time.parse(gt_date) unless Time===gt_date
359
- #lt_date = Time.parse(lt_date) unless Time===lt_date
360
- changes = after(gt_date).before(lt_date)
361
- else
362
- lt_vers, lt_date = *lt
363
- #lt_date = Time.parse(lt_date) unless Time===lt_date
364
- changes = before(lt_date)
365
- end
366
- reltext = changes.format_rel_types(rev)
367
- unless reltext.strip.empty?
368
- log << "#{marker} #{lt_vers} / #{lt_date.strftime('%Y-%m-%d')}\n\n#{reltext}"
369
- end
370
- end
371
- # reverse log order and make into document
372
- marker[0,1] + " #{title}\n\n" + log.reverse.join("\n")
373
- end
374
-
375
- #
376
- def format_rel_types(rev=false)
377
- groups = changes.group_by{ |e| e.type_number }
378
- string = ""
379
- 5.times do |n|
380
- entries = groups[n]
381
- next if !entries
382
- next if entries.empty?
383
- string << "* #{entries.size} #{entries[0].label}\n\n"
384
- entries.sort!{|a,b| a.date <=> b.date }
385
- entries.each do |entry|
386
- #string << "== #{date} #{who}\n\n" # no email :(
387
- if rev
388
- text = "#{entry.message} (##{entry.revision})"
389
- else
390
- text = "#{entry.message}"
391
- end
392
- text = text.tabto(6)
393
- text[4] = '*'
394
- #entry = entry.join(' ').tabto(6)
395
- #entry[4] = '*'
396
- string << text
397
- string << "\n"
398
- end
399
- string << "\n"
400
- end
401
- string
402
- end
403
-
404
- #
405
- def releases(file)
406
- return [] unless file
407
- clog = File.read(file)
408
- tags = clog.scan(/^(==|##)(.*?)$/)
409
- rels = tags.collect do |t|
410
- parse_version_tag(t[1])
411
- end
412
- @marker = tags[0][0]
413
- return rels
414
- end
415
-
416
- #
417
- def parse_version_tag(tag)
418
- version, date = *tag.split('/')
419
- version, date = version.strip, date.strip
420
- return version, date
421
- end
422
- =end
183
+ # TODO: THIS IS HERE AS A REMINDER ABOUT TEH XSL TEMPLATE.
184
+ # WHAT TO DO WITH IT?
423
185
 
424
186
  =begin
425
187
  ###################