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/git.rb
CHANGED
@@ -1,162 +1,188 @@
|
|
1
1
|
require 'vclog/adapters/abstract'
|
2
2
|
|
3
3
|
module VCLog
|
4
|
-
module Adapters
|
5
4
|
|
6
|
-
|
7
|
-
#
|
8
|
-
class Git < Abstract
|
5
|
+
module Adapters
|
9
6
|
|
10
|
-
|
11
|
-
|
7
|
+
# GIT Adapter.
|
8
|
+
#
|
9
|
+
class Git < Abstract
|
10
|
+
|
11
|
+
GIT_COMMIT_MARKER = '=====%n'
|
12
|
+
GIT_FIELD_MARKER = '-----%n'
|
13
|
+
|
14
|
+
RUBY_COMMIT_MARKER = "=====\n"
|
15
|
+
RUBY_FIELD_MARKER = "-----\n"
|
16
|
+
|
17
|
+
# Collect changes, i.e. commits.
|
18
|
+
def extract_changes
|
19
|
+
list = []
|
20
|
+
|
21
|
+
command = 'git log --name-only --pretty=format:"' +
|
22
|
+
GIT_COMMIT_MARKER +
|
23
|
+
'%ci' +
|
24
|
+
GIT_FIELD_MARKER +
|
25
|
+
'%aN' +
|
26
|
+
GIT_FIELD_MARKER +
|
27
|
+
'%H' +
|
28
|
+
GIT_FIELD_MARKER +
|
29
|
+
'%s%n%n%b' +
|
30
|
+
GIT_FIELD_MARKER +
|
31
|
+
'"'
|
32
|
+
|
33
|
+
changes = `#{command}`.split(RUBY_COMMIT_MARKER)
|
34
|
+
|
35
|
+
changes.shift # throw the first (empty) entry away
|
36
|
+
|
37
|
+
changes.each do |entry|
|
38
|
+
date, who, id, msg, files = entry.split(RUBY_FIELD_MARKER)
|
39
|
+
date = Time.parse(date)
|
40
|
+
files = files.split("\n")
|
41
|
+
list << Change.new(:id=>id, :date=>date, :who=>who, :msg=>msg, :files=>files)
|
42
|
+
end
|
43
|
+
|
44
|
+
return list
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
#def extract_files(change_list)
|
49
|
+
# change_list.each do |change|
|
50
|
+
# files = `git show --pretty="format:" --name-only #{c.id}`
|
51
|
+
# files = files.split("\n")
|
52
|
+
# change.files = files
|
53
|
+
# end
|
54
|
+
#end
|
55
|
+
|
56
|
+
# Collect tags.
|
57
|
+
#
|
58
|
+
# `git show 1.0` produces:
|
59
|
+
#
|
60
|
+
# tag 1.0
|
61
|
+
# Tagger: 7rans <transfire@gmail.com>
|
62
|
+
# Date: Sun Oct 25 09:27:58 2009 -0400
|
63
|
+
#
|
64
|
+
# version 1.0
|
65
|
+
# commit
|
66
|
+
# ...
|
67
|
+
#
|
68
|
+
# @todo This code is pretty poor, but it suffices for now.
|
69
|
+
# And we need not worry about it the future b/c eventually
|
70
|
+
# we will replace it by using the `amp` or `scm` gem.
|
71
|
+
def extract_tags
|
72
|
+
list = []
|
73
|
+
tags = `git tag -l`
|
74
|
+
tags.split(/\s+/).each do |tag|
|
75
|
+
next unless version_tag?(tag) # only version tags
|
76
|
+
who, date, rev, msg = nil, nil, nil, nil
|
77
|
+
info = `git show #{tag}`
|
78
|
+
info, *_ = info.split(/^(commit|diff|----)/)
|
79
|
+
if /\Atag/ =~ info
|
80
|
+
msg = ''
|
81
|
+
info.lines.to_a[1..-1].each do |line|
|
82
|
+
case line
|
83
|
+
when /^Tagger:/
|
84
|
+
who = $'.strip
|
85
|
+
when /^Date:/
|
86
|
+
date = $'.strip
|
87
|
+
else
|
88
|
+
msg << line
|
89
|
+
end
|
90
|
+
end
|
91
|
+
msg = msg.strip
|
12
92
|
|
13
|
-
|
14
|
-
|
93
|
+
#info = `git show #{tag}^ --pretty=format:"%ci|~|%H|~|"`
|
94
|
+
#cdate, id, *_ = *info.split('|~|')
|
15
95
|
|
16
|
-
|
17
|
-
def initialize_framework
|
18
|
-
#require 'grit'
|
19
|
-
end
|
96
|
+
info = git_show("#{tag}^")
|
20
97
|
|
21
|
-
|
22
|
-
def grit_repo
|
23
|
-
@grit_repo ||= Grit::Repo.new(root)
|
24
|
-
end
|
98
|
+
change = Change.new(info)
|
25
99
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
list
|
100
|
+
list << Tag.new(:name=>tag, :date=>date, :who=>who, :msg=>msg, :commit=>change)
|
101
|
+
else
|
102
|
+
#info = `git show #{tag} --pretty=format:"%cn|~|%ce|~|%ci|~|%H|~|%s|~|"`
|
103
|
+
info = git_show(tag)
|
104
|
+
change = Change.new(info)
|
105
|
+
|
106
|
+
tag_info = {
|
107
|
+
:name => tag,
|
108
|
+
:who => info[:who],
|
109
|
+
:date => info[:date],
|
110
|
+
:msg => info[:message],
|
111
|
+
:commit => change
|
112
|
+
}
|
113
|
+
list << Tag.new(tag_info)
|
114
|
+
end
|
115
|
+
|
116
|
+
#if $DEBUG
|
117
|
+
# p who, date, rev, msg
|
118
|
+
# puts
|
119
|
+
#end
|
120
|
+
|
121
|
+
#list << tag
|
122
|
+
end
|
123
|
+
|
124
|
+
return list
|
51
125
|
end
|
52
|
-
list
|
53
|
-
end
|
54
126
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
# files = `git show --pretty="format:" --name-only #{c.id}`
|
59
|
-
# files = files.split("\n")
|
60
|
-
# change.files = files
|
61
|
-
# end
|
62
|
-
#end
|
63
|
-
|
64
|
-
# TODO
|
65
|
-
#def extract_changes
|
66
|
-
# repo.commit.map do |commit|
|
67
|
-
# [commit.id, commit.date, commit.author.to_s, commit.message]
|
68
|
-
# end
|
69
|
-
#end
|
70
|
-
|
71
|
-
# Collect tags.
|
72
|
-
#
|
73
|
-
# `git show 1.0` produces:
|
74
|
-
#
|
75
|
-
# tag 1.0
|
76
|
-
# Tagger: 7rans <transfire@gmail.com>
|
77
|
-
# Date: Sun Oct 25 09:27:58 2009 -0400
|
78
|
-
#
|
79
|
-
# version 1.0
|
80
|
-
# commit
|
81
|
-
# ...
|
82
|
-
#
|
83
|
-
def extract_tags
|
84
|
-
list = []
|
85
|
-
tags = `git tag -l`
|
86
|
-
tags.split(/\s+/).each do |tag|
|
87
|
-
next unless version_tag?(tag) # only version tags
|
88
|
-
who, date, rev, msg = nil, nil, nil, nil
|
89
|
-
info = `git show #{tag}`
|
90
|
-
info, *_ = info.split(/^(commit|diff|----)/)
|
91
|
-
if /\Atag/ =~ info
|
92
|
-
msg = ''
|
93
|
-
info.lines.to_a[1..-1].each do |line|
|
94
|
-
case line
|
95
|
-
when /^Tagger:/
|
96
|
-
who = $'.strip
|
97
|
-
when /^Date:/
|
98
|
-
date = $'.strip
|
99
|
-
else
|
100
|
-
msg << line
|
101
|
-
end
|
102
|
-
end
|
103
|
-
msg = msg.strip
|
104
|
-
info = `git show #{tag}^ --pretty=format:"%ci|~|%H|~|"`
|
105
|
-
cdate, id, *_ = *info.split('|~|')
|
106
|
-
else
|
107
|
-
info = `git show #{tag} --pretty=format:"%cn|~|%ce|~|%ci|~|%H|~|%s|~|"`
|
108
|
-
who, email, cdate, id, msg, *_ = *info.split('|~|')
|
109
|
-
who = who + ' ' + email
|
110
|
-
date = cdate
|
111
|
-
end
|
112
|
-
|
113
|
-
#if $DEBUG
|
114
|
-
# p who, date, rev, msg
|
115
|
-
# puts
|
116
|
-
#end
|
117
|
-
|
118
|
-
list << Tag.new(:name=>tag, :date=>date, :who=>who, :msg=>msg, :commit_id=>id, :commit_date=>cdate)
|
127
|
+
# User name of developer.
|
128
|
+
def user
|
129
|
+
@user ||= `git config user.name`.strip
|
119
130
|
end
|
120
|
-
list
|
121
|
-
end
|
122
131
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
# end
|
128
|
-
# list
|
129
|
-
#end
|
132
|
+
# Email address of developer.
|
133
|
+
def email
|
134
|
+
@email ||= `git config user.email`.strip
|
135
|
+
end
|
130
136
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
end
|
137
|
+
#
|
138
|
+
def repository
|
139
|
+
@repository ||= `git config remote.origin.url`.strip
|
140
|
+
end
|
136
141
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
+
#
|
143
|
+
# Create a tag for the given commit reference.
|
144
|
+
#
|
145
|
+
def tag(ref, label, date, message)
|
146
|
+
file = tempfile("message", message)
|
147
|
+
date = date.strftime('%Y-%m-%d 23:59') unless String===date
|
142
148
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
149
|
+
cmd = %[GIT_AUTHOR_DATE='#{date}' GIT_COMMITTER_DATE='#{date}' git tag -a -F '#{file}' #{label} #{ref}]
|
150
|
+
puts cmd if $DEBUG
|
151
|
+
`#{cmd}` unless $DRYRUN
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
#
|
157
|
+
#
|
158
|
+
#
|
159
|
+
def git_show(ref)
|
160
|
+
command = 'git show ' + ref.to_s + ' --name-only --pretty=format:"' +
|
161
|
+
'%ci' +
|
162
|
+
GIT_FIELD_MARKER +
|
163
|
+
'%cn' +
|
164
|
+
GIT_FIELD_MARKER +
|
165
|
+
'%ce' +
|
166
|
+
GIT_FIELD_MARKER +
|
167
|
+
'%H' +
|
168
|
+
GIT_FIELD_MARKER +
|
169
|
+
'%s%n%n%b' +
|
170
|
+
GIT_FIELD_MARKER +
|
171
|
+
'"'
|
172
|
+
|
173
|
+
entry = `#{command}`
|
174
|
+
|
175
|
+
date, who, email, id, msg, files = entry.split(RUBY_FIELD_MARKER)
|
176
|
+
|
177
|
+
who = who + ' ' + email
|
178
|
+
date = Time.parse(date)
|
179
|
+
files = files.split("\n")
|
148
180
|
|
149
|
-
|
150
|
-
|
151
|
-
file = tempfile("message", message)
|
152
|
-
date = date.strftime('%Y-%m-%d 23:59') unless String===date
|
181
|
+
return { :date=>date, :who=>who, :id=>id, :message=>msg, :files=>files }
|
182
|
+
end
|
153
183
|
|
154
|
-
cmd = %[GIT_AUTHOR_DATE='#{date}' GIT_COMMITTER_DATE='#{date}' git tag -a -F '#{file}' #{label} #{ref}]
|
155
|
-
puts cmd if $DEBUG
|
156
|
-
`#{cmd}` unless $DRYRUN
|
157
184
|
end
|
158
185
|
|
159
|
-
end
|
186
|
+
end
|
160
187
|
|
161
188
|
end
|
162
|
-
end
|
data/lib/vclog/adapters/hg.rb
CHANGED
@@ -1,93 +1,129 @@
|
|
1
1
|
require 'vclog/adapters/abstract'
|
2
2
|
|
3
3
|
module VCLog
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
4
|
+
|
5
|
+
module Adapters
|
6
|
+
|
7
|
+
# Mercurial Adapter
|
8
|
+
#
|
9
|
+
class Hg < Abstract
|
10
|
+
|
11
|
+
#
|
12
|
+
# Collect changes.
|
13
|
+
#
|
14
|
+
def extract_changes
|
15
|
+
list = []
|
16
|
+
changelog = `hg log -v`.strip
|
17
|
+
changes = changelog.split("\n\n\n")
|
18
|
+
changes.each do |entry|
|
19
|
+
settings = parse_entry(entry)
|
20
|
+
list << Change.new(settings)
|
21
|
+
end
|
22
|
+
list
|
19
23
|
end
|
20
|
-
list
|
21
|
-
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
#
|
26
|
+
# Collect tags.
|
27
|
+
#
|
28
|
+
# @todo Extract first commit prior to tag and provide it with Tag object.
|
29
|
+
#
|
30
|
+
def extract_tags
|
31
|
+
list = []
|
32
|
+
if File.exist?('.hgtags')
|
33
|
+
File.readlines('.hgtags').each do |line|
|
34
|
+
rev, tag = line.strip.split(' ')
|
35
|
+
entry = `hg log -v -r #{rev}`.strip
|
36
|
+
settings = parse_entry(entry)
|
37
|
+
settings[:name] = tag
|
38
|
+
list << Tag.new(settings)
|
39
|
+
end
|
32
40
|
end
|
41
|
+
list
|
33
42
|
end
|
34
|
-
list
|
35
|
-
end
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
#
|
45
|
+
# Username.
|
46
|
+
#
|
47
|
+
# @todo check .hgrc for user.
|
48
|
+
#
|
49
|
+
def user
|
50
|
+
ENV['HGUSER'] || ENV['USER']
|
51
|
+
end
|
41
52
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
#
|
54
|
+
# User's email address.
|
55
|
+
#
|
56
|
+
# @todo check .hgrc for email.
|
57
|
+
#
|
58
|
+
def email
|
59
|
+
ENV['HGEMAIL'] || ENV['EMAIL']
|
60
|
+
end
|
46
61
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
62
|
+
#
|
63
|
+
# URI of repository.
|
64
|
+
#
|
65
|
+
def uri
|
66
|
+
@uri ||= `hg showconfig paths.default`.strip
|
67
|
+
end
|
51
68
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
69
|
+
# @deprecated
|
70
|
+
alias_method :repository, :uri
|
71
|
+
|
72
|
+
#
|
73
|
+
#
|
74
|
+
#
|
75
|
+
def uuid
|
76
|
+
nil
|
77
|
+
end
|
56
78
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
79
|
+
#
|
80
|
+
# TODO: Will multi-line messages work okay this way?
|
81
|
+
#
|
82
|
+
def tag(ref, label, date, msg)
|
83
|
+
file = tempfile("message", msg)
|
84
|
+
date = date.strftime('%Y-%m-%d') unless String===date
|
61
85
|
|
62
|
-
|
86
|
+
cmd = %[hg tag -r #{ref} -d #{date} -m "$(cat #{file})" #{label}]
|
63
87
|
|
64
|
-
|
65
|
-
|
66
|
-
|
88
|
+
puts cmd if $DEBUG
|
89
|
+
`#{cmd}` unless $DRYRUN
|
90
|
+
end
|
67
91
|
|
68
|
-
|
92
|
+
private
|
69
93
|
|
94
|
+
#
|
95
|
+
# Parse log entry.
|
96
|
+
#
|
70
97
|
def parse_entry(entry)
|
71
|
-
|
98
|
+
settings = {}
|
99
|
+
|
72
100
|
entry.strip!
|
101
|
+
|
73
102
|
if md = /^changeset:(.*?)$/.match(entry)
|
74
|
-
|
103
|
+
settings[:id] = md[1].strip
|
75
104
|
end
|
105
|
+
|
76
106
|
if md = /^date:(.*?)$/.match(entry)
|
77
|
-
date = md[1].strip
|
107
|
+
settings[:date] = Time.parse(md[1].strip)
|
78
108
|
end
|
109
|
+
|
79
110
|
if md = /^user:(.*?)$/.match(entry)
|
80
|
-
who = md[1].strip
|
111
|
+
settings[:who] = md[1].strip
|
112
|
+
end
|
113
|
+
|
114
|
+
if md = /^files:(.*?)$/.match(entry)
|
115
|
+
settings[:files] = md[1].strip.split(' ')
|
81
116
|
end
|
117
|
+
|
82
118
|
if md = /^description:(.*?)\Z/m.match(entry)
|
83
|
-
msg = md[1].strip
|
119
|
+
settings[:msg] = md[1].strip
|
84
120
|
end
|
85
|
-
|
86
|
-
|
87
|
-
return rev, date, who, msg
|
121
|
+
|
122
|
+
return settings
|
88
123
|
end
|
89
124
|
|
125
|
+
end
|
126
|
+
|
90
127
|
end
|
91
128
|
|
92
129
|
end
|
93
|
-
end
|