vclog 1.8.2 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|