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.
- data/.ruby +4 -3
- data/.yardopts +7 -0
- data/HISTORY.rdoc +207 -0
- data/README.rdoc +44 -27
- data/bin/vclog +4 -2
- data/bin/vclog-autotag +6 -0
- data/bin/vclog-bump +6 -0
- data/bin/vclog-formats +6 -0
- data/bin/vclog-version +6 -0
- data/lib/vclog.rb +1 -1
- data/lib/vclog.yml +58 -0
- data/lib/vclog/adapters.rb +2 -1
- data/lib/vclog/adapters/abstract.rb +87 -232
- data/lib/vclog/adapters/darcs.rb +72 -67
- data/lib/vclog/adapters/git.rb +166 -140
- data/lib/vclog/adapters/hg.rb +98 -62
- data/lib/vclog/adapters/svn.rb +116 -113
- data/lib/vclog/change.rb +110 -81
- data/lib/vclog/change_point.rb +77 -0
- data/lib/vclog/changelog.rb +58 -296
- data/lib/vclog/cli.rb +6 -70
- data/lib/vclog/cli/abstract.rb +64 -81
- data/lib/vclog/cli/autotag.rb +1 -3
- data/lib/vclog/cli/bump.rb +3 -4
- data/lib/vclog/cli/formats.rb +4 -4
- data/lib/vclog/cli/log.rb +86 -0
- data/lib/vclog/cli/version.rb +3 -3
- data/lib/vclog/{facets.rb → core_ext.rb} +0 -0
- data/lib/vclog/heuristics.rb +112 -38
- data/lib/vclog/heuristics/rule.rb +52 -12
- data/lib/vclog/heuristics/{label.rb → type.rb} +2 -2
- data/lib/vclog/history_file.rb +2 -2
- data/lib/vclog/metadata.rb +13 -1
- data/lib/vclog/release.rb +26 -12
- data/lib/vclog/repo.rb +191 -27
- data/lib/vclog/report.rb +187 -0
- data/lib/vclog/tag.rb +66 -39
- data/lib/vclog/templates/changelog.ansi.rb +9 -26
- data/lib/vclog/templates/changelog.atom.erb +3 -3
- data/lib/vclog/templates/changelog.gnu.rb +4 -11
- data/lib/vclog/templates/changelog.html.erb +11 -2
- data/lib/vclog/templates/changelog.markdown.rb +4 -4
- data/lib/vclog/templates/changelog.rdoc.rb +4 -4
- data/lib/vclog/templates/changelog.rss.erb +2 -6
- data/lib/vclog/templates/changelog.xml.erb +14 -2
- data/lib/vclog/templates/history.ansi.rb +10 -17
- data/lib/vclog/templates/history.atom.erb +4 -4
- data/lib/vclog/templates/history.gnu.rb +5 -7
- data/lib/vclog/templates/history.html.erb +11 -4
- data/lib/vclog/templates/history.json.rb +1 -1
- data/lib/vclog/templates/history.markdown.rb +5 -7
- data/lib/vclog/templates/history.rdoc.rb +5 -9
- data/lib/vclog/templates/history.rss.erb +3 -5
- data/lib/vclog/templates/history.xml.erb +15 -3
- data/lib/vclog/templates/history.yaml.rb +1 -1
- data/man/man1/vclog-autotag.1 +1 -1
- data/man/man1/vclog-autotag.1.html +1 -1
- data/man/man1/vclog-bump.1 +1 -1
- data/man/man1/vclog-bump.1.html +1 -1
- data/man/man1/vclog-version.1 +1 -1
- data/man/man1/vclog-version.1.html +1 -1
- data/man/man1/vclog.1 +25 -13
- data/man/man1/vclog.1.html +29 -20
- data/man/man1/vclog.1.ronn +31 -18
- data/test/unit/case_metadata.rb +1 -1
- metadata +48 -34
- data/lib/vclog/cli/changelog.rb +0 -33
- data/lib/vclog/cli/help.rb +0 -42
- data/lib/vclog/cli/history.rb +0 -39
- data/lib/vclog/formatter.rb +0 -123
- data/lib/vclog/history.rb +0 -131
- data/lib/vclog/kernel.rb +0 -12
- data/man/man1/vclog-changelog.1 +0 -47
- data/man/man1/vclog-changelog.1.html +0 -123
- data/man/man1/vclog-changelog.1.ronn +0 -39
- data/man/man1/vclog-history.1 +0 -44
- data/man/man1/vclog-history.1.html +0 -122
- data/man/man1/vclog-history.1.ronn +0 -38
data/lib/vclog/adapters.rb
CHANGED
@@ -1,276 +1,131 @@
|
|
1
1
|
module VCLog
|
2
|
-
module Adapters
|
3
2
|
|
4
|
-
|
5
|
-
require 'pathname'
|
6
|
-
require 'tempfile'
|
3
|
+
module Adapters
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
require 'vclog/change'
|
12
|
-
require 'vclog/tag'
|
5
|
+
require 'time'
|
6
|
+
require 'pathname'
|
7
|
+
require 'tempfile'
|
13
8
|
|
14
|
-
|
15
|
-
|
9
|
+
require 'vclog/changelog'
|
10
|
+
require 'vclog/change'
|
11
|
+
require 'vclog/tag'
|
16
12
|
|
17
|
-
|
18
|
-
class Abstract
|
13
|
+
# TODO: Could we support a "no scm" changelog based on `LOG:` entries in source files?
|
19
14
|
|
20
|
-
#
|
21
|
-
attr :config
|
22
|
-
|
23
|
-
# Root location.
|
24
|
-
attr :root
|
25
|
-
|
26
|
-
# Heuristics object.
|
27
|
-
attr :heuristics
|
28
|
-
|
29
|
-
# Minimum change level.
|
30
|
-
attr :level
|
15
|
+
# TODO: Possibly use Amp or SCM gem for future version.
|
31
16
|
|
17
|
+
# Abstract base class for all version control system adapters.
|
32
18
|
#
|
33
|
-
|
34
|
-
@repo = repo
|
19
|
+
class Abstract
|
35
20
|
|
36
|
-
|
37
|
-
|
38
|
-
@level = repo.level
|
21
|
+
#
|
22
|
+
attr :config
|
39
23
|
|
40
|
-
|
41
|
-
|
24
|
+
# Root location.
|
25
|
+
attr :root
|
42
26
|
|
43
|
-
|
44
|
-
|
45
|
-
def initialize_framework
|
46
|
-
end
|
27
|
+
# Heuristics object.
|
28
|
+
attr :heuristics
|
47
29
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
30
|
+
#
|
31
|
+
def initialize(repo)
|
32
|
+
@repo = repo
|
33
|
+
@root = repo.root
|
34
|
+
@heuristics = repo.heuristics
|
52
35
|
|
53
|
-
|
54
|
-
def extract_changes
|
55
|
-
raise "Not Implemented"
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
def tags
|
60
|
-
@tags ||= extract_tags
|
61
|
-
end
|
62
|
-
|
63
|
-
#
|
64
|
-
# TODO: possbile to move heuristics lookup into Change class?
|
65
|
-
def changes
|
66
|
-
@changes ||= all_changes.select do |c|
|
67
|
-
c.level >= self.level
|
36
|
+
initialize_framework
|
68
37
|
end
|
69
|
-
end
|
70
38
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
changes = []
|
75
|
-
extract_changes.each do |change|
|
76
|
-
#raise "how did this happen?" if Change == c
|
77
|
-
#rev, date, who, msg = *c
|
78
|
-
#type, level, label, nmsg = *heuristics.lookup(msg)
|
79
|
-
#Change.new(rev, date, who, nmsg||msg, type, level, label)
|
80
|
-
change.apply_heuristics(heuristics)
|
81
|
-
changes << change
|
82
|
-
end
|
83
|
-
changes
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
#
|
88
|
-
def tag?(name)
|
89
|
-
tags.find{ |t| t.name == name }
|
90
|
-
end
|
91
|
-
|
92
|
-
#
|
93
|
-
def changelog
|
94
|
-
ChangeLog.new(changes)
|
95
|
-
end
|
96
|
-
|
97
|
-
#
|
98
|
-
def history
|
99
|
-
@history ||= History.new(self)
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
|
-
def display(type, format, options)
|
104
|
-
@options = options
|
105
|
-
formatter = Formatter.new(self)
|
106
|
-
formatter.display(type, format, options)
|
107
|
-
end
|
108
|
-
|
109
|
-
# TODO: allow config of these levels thresholds ?
|
110
|
-
def bump
|
111
|
-
max = history.releases[0].changes.map{ |c| c.level }.max
|
112
|
-
if max > 1
|
113
|
-
bump_part('major')
|
114
|
-
elsif max >= 0
|
115
|
-
bump_part('minor')
|
116
|
-
else
|
117
|
-
bump_part('patch')
|
39
|
+
# This is used if the adapter is using an external library
|
40
|
+
# to interface with the repository.
|
41
|
+
def initialize_framework
|
118
42
|
end
|
119
|
-
end
|
120
43
|
|
121
|
-
|
122
|
-
|
123
|
-
|
44
|
+
#
|
45
|
+
def extract_tags
|
46
|
+
raise "Not Implemented"
|
47
|
+
end
|
124
48
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
else
|
129
|
-
v = '0.0.0'
|
49
|
+
#
|
50
|
+
def extract_changes
|
51
|
+
raise "Not Implemented"
|
130
52
|
end
|
131
53
|
|
132
|
-
|
54
|
+
#
|
55
|
+
def tags
|
56
|
+
@tags ||= extract_tags
|
57
|
+
end
|
133
58
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
(1..(v.size-1)).each{ |i| v[i] = '0' }
|
138
|
-
v.join('.')
|
139
|
-
when 'minor'
|
140
|
-
v[1] = '0' unless v[1]
|
141
|
-
v[1] = v[1].succ
|
142
|
-
(2..(v.size-1)).each{ |i| v[i] = '0' }
|
143
|
-
v.join('.')
|
144
|
-
when 'patch'
|
145
|
-
v[1] = '0' unless v[1]
|
146
|
-
v[2] = '0' unless v[2]
|
147
|
-
v[2] = v[2].succ
|
148
|
-
(3..(v.size-1)).each{ |i| v[i] = '0' }
|
149
|
-
v.join('.')
|
150
|
-
else
|
151
|
-
v[-1] = '0' unless v[-1]
|
152
|
-
v[-1] = v[-1].succ
|
153
|
-
v.join('.')
|
59
|
+
#
|
60
|
+
def changes
|
61
|
+
@changes ||= extract_changes
|
154
62
|
end
|
155
|
-
end
|
156
63
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
else
|
163
|
-
v = '0.0.0'
|
64
|
+
#
|
65
|
+
def change_points
|
66
|
+
@change_points ||= (
|
67
|
+
changes.inject([]){ |list, change| list.concat(change.points); list }
|
68
|
+
)
|
164
69
|
end
|
165
|
-
return v
|
166
|
-
end
|
167
|
-
|
168
|
-
# Return the latest commit as of a given date.
|
169
|
-
def change_by_date(date)
|
170
|
-
list = all_changes.select{ |c| c.date <= date }
|
171
|
-
list.sort_by{ |c| c.date }.last
|
172
|
-
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
#
|
177
|
-
def version_tag?(tag_name)
|
178
|
-
/(v|\d)/i =~ tag_name
|
179
|
-
end
|
180
70
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
File.open(mfile.path, 'w'){ |f| f << content }
|
185
|
-
mfile.path
|
186
|
-
end
|
187
|
-
|
188
|
-
=begin
|
189
|
-
# Looks for a "[type]" indicator at the end of the commit message.
|
190
|
-
# If that is not found, it looks at front of message for
|
191
|
-
# "[type]" or "[type]:". Failing that it tries just "type:".
|
192
|
-
#
|
193
|
-
def split_type(note)
|
194
|
-
note = note.strip
|
195
|
-
if md = /\[(.*?)\]\Z/.match(note)
|
196
|
-
t = md[1].strip.downcase
|
197
|
-
n = note[0...(md.begin(0))]
|
198
|
-
elsif md = /\A\[(.*?)\]\:?/.match(note)
|
199
|
-
t = md[1].strip.downcase
|
200
|
-
n = note[md.end(0)..-1]
|
201
|
-
elsif md = /\A(\w+?)\:/.match(note)
|
202
|
-
t = md[1].strip.downcase
|
203
|
-
n = note[md.end(0)..-1]
|
204
|
-
else
|
205
|
-
n, t = note, nil
|
71
|
+
#
|
72
|
+
def tag?(name)
|
73
|
+
tags.find{ |t| t.name == name }
|
206
74
|
end
|
207
|
-
n.gsub!(/^\s*?\n/m,'') # remove blank lines
|
208
|
-
return n, t
|
209
|
-
end
|
210
|
-
=end
|
211
|
-
|
212
|
-
=begin
|
213
|
-
# Write the ChangeLog to file.
|
214
75
|
|
215
|
-
|
216
|
-
|
217
|
-
|
76
|
+
# Returns the current verion string.
|
77
|
+
def version
|
78
|
+
if tags.last
|
79
|
+
v = tags[-1].name # TODO: ensure the latest version
|
80
|
+
v = tags[-2].name if v == 'HEAD'
|
81
|
+
else
|
82
|
+
v = '0.0.0'
|
83
|
+
end
|
84
|
+
return v
|
218
85
|
end
|
219
|
-
File.open(file,'w+'){ |f| f << log }
|
220
|
-
puts "Change log written to #{file}."
|
221
|
-
end
|
222
86
|
|
223
|
-
|
87
|
+
# Return the latest commit as of a given date.
|
88
|
+
def change_by_date(date)
|
89
|
+
list = changes.select{ |c| c.date <= date }
|
90
|
+
list.sort_by{ |c| c.date }.last
|
91
|
+
end
|
224
92
|
|
225
|
-
|
226
|
-
|
227
|
-
|
93
|
+
# Fallback for user is `ENV['USER']`.
|
94
|
+
def user
|
95
|
+
ENV['USER']
|
228
96
|
end
|
229
|
-
File.open(file,'w'){ |f| f << stamp }
|
230
|
-
puts "#{file} saved."
|
231
|
-
end
|
232
97
|
|
233
|
-
|
98
|
+
# Fallback for email address is `ENV['EMAIL']`.
|
99
|
+
def email
|
100
|
+
ENV['EMAIL']
|
101
|
+
end
|
234
102
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
else
|
239
|
-
date = Time.now.strftime("%Y-%m-%d")
|
103
|
+
#
|
104
|
+
def repository
|
105
|
+
nil
|
240
106
|
end
|
241
|
-
status = nil if status.to_s.strip.empty?
|
242
|
-
stamp = []
|
243
|
-
stamp << version
|
244
|
-
stamp << status if status
|
245
|
-
stamp << "(#{date})"
|
246
|
-
stamp.join(' ')
|
247
|
-
end
|
248
|
-
=end
|
249
107
|
|
250
|
-
|
108
|
+
#
|
109
|
+
def uuid
|
110
|
+
nil
|
111
|
+
end
|
251
112
|
|
252
|
-
|
253
|
-
def user
|
254
|
-
ENV['USER']
|
255
|
-
end
|
113
|
+
private
|
256
114
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
115
|
+
#
|
116
|
+
def version_tag?(tag_name)
|
117
|
+
/(v|\d)/i =~ tag_name
|
118
|
+
end
|
261
119
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
120
|
+
#
|
121
|
+
def tempfile(name, content)
|
122
|
+
mfile = Tempfile.new(name)
|
123
|
+
File.open(mfile.path, 'w'){ |f| f << content }
|
124
|
+
mfile.path
|
125
|
+
end
|
266
126
|
|
267
|
-
#
|
268
|
-
def uuid
|
269
|
-
nil
|
270
127
|
end
|
271
128
|
|
272
129
|
end
|
273
130
|
|
274
131
|
end
|
275
|
-
end
|
276
|
-
|
data/lib/vclog/adapters/darcs.rb
CHANGED
@@ -1,88 +1,93 @@
|
|
1
1
|
require 'vclog/adapters/abstract'
|
2
2
|
|
3
3
|
module VCLog
|
4
|
-
module Adapters
|
5
|
-
|
6
|
-
# = Darcs
|
7
|
-
#
|
8
|
-
# Provide Darcs SCM revision tools.
|
9
|
-
#
|
10
|
-
# TODO: This needs to be fixed!!!!!!!
|
11
|
-
#
|
12
|
-
class Darcs < Abstract
|
13
|
-
|
14
|
-
# Is a darcs repository?
|
15
|
-
def repository?
|
16
|
-
File.directory?('_darcs')
|
17
|
-
end
|
18
4
|
|
19
|
-
|
20
|
-
module_function :repository?
|
5
|
+
module Adapters
|
21
6
|
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
7
|
+
# Darcs SCM adapter.
|
8
|
+
#
|
9
|
+
# FIXME: This needs to be fixed!!!!!!!
|
10
|
+
#
|
11
|
+
class Darcs < Abstract
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
|
13
|
+
#
|
14
|
+
def initialize(*)
|
15
|
+
raise "Darcs is not yet supported. Please help us fix that!"
|
16
|
+
end
|
30
17
|
|
31
|
-
|
18
|
+
# Is a darcs repository?
|
19
|
+
def repository?
|
20
|
+
File.directory?('_darcs')
|
21
|
+
end
|
32
22
|
|
33
|
-
|
23
|
+
# This is also a module function.
|
24
|
+
module_function :repository?
|
34
25
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
when /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)/
|
39
|
-
when /^\s*tagged/
|
40
|
-
log << $'
|
41
|
-
log << "\n"
|
42
|
-
else
|
43
|
-
log << line
|
44
|
-
log << "\n"
|
45
|
-
end
|
26
|
+
# Cached Changelog.
|
27
|
+
def changelog
|
28
|
+
@changelog ||= generate_changelog
|
46
29
|
end
|
47
30
|
|
48
|
-
|
49
|
-
|
31
|
+
# Generate Changelog object.
|
32
|
+
def generate_changelog
|
33
|
+
raise "not a darcs repository" unless repository?
|
34
|
+
|
35
|
+
log = Changelog.new
|
36
|
+
|
37
|
+
txt = `darcs changes` #--repo=#{@repository}`
|
38
|
+
|
39
|
+
txt.each_line do |line|
|
40
|
+
case line
|
41
|
+
when /^\s*$/
|
42
|
+
when /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)/
|
43
|
+
when /^\s*tagged/
|
44
|
+
log << $'
|
45
|
+
log << "\n"
|
46
|
+
else
|
47
|
+
log << line
|
48
|
+
log << "\n"
|
49
|
+
end
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
52
|
+
return log
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrieve the "revision number" from the darcs tree.
|
56
|
+
def calculate_version
|
57
|
+
raise "not a darcs repository" unless repository?
|
58
|
+
|
59
|
+
status = info.status
|
60
|
+
|
61
|
+
changes = `darcs changes`
|
62
|
+
count = 0
|
63
|
+
tag = "0.0"
|
64
|
+
|
65
|
+
changes.each("\n\n") do |change|
|
66
|
+
head, title, desc = change.split("\n", 3)
|
67
|
+
if title =~ /^ \*/
|
68
|
+
# Normal change.
|
69
|
+
count += 1
|
70
|
+
elsif title =~ /tagged (.*)/
|
71
|
+
# Tag. We look for these.
|
72
|
+
tag = $1
|
73
|
+
break
|
74
|
+
else
|
75
|
+
warn "Unparsable change: #{change}"
|
76
|
+
end
|
72
77
|
end
|
78
|
+
ver = "#{tag}.#{count.to_s}"
|
79
|
+
|
80
|
+
return ver
|
81
|
+
#format_version_stamp(ver, status) # ,released)
|
73
82
|
end
|
74
|
-
ver = "#{tag}.#{count.to_s}"
|
75
83
|
|
76
|
-
|
77
|
-
|
78
|
-
|
84
|
+
# TODO
|
85
|
+
def tag(ref, label, msg)
|
86
|
+
`darcs tag #{label}`
|
87
|
+
end
|
79
88
|
|
80
|
-
# TODO
|
81
|
-
def tag(ref, label, msg)
|
82
|
-
`darcs tag #{label}`
|
83
89
|
end
|
84
90
|
|
85
91
|
end
|
86
92
|
|
87
93
|
end
|
88
|
-
end
|