vclog 1.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.rdoc ADDED
@@ -0,0 +1,87 @@
1
+ = RELEASE HISTORY
2
+
3
+ == 1.4.0 / 2010-05-26
4
+
5
+ This release includes some basic improvments and a few bug fixes. The primary change you might encounter is the need to use -e or --extra in order to see the detailed Changes list in the Release History. Also changed 'git-log' to 'git log', as it seems the latest versions of git does not support the many executables any longer. SVN support requires xmlsimple library. Note also that SVN support is lack luster at this time becuase it hits the server every time an 'svn log' command is issued which is done once for each tag when a history is generated (any one know a better way?).
6
+
7
+ Changes:
8
+
9
+ * 1 Minor Enhancement
10
+
11
+ * Use -e or --extra to see Changes list in release history.
12
+ * Use xmlsimple for parsing SVN log output.
13
+ * Improve git log parsing with --pretty option.
14
+
15
+ * 2 Bug Fixes
16
+
17
+ * Sort release tags in correct order.
18
+ * Change 'git-log' to 'git log'.
19
+
20
+
21
+ == 1.3.0 / 2010-02-08
22
+
23
+ For the an end-user the only significant change is the support of 'label:' notation for commit labels. I have found that I am much more apt to use them if they come first in the commit message and that some developers already use the 'label:' notation to specify 'system module' effected --a useful system of labeling.
24
+
25
+ Changes:
26
+
27
+ * 1 Major Enhancement
28
+
29
+ * Support 'label:' fromat commit types
30
+
31
+ * 2 Implementation Enhancements
32
+
33
+ * Adjust location of plugins for latest version of Plugin gem.
34
+ * Use Erb as template system for all formats.
35
+
36
+ * 1 Bug Fix
37
+
38
+ * Corrected error for --current and --bump commands.
39
+
40
+
41
+ == 1.2 / 2009-10-26
42
+
43
+ Version 1.2 overhuals the internals so that History output is based on scm tags, not on a pre-existing history file. This is really the proper way to go about it and those who use it will, I think, be happily surprised at how it promotes good practices for the maintenance of History files. This overhaul led to substantial changes in the command-line interface.
44
+
45
+ Changes:
46
+
47
+ * 2 Major Enhancements
48
+
49
+ * Rewrote History class.
50
+ * Changed command-line interface.
51
+
52
+
53
+ == 1.1 / 2009-10-23
54
+
55
+ This release adds yaml and json formats an improves
56
+ the command.
57
+
58
+ Changes:
59
+
60
+ * 2 Major Enhancements
61
+
62
+ * Added YAML format.
63
+ * Added JSON format.
64
+
65
+ * 1 Minor Enhancements
66
+
67
+ * Use OptionParser instead of GetoptLong.
68
+
69
+
70
+ == 1.0.0 / 2009-10-13
71
+
72
+ This is the first "production" release of VCLog.
73
+
74
+ * 2 Major Enhancements
75
+
76
+ * Improved command line interface.
77
+ * Added output option to save changelog.
78
+
79
+
80
+ == 0.1.0 / 2009-08-17
81
+
82
+ This is the initial version of vclog.
83
+
84
+ * 1 Major Enhancement
85
+
86
+ * Happy Birthday
87
+
data/PROFILE ADDED
@@ -0,0 +1,17 @@
1
+ ---
2
+ title : VCLog
3
+ summary : Cross-VCS/SCM ChangeLog Generator
4
+ copyright: Copyright (c) 2009 Thomas Sawyer
5
+ license : GPL3
6
+ suite : proutils
7
+ authors : Thomas Sawyer
8
+ created : 2006-05-09
9
+ contact : http://googlegroups.com/group/proutils
10
+
11
+ description:
12
+ VCLog is a cross-VCS/SCM ChangeLog generator.
13
+
14
+ resources:
15
+ homepage: http://proutils.rubyforge.org/vclog
16
+ repository: git://github.com/proutils/vclog.git
17
+
File without changes
data/REQUIRE ADDED
@@ -0,0 +1,9 @@
1
+ runtime:
2
+ - facets >2.4
3
+
4
+ development:
5
+ - syckle
6
+
7
+ development/test:
8
+ - cucumber
9
+
@@ -1,22 +1,5 @@
1
1
  = TODO
2
2
 
3
- == Support Markdown and RDoc release output styles
4
-
5
- Right now its all RDoc.
6
-
7
- == Imporved parsing flexability
8
-
9
- In general parsing hueristics need to be imporved. Some specifics:
10
-
11
- * Need to support relase comments.
12
- * Need to recognize "Changes:" marker
13
-
14
-
15
- == Typed option needs work
16
-
17
- It produced no results sometimes. Fix or deprecate.
18
-
19
-
20
3
  == Automagical Version
21
4
 
22
5
  Would be cool if it could also generate an automagical version number.
data/VERSION ADDED
@@ -0,0 +1,5 @@
1
+ name : vclog
2
+ major: 1
3
+ minor: 4
4
+ patch: 0
5
+ date : 2010-05-26
data/bin/vclog CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- load 'vclog/cli'
2
+ require 'vclog/cli'
3
3
  VCLog.run
4
4
 
@@ -0,0 +1,16 @@
1
+ Feature: Release History
2
+ As a SCM user
3
+ I want to generate a nicely formatted Release History
4
+
5
+ Scenario: SVN History
6
+ Given a SVN repository
7
+ When I generate a History
8
+ Then it should include all tags
9
+ And the list of releases should be in order from newest to oldest
10
+
11
+ Scenario: Git History
12
+ Given a Git repository
13
+ When I generate a History
14
+ Then it should include all tags
15
+ And the list of releases should be in order from newest to oldest
16
+
@@ -0,0 +1,29 @@
1
+ Given /^a SVN repository/ do
2
+ @directory = File.dirname(__FILE__) + '/../../test/fixtures/tzinfo'
3
+ @tag_numbers = Dir["@directory/tags/*"].map{ |d| File.basename(d) }
4
+ end
5
+
6
+ # For git we will have to use the VCLog project itself, I guess.
7
+ Given /^a Git repository/ do
8
+ @directory = File.dirname(__FILE__) + '/../..' #/fixtures/git-repo'
9
+ tags1 = `cd #{@directory}; git tag -l "[0-9]*"`
10
+ tags2 = `cd #{@directory}; git tag -l "v[0-9]*"`
11
+ @tag_numbers = tags1.split("\n") + tags2.split("\n")
12
+ end
13
+
14
+ When /I generate a History/ do
15
+ @system = VCLog::VCS.factory(@directory)
16
+ @history = VCLog::History.new(@system)
17
+ end
18
+
19
+ Then /it should include all tags/ do
20
+ tags = @history.tags.map{ |t| t.name }
21
+ tags.sort.assert == @tag_numbers.sort
22
+ end
23
+
24
+ And /^the list of releases should be in order from newest to oldest/ do
25
+ rels_names = @history.releases.map{ |r| r.tag.name }
26
+ rels_names.shift # remove imaginary current tag
27
+ rels_names.assert == @tag_numbers.sort.reverse
28
+ end
29
+
@@ -0,0 +1 @@
1
+ require 'ae'
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift( File.dirname(__FILE__) + '/../../lib' )
2
+ require 'vclog'
@@ -0,0 +1,194 @@
1
+ module Syckle::Plugins
2
+
3
+ # VClog service generates changelogs from
4
+ # SCM commit messages.
5
+ #
6
+ class VClog < Service
7
+
8
+ cycle :main, :document
9
+
10
+ #available do |project|
11
+ # begin
12
+ # require 'vclog/vcs'
13
+ # true
14
+ # rescue LoadError
15
+ # false
16
+ # end
17
+ #end
18
+
19
+ # Current version of project.
20
+ attr_accessor :version
21
+
22
+ # Changelog format. Default is +html+.
23
+ # Supports +html+, +xml+, +json+, +yaml+, +rdoc+, +markdown+, and +gnu+.
24
+ attr_accessor :format
25
+
26
+ # Changelog layout type (+log+ or +rel+). Default is +log+.
27
+ attr_accessor :type
28
+
29
+ # Output file to store changelog.
30
+ # The defualt is 'log/vclog/changelog.{format}'.
31
+ attr_accessor :output
32
+
33
+ # Show revision numbers (true/false)?
34
+ attr_accessor :rev
35
+
36
+ # Some formats, such as +rdoc+, use a title field. Defaults to project title.
37
+ attr_accessor :title
38
+
39
+ # Some formats can reference an optional stylesheet (namely +xml+ and +html+).
40
+ attr_accessor :style
41
+
42
+ #
43
+ def initialize_defaults
44
+ require 'vclog/vcs'
45
+ @version = metadata.version
46
+ @title = metadata.title
47
+ @format = 'html'
48
+ @type = 'log'
49
+ end
50
+
51
+ #
52
+ def valid?
53
+ return false unless format =~ /^(html|yaml|json|xml|rdoc|markdown|gnu|txt)$/
54
+ return false unless type =~ /^(log|rel|history|changelog)$/
55
+ return true
56
+ end
57
+
58
+ #
59
+ def format=(f)
60
+ @format = f.to_s.downcase
61
+ end
62
+
63
+ #
64
+ def type=(f)
65
+ @type = f.to_s.downcase
66
+ end
67
+
68
+ # Generate changelog.
69
+ def document
70
+ document_changelog
71
+ end
72
+
73
+ #++
74
+ # TODO: apply_naming_policy ?
75
+ #--
76
+
77
+ def document_changelog
78
+ case type
79
+ when 'rel', 'history'
80
+ file = output || (project.log + "vclog/history.#{format}").to_s
81
+ else
82
+ file = output || (project.log + "vclog/changelog.#{format}").to_s
83
+ end
84
+ #apply_naming_policy('changelog', log_format.downcase)
85
+ if dryrun?
86
+ report "# vclog --#{type} --#{format} -o #{file}"
87
+ else
88
+ changed = save(file)
89
+ if changed
90
+ report "Updated #{relative_from_root(file)}"
91
+ else
92
+ report "#{relative_from_root(file)} is current"
93
+ end
94
+ end
95
+ end
96
+
97
+ # Save changelog/history to +output+ file.
98
+ def save(output)
99
+ text = render
100
+ if File.exist?(output)
101
+ if File.read(output) != text
102
+ File.open(output, 'w'){ |f| f << text }
103
+ true
104
+ else
105
+ false
106
+ end
107
+ else
108
+ dir = File.dirname(output)
109
+ mkdir_p(dir) unless File.exist?(dir)
110
+ File.open(output, 'w'){ |f| f << text }
111
+ end
112
+ end
113
+
114
+ # Returns changelog or history depending on type selection.
115
+ def log
116
+ @log ||= (
117
+ case type
118
+ when 'log', 'changelog'
119
+ log = vcs.changelog
120
+ when 'rel', 'history'
121
+ log = vcs.history(:title=>title, :version=>version)
122
+ else
123
+ log = vcs.changelog
124
+ end
125
+ )
126
+ end
127
+
128
+ # Access to version control system.
129
+ def vcs
130
+ #@vcs ||= VCLog::VCS.new #(self)
131
+ @vcs ||= VCLog::VCS.factory #(root)
132
+ end
133
+
134
+ # Convert log to desiered format.
135
+ def render
136
+ case format
137
+ when 'xml'
138
+ txt = log.to_xml(style) # xsl stylesheet url
139
+ when 'html'
140
+ txt = log.to_html(style) # css stylesheet url
141
+ when 'yaml'
142
+ txt = log.to_yaml
143
+ when 'json'
144
+ txt = log.to_json
145
+ when 'markdown'
146
+ txt = log.to_markdown(rev)
147
+ when 'rdoc'
148
+ txt = log.to_rdoc(rev)
149
+ else #:gnu
150
+ txt = log.to_gnu(rev)
151
+ end
152
+ txt
153
+ end
154
+
155
+
156
+ =begin
157
+ #
158
+ def document_public_changelog
159
+ if output
160
+ file = project.root + output
161
+ else
162
+ file = project.root.glob_first("{CHANGES,CHANGELOG}{.txt,}", :casefold)
163
+ end
164
+
165
+ if file
166
+ #file = (project.root + file).to_s
167
+ if dryrun?
168
+ report "vclog > #{file}"
169
+ else
170
+ public_changelog = typed ? changelog.typed : changelog
171
+ if layout == 'rel'
172
+ changed = public_changelog.save(file.to_s, :rel, metadata.version, metadata.release)
173
+ else
174
+ changed = public_changelog.save(file.to_s, :gnu)
175
+ end
176
+ if changed
177
+ report "Updated #{relative_from_root(file)}"
178
+ else
179
+ report "#{relative_from_root(file)} is current"
180
+ end
181
+ end
182
+ end
183
+ end
184
+ =end
185
+
186
+ #
187
+ def relative_from_root(path)
188
+ Pathname.new(path).relative_path_from(project.root)
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+
@@ -15,6 +15,8 @@ module VCLog
15
15
 
16
16
  include Enumerable
17
17
 
18
+ DIR = File.dirname(__FILE__)
19
+
18
20
  DAY = 24*60*60
19
21
 
20
22
  attr :changes
@@ -124,46 +126,91 @@ module VCLog
124
126
  # mapped
125
127
  #end
126
128
 
127
- ##################
128
- # Output Formats #
129
- ##################
129
+ # O U T P U T F O R M A T S
130
+
131
+ #
132
+
133
+ # def to_gnu(rev=false)
134
+ # x = []
135
+ # by_date.each do |date, date_changes|
136
+ # date_changes.by_author.each do |author, author_changes|
137
+ # x << %[#{date} #{author}\n]
138
+ # #author_changes = author_changes.sort{|a,b| b.date <=> a.date}
139
+ # author_changes.each do |entry|
140
+ # if entry.type
141
+ # msg = "#{entry.message} [#{entry.type}]".tabto(10)
142
+ # else
143
+ # msg = "#{entry.message}".tabto(10)
144
+ # end
145
+ # msg << " (#{entry.revision})" if rev
146
+ # msg[8] = '*'
147
+ # x << msg
148
+ # end
149
+ # end
150
+ # x << "\n"
151
+ # end
152
+ # return x.join("\n")
153
+ # end
154
+
155
+ #
156
+
157
+ def to_gnu(rev=false)
158
+ tmp = File.read(File.join(DIR, 'templates', 'changelog.gnu'))
159
+ erb = ERB.new(tmp)
160
+ erb.result(binding)
161
+ end
162
+
163
+ #
130
164
 
131
165
  def to_yaml
132
166
  require 'yaml'
133
167
  changes.to_yaml
134
168
  end
135
169
 
170
+ #
171
+
136
172
  def to_json
137
173
  require 'json'
138
174
  changes.to_json
139
175
  end
140
176
 
141
177
  #
142
- def to_gnu(rev=false)
143
- x = []
144
- by_date.each do |date, date_changes|
145
- date_changes.by_author.each do |author, author_changes|
146
- x << %[#{date} #{author}\n]
147
- #author_changes = author_changes.sort{|a,b| b.date <=> a.date}
148
- author_changes.each do |entry|
149
- if entry.type
150
- msg = "#{entry.message} [#{entry.type}]".tabto(10)
151
- else
152
- msg = "#{entry.message}".tabto(10)
153
- end
154
- msg << " (#{entry.revision})" if rev
155
- msg[8] = '*'
156
- x << msg
157
- end
158
- end
159
- x << "\n"
160
- end
161
- return x.join("\n")
178
+ alias_method :to_s, :to_gnu
179
+
180
+ # Translate changelog into a XML document.
181
+
182
+ def to_xml(xsl=nil)
183
+ tmp = File.read(File.join(DIR, 'templates', 'changelog.xml'))
184
+ erb = ERB.new(tmp)
185
+ erb.result(binding)
162
186
  end
163
187
 
164
- #
165
- alias_method :to_s, :to_gnu
188
+ # Create an HTML formated changelog.
189
+ # +css+ reference defaults to 'log.css'
166
190
 
191
+ def to_html(css=nil)
192
+ tmp = File.read(File.join(DIR, 'templates', 'changelog.html'))
193
+ erb = ERB.new(tmp)
194
+ erb.result(binding)
195
+ end
196
+
197
+ # Translate history into a RDoc formatted document.
198
+
199
+ def to_rdoc(rev=false)
200
+ tmp = File.read(File.join(DIR, 'templates', 'changelog.rdoc'))
201
+ erb = ERB.new(tmp)
202
+ erb.result(binding)
203
+ end
204
+
205
+ # Translate history into a Markdown formatted document.
206
+
207
+ def to_markdown(rev=false)
208
+ tmp = File.read(File.join(DIR, 'templates', 'changelog.markdown'))
209
+ erb = ERB.new(tmp)
210
+ erb.result(binding)
211
+ end
212
+
213
+ =begin
167
214
  # Create an XML formated changelog.
168
215
  # +xsl+ reference defaults to 'log.xsl'
169
216
  def to_xml(xsl=nil)
@@ -184,9 +231,9 @@ module VCLog
184
231
  x << %[</log>]
185
232
  return x.join("\n")
186
233
  end
234
+ =end
187
235
 
188
- # Create an HTML formated changelog.
189
- # +css+ reference defaults to 'log.css'
236
+ =begin
190
237
  def to_html(css=nil)
191
238
  css = 'log.css' if css.nil?
192
239
  x = []
@@ -195,7 +242,7 @@ module VCLog
195
242
  x << %[ <title>ChangeLog</title>]
196
243
  x << %[ <style>]
197
244
  x << %[ body{font-family: sans-serif;}]
198
- x << %[ #changelog{width:800px;margin:0 auto;}]
245
+ x << %[ .changelog{width:800px;margin:0 auto;}]
199
246
  x << %[ li{padding: 10px;}]
200
247
  x << %[ .date{font-weight: bold; color: gray; float: left; padding: 0 5px;}]
201
248
  x << %[ .author{color: red;}]
@@ -205,7 +252,7 @@ module VCLog
205
252
  x << %[ <link rel="stylesheet" href="#{css}" type="text/css">] if css
206
253
  x << %[</head>]
207
254
  x << %[<body>]
208
- x << %[ <div id="changelog">]
255
+ x << %[ <div class="changelog">]
209
256
  x << %[ <h1>ChangeLog</h1>]
210
257
  x << %[ <ul class="log">]
211
258
  changes.sort{|a,b| b.date <=> a.date}.each do |entry|
@@ -223,61 +270,20 @@ module VCLog
223
270
  x << %[</html>]
224
271
  return x.join("\n")
225
272
  end
226
-
227
-
228
- # Translate history into a Markdown formatted document.
229
- def to_markdown(rev=false)
230
- to_markup('#', rev)
231
- end
232
-
233
- # Translate history into a RDoc formatted document.
234
- def to_rdoc(rev=false)
235
- to_markup('=', rev)
236
- end
237
-
238
- #
239
- def to_markup(marker, rev=false)
240
-
241
- x = []
242
- by_date.each do |date, date_changes|
243
- date_changes.by_author.each do |author, author_changes|
244
- x << "#{marker}#{marker} #{date} #{author}\n"
245
- x << to_markup_changes(author_changes, rev)
246
- end
247
- x << ""
248
- end
249
- marker + " #{title}\n\n" + x.join("\n")
250
- end
273
+ =end
251
274
 
252
275
  private
253
276
 
254
277
  #
255
- def to_markup_changes(changes, rev=false)
256
- groups = changes.group_by{ |e| e.type_number }
257
- string = ""
258
- 5.times do |n|
259
- entries = groups[n]
260
- next if !entries
261
- next if entries.empty?
262
- string << "* #{entries.size} #{entries[0].type_phrase}\n\n"
263
- entries.sort!{|a,b| a.date <=> b.date }
264
- entries.each do |entry|
265
- #string << "#{marker}#{marker} #{entry.date} #{entry.author}\n\n" # no email :(
266
- if rev
267
- text = "#{entry.message} (##{entry.revision})"
268
- else
269
- text = "#{entry.message}"
270
- end
271
- text = text.tabto(6)
272
- text[4] = '*'
273
- #entry = entry.join(' ').tabto(6)
274
- #entry[4] = '*'
275
- string << text
276
- string << "\n"
277
- end
278
- string << "\n"
279
- end
280
- string.chomp("\n")
278
+ def h(input)
279
+ result = input.to_s.dup
280
+ result.gsub!("&", "&amp;")
281
+ result.gsub!("<", "&lt;")
282
+ result.gsub!(">", "&gt;")
283
+ result.gsub!("'", "&apos;")
284
+ #result.gsub!("@", "&at;")
285
+ result.gsub!("\"", "&quot;")
286
+ return result
281
287
  end
282
288
 
283
289
  end
@@ -434,20 +440,6 @@ end
434
440
  end if different
435
441
  end
436
442
 
437
- private
438
-
439
- #
440
- def escxml(input)
441
- result = input.to_s.dup
442
- result.gsub!("&", "&amp;")
443
- result.gsub!("<", "&lt;")
444
- result.gsub!(">", "&gt;")
445
- result.gsub!("'", "&apos;")
446
- #result.gsub!("@", "&at;")
447
- result.gsub!("\"", "&quot;")
448
- return result
449
- end
450
-
451
443
  #
452
444
  def save_xsl(file)
453
445
  #xslfile = file.chomp(File.extname(file)) + '.xsl'
@@ -459,42 +451,5 @@ end
459
451
  end
460
452
  end
461
453
  end
462
-
463
-
464
- DEFAULT_LOG_XSL = <<-END.tabto(0)
465
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
466
-
467
- <xsl:output cdata-section-elements="script"/>
468
-
469
- <xsl:template match="/">
470
- <html>
471
- <head>
472
- <title>Changelog</title>
473
- <link REL='SHORTCUT ICON' HREF="../img/ruby-sm.png" />
474
- <style>
475
- td { font-family: sans-serif; padding: 0px 10px; }
476
- </style>
477
- </head>
478
- <body>
479
- <div class="container">
480
- <h1>Changelog</h1>
481
- <table style="width: 100%;">
482
- <xsl:apply-templates />
483
- </table>
484
- </div>
485
- </body>
486
- </html>
487
- </xsl:template>
488
-
489
- <xsl:template match="entry">
490
- <tr>
491
- <td><b><pre><xsl:value-of select="message"/></pre></b></td>
492
- <td><xsl:value-of select="author"/></td>
493
- <td><xsl:value-of select="date"/></td>
494
- </tr>
495
- </xsl:template>
496
-
497
- </xsl:stylesheet>
498
- END
499
454
  =end
500
455