create_changelog 1.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +16 -0
- data/README.md +146 -0
- data/bin/ccl +66 -0
- data/bin/ccl~ +66 -0
- data/lib/array.rb +18 -0
- data/lib/changelog_filter.rb +57 -0
- data/lib/changelog_filter.rb~ +57 -0
- data/lib/commit_changelog.rb +31 -0
- data/lib/create_changelog.rb +74 -0
- data/lib/git.rb +60 -0
- data/lib/git.rb~ +58 -0
- data/lib/tag.rb +51 -0
- data/lib/tag_list.rb +62 -0
- data/lib/version.rb +3 -0
- data/lib/version.rb~ +3 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd381224eb8e14e9bdbb5b5b58dedb315b2390ab
|
4
|
+
data.tar.gz: 3713419603968048a91c5bb5eb02f0df554b263e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a38fea06c029efe529b4defb5cab2a772df00a554ea5f27eef7250c278eb46e5e686fe06b5b8a33d9c7fd09d8e67b0b6d624e2993262d3fc7785b28801c0837
|
7
|
+
data.tar.gz: a9dc791d30ca360cbf964a8c303da4c9f44e152c858fc12c76c7732b6ddc747b87c7a87fdbb144e8fb1729e06296d0b5163501804f53a512dd17b20eebb8639e
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Version 1.1.0 (2015-01-18)
|
2
|
+
========================================================================
|
3
|
+
|
4
|
+
- CHANGED: Accept dashes in addition to asterisks in changelog lines.
|
5
|
+
- NEW: Create gem.
|
6
|
+
|
7
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
8
|
+
|
9
|
+
|
10
|
+
Version 1.0.0 (2015-01-18)
|
11
|
+
========================================================================
|
12
|
+
|
13
|
+
|
14
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
15
|
+
|
16
|
+
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
create-changelog
|
2
|
+
================
|
3
|
+
|
4
|
+
Ruby program with command-line interface that creates a changelog from
|
5
|
+
log lines in a git repository that can be read and understood by end
|
6
|
+
users.
|
7
|
+
|
8
|
+
There are several approaches to creating changelog files from git
|
9
|
+
commits (e.g., [gitchangelog][], [gitlog-to-changelog][gl2cl] and many
|
10
|
+
more). None of these quite fit my needs, so I decided to create my own
|
11
|
+
tool.
|
12
|
+
|
13
|
+
What's special about my approach is that the changelog information is
|
14
|
+
not taken from every commit, but from specially marked lines in the
|
15
|
+
commit messages and tag annotations. Changelog lines must comply with
|
16
|
+
the format:
|
17
|
+
|
18
|
+
- [KEYWORD]: [TEXT]
|
19
|
+
|
20
|
+
Where `[KEYWORD]` may be any keyword of your liking, such as "NEW",
|
21
|
+
"FIX", and so on. (I am planning to predefine these keywords in a later
|
22
|
+
version.) `[TEXT]` is an explanation of the change. _Note that the
|
23
|
+
program currently operates on single lines, so it is not possible to
|
24
|
+
have `[TEXT]` span several lines._
|
25
|
+
|
26
|
+
The reason why I chose to have special changelog lines rather than
|
27
|
+
commit subjects is that commits are rather technical, but I want to have
|
28
|
+
a changelog that can be read by 'normal' end users.
|
29
|
+
|
30
|
+
|
31
|
+
Usage
|
32
|
+
-----
|
33
|
+
|
34
|
+
### Creating log entries
|
35
|
+
When committing, add a line that fits the above definition to the commit
|
36
|
+
message, e.g.
|
37
|
+
|
38
|
+
Implement Backup class.
|
39
|
+
|
40
|
+
- NEW: Ability to back up the files.
|
41
|
+
|
42
|
+
Create annotated tags to identify new versions:
|
43
|
+
|
44
|
+
Version 7.0.0-alpha.3
|
45
|
+
|
46
|
+
This version adds a new backup feature and fixes several bugs.
|
47
|
+
|
48
|
+
If you wish, you can include additional changelog entries in the tag
|
49
|
+
annotation. These may even be the same that you used for the commit
|
50
|
+
messages (and this tool provides a way to filter the commit messages for
|
51
|
+
just these lines). The tool ensures that there are no duplicate
|
52
|
+
changelog entries.
|
53
|
+
|
54
|
+
Version 7.0.0-alpha.3
|
55
|
+
|
56
|
+
This version adds a new backup feature and fixes several bugs.
|
57
|
+
|
58
|
+
- NEW: Ability to back up the files.
|
59
|
+
|
60
|
+
|
61
|
+
### Generating the log
|
62
|
+
|
63
|
+
To generate a complete change log, simply run the tool in the directory
|
64
|
+
of the git repository, or indicate a working directory:
|
65
|
+
|
66
|
+
ccl.rb -d /home/me/my/repository
|
67
|
+
|
68
|
+
The output will be in markdown format. If you wish, you can further
|
69
|
+
process it using tools like [pandoc][] for example. Of course, it is
|
70
|
+
also possible to incorporate the command in the content files for a
|
71
|
+
static site generator such as [nanoc][].
|
72
|
+
|
73
|
+
If you want to track your log in the git repository, you probably will
|
74
|
+
not yet have an annotated tag for the version you are preparing. In this
|
75
|
+
case, the tool will use "Unpublished changes" as the heading for the
|
76
|
+
latest changes. To use the version number that you are about to use in
|
77
|
+
the tag, call the tool with an optional argument:
|
78
|
+
|
79
|
+
ccl.rb 7.0.0-alpha.4
|
80
|
+
|
81
|
+
Be aware that currently, the date of the most recent commit (that HEAD
|
82
|
+
points to) will be appended to the heading.
|
83
|
+
|
84
|
+
To exclude recent changes that were logged since the last tag:
|
85
|
+
|
86
|
+
ccl.rb --no-recent
|
87
|
+
ccl.rb -n
|
88
|
+
|
89
|
+
To just see the (undecorated) changelog entries since the last tag, use:
|
90
|
+
|
91
|
+
ccl.rb --recent
|
92
|
+
ccl.rb -r
|
93
|
+
|
94
|
+
This can be handy if you want to add a log of recent changes to your tag
|
95
|
+
annotation. For example, using the Vim text editor, issue:
|
96
|
+
|
97
|
+
:r!ccl.rb -r
|
98
|
+
|
99
|
+
The tool will make sure that no changelog lines are duplicated.
|
100
|
+
|
101
|
+
|
102
|
+
Changelog format
|
103
|
+
----------------
|
104
|
+
|
105
|
+
The changelog format resembles the [suggestions][kacl] made by Olivier
|
106
|
+
Lacan. I have not yet have the time to implement automatic generation of
|
107
|
+
subheadings. Maybe I'll add the feature in the future.
|
108
|
+
|
109
|
+
|
110
|
+
Live example
|
111
|
+
------------
|
112
|
+
|
113
|
+
<http://xltoolbox.sf.net/changelog-ng>
|
114
|
+
|
115
|
+
|
116
|
+
Code
|
117
|
+
----
|
118
|
+
|
119
|
+
To understand the code, you can run `rdoc` in the repository's
|
120
|
+
directory. The resulting `doc` subdirectory will be ignored by Git.
|
121
|
+
|
122
|
+
|
123
|
+
License
|
124
|
+
-------
|
125
|
+
|
126
|
+
Copyright 2015 Daniel Kraus
|
127
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
128
|
+
you may not use this file except in compliance with the License.
|
129
|
+
You may obtain a copy of the License at
|
130
|
+
|
131
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
132
|
+
|
133
|
+
Unless required by applicable law or agreed to in writing, software
|
134
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
135
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
136
|
+
See the License for the specific language governing permissions and
|
137
|
+
limitations under the License.
|
138
|
+
|
139
|
+
[gitchangelog]: https://pypi.python.org/pypi/gitchangelog
|
140
|
+
[gl2cl]: https://github.com/manuelbua/gitver/blob/master/gitlog-to-changelog
|
141
|
+
[gnu-changelog]: http://www.gnu.org/prep/standards/html_node/Change-Logs.html
|
142
|
+
[pandoc]: http://johnmacfarlane.net/pandoc
|
143
|
+
[nanoc]: http://nanoc.ws
|
144
|
+
[kacl]: http://keepachangelog.com
|
145
|
+
|
146
|
+
<!-- vim: set tw=72 : -->
|
data/bin/ccl
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Create-changelog
|
3
|
+
# Copyright 2015 Daniel Kraus
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
# Filters the git log of the repository in the current directory
|
17
|
+
# for unique lines that match the pattern
|
18
|
+
# * [KEYWORD]: [DESCRIPTION]
|
19
|
+
# The filtered lines are sorted and written to standard out.
|
20
|
+
|
21
|
+
require 'optparse'
|
22
|
+
require_relative '../lib/create_changelog.rb'
|
23
|
+
require_relative '../lib/git.rb'
|
24
|
+
require_relative '../lib/version.rb'
|
25
|
+
|
26
|
+
def main
|
27
|
+
options = {}
|
28
|
+
working_dir = Dir.pwd
|
29
|
+
option_parser = OptionParser.new do |opts|
|
30
|
+
exe_name = File.basename($PROGRAM_NAME)
|
31
|
+
opts.banner = "#{exe_name} version #{CreateChangelog::VERSION}\n"
|
32
|
+
opts.banner += "Creates changelog from log entries in git log\n"
|
33
|
+
opts.banner += "Usage: #{exe_name} [options] [current_version]"
|
34
|
+
opts.on("-r", "--recent",
|
35
|
+
"Include only most recent changes") do
|
36
|
+
abort "FATAL: Cannot combine --recent and --no-recent" if options[:no_recent]
|
37
|
+
options[:only_recent] = true
|
38
|
+
end
|
39
|
+
opts.on("-n", "--no-recent",
|
40
|
+
"Exclude the most recent changes (from untagged commits)") do
|
41
|
+
abort "FATAL: Cannot combine --recent and --no-recent" if options[:recent]
|
42
|
+
options[:no_recent] = true
|
43
|
+
end
|
44
|
+
opts.on("-d WORKING_DIR", "--dir WORKING_DIR",
|
45
|
+
"Use alternate working directory") do |dir|
|
46
|
+
working_dir = dir
|
47
|
+
end
|
48
|
+
end
|
49
|
+
option_parser.parse!
|
50
|
+
|
51
|
+
Dir.chdir(working_dir) do
|
52
|
+
abort "FATAL: Not a git repository." unless Git.is_git_repository?
|
53
|
+
|
54
|
+
change_log = Changelog.new
|
55
|
+
change_log.recent_changes_heading = ARGV[0] unless ARGV.empty?
|
56
|
+
if options[:only_recent]
|
57
|
+
puts change_log.generate_recent
|
58
|
+
else
|
59
|
+
puts change_log.generate(options[:no_recent])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
main
|
65
|
+
|
66
|
+
# vim: nospell
|
data/bin/ccl~
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Create-changelog
|
3
|
+
# Copyright 2015 Daniel Kraus
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
# Filters the git log of the repository in the current directory
|
17
|
+
# for unique lines that match the pattern
|
18
|
+
# * [KEYWORD]: [DESCRIPTION]
|
19
|
+
# The filtered lines are sorted and written to standard out.
|
20
|
+
|
21
|
+
require 'optparse'
|
22
|
+
require_relative '../lib/changelog.rb'
|
23
|
+
require_relative '../lib/git.rb'
|
24
|
+
require_relative '../lib/version.rb'
|
25
|
+
|
26
|
+
def main
|
27
|
+
options = {}
|
28
|
+
working_dir = Dir.pwd
|
29
|
+
option_parser = OptionParser.new do |opts|
|
30
|
+
exe_name = File.basename($PROGRAM_NAME)
|
31
|
+
opts.banner = "#{exe_name} version #{CreateChangelog::VERSION}\n"
|
32
|
+
opts.banner += "Creates changelog from log entries in git log\n"
|
33
|
+
opts.banner += "Usage: #{exe_name} [options] [current_version]"
|
34
|
+
opts.on("-r", "--recent",
|
35
|
+
"Include only most recent changes") do
|
36
|
+
abort "FATAL: Cannot combine --recent and --no-recent" if options[:no_recent]
|
37
|
+
options[:only_recent] = true
|
38
|
+
end
|
39
|
+
opts.on("-n", "--no-recent",
|
40
|
+
"Exclude the most recent changes (from untagged commits)") do
|
41
|
+
abort "FATAL: Cannot combine --recent and --no-recent" if options[:recent]
|
42
|
+
options[:no_recent] = true
|
43
|
+
end
|
44
|
+
opts.on("-d WORKING_DIR", "--dir WORKING_DIR",
|
45
|
+
"Use alternate working directory") do |dir|
|
46
|
+
working_dir = dir
|
47
|
+
end
|
48
|
+
end
|
49
|
+
option_parser.parse!
|
50
|
+
|
51
|
+
Dir.chdir(working_dir) do
|
52
|
+
abort "FATAL: Not a git repository." unless Git.is_git_repository?
|
53
|
+
|
54
|
+
change_log = Changelog.new
|
55
|
+
change_log.recent_changes_heading = ARGV[0] unless ARGV.empty?
|
56
|
+
if options[:only_recent]
|
57
|
+
puts change_log.generate_recent
|
58
|
+
else
|
59
|
+
puts change_log.generate(options[:no_recent])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
main
|
65
|
+
|
66
|
+
# vim: nospell
|
data/lib/array.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Removes common indentation from an array of strings
|
2
|
+
class Array
|
3
|
+
def remove_indent
|
4
|
+
lines_with_indent = self.select do |line|
|
5
|
+
line.size > 0
|
6
|
+
end
|
7
|
+
indents = lines_with_indent.map do |line|
|
8
|
+
match = line.match(/^( +)([^ ]|$)+/)
|
9
|
+
match ? match[1].size : 0
|
10
|
+
end
|
11
|
+
indent = indents.min
|
12
|
+
self.map do |line|
|
13
|
+
line[indent..-1]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# vim: nospell
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# changelog_filter.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'array'
|
16
|
+
|
17
|
+
# Filters a text or array for changelog entries.
|
18
|
+
class ChangelogFilter
|
19
|
+
# Factory method that creates an instance given a text string
|
20
|
+
def self.FromString(string)
|
21
|
+
unless string.is_a?(String)
|
22
|
+
fail "Must call this factory with String, not " + string.class.to_s
|
23
|
+
end
|
24
|
+
self.FromArray(string.chomp.split("\n"))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Factory method that creates an instance given an array of strings
|
28
|
+
def self.FromArray(ary)
|
29
|
+
unless ary.is_a?(Array)
|
30
|
+
fail "Must call this factory with Array, not " + ary.class.to_s
|
31
|
+
end
|
32
|
+
filter = ChangelogFilter.new
|
33
|
+
log, filter.other_text = ary.partition do |line|
|
34
|
+
line.match(pattern)
|
35
|
+
end
|
36
|
+
filter.changelog = log.uniq.sort.remove_indent if log.length > 0
|
37
|
+
filter
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the grep string that matches changelog entries.
|
41
|
+
def self.pattern
|
42
|
+
'\s*[*-]\s+[^:]+:\s'
|
43
|
+
end
|
44
|
+
|
45
|
+
# An array of changelog entries.
|
46
|
+
attr_accessor :changelog
|
47
|
+
|
48
|
+
# An array of text lines that are not changelog entries.
|
49
|
+
attr_accessor :other_text
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# vim: nospell
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# changelog_filter.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative 'array'
|
16
|
+
|
17
|
+
# Filters a text or array for changelog entries.
|
18
|
+
class ChangelogFilter
|
19
|
+
# Factory method that creates an instance given a text string
|
20
|
+
def self.FromString(string)
|
21
|
+
unless string.is_a?(String)
|
22
|
+
fail "Must call this factory with String, not " + string.class.to_s
|
23
|
+
end
|
24
|
+
self.FromArray(string.chomp.split("\n"))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Factory method that creates an instance given an array of strings
|
28
|
+
def self.FromArray(ary)
|
29
|
+
unless ary.is_a?(Array)
|
30
|
+
fail "Must call this factory with Array, not " + ary.class.to_s
|
31
|
+
end
|
32
|
+
filter = ChangelogFilter.new
|
33
|
+
log, filter.other_text = ary.partition do |line|
|
34
|
+
line.match(pattern)
|
35
|
+
end
|
36
|
+
filter.changelog = log.uniq.sort.remove_indent if log.length > 0
|
37
|
+
filter
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the grep string that matches changelog entries.
|
41
|
+
def self.pattern
|
42
|
+
'\s*\*\s+[^:]+:\s'
|
43
|
+
end
|
44
|
+
|
45
|
+
# An array of changelog entries.
|
46
|
+
attr_accessor :changelog
|
47
|
+
|
48
|
+
# An array of text lines that are not changelog entries.
|
49
|
+
attr_accessor :other_text
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# vim: nospell
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# commit_changelog.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require_relative 'changelog_filter'
|
15
|
+
|
16
|
+
# Filters commit messages for changelog entries.
|
17
|
+
class CommitChangelog
|
18
|
+
# Contains changelog entries of the commits.
|
19
|
+
attr_reader :changelog
|
20
|
+
|
21
|
+
# Instantiates an object containing changelog entries between
|
22
|
+
# two git commits.
|
23
|
+
def initialize(to_commit, from_commit)
|
24
|
+
pattern = ChangelogFilter.pattern
|
25
|
+
messages = Git.get_filtered_messages(from_commit, to_commit, pattern)
|
26
|
+
filter = ChangelogFilter.FromString(messages)
|
27
|
+
@changelog = filter.changelog
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# vim: nospell
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# changelog.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require_relative './commit_changelog.rb'
|
15
|
+
require_relative './tag_list.rb'
|
16
|
+
require_relative './tag.rb'
|
17
|
+
|
18
|
+
# Central class that puts together the changelog.
|
19
|
+
class Changelog
|
20
|
+
# Heading for the most recent changes.
|
21
|
+
attr_writer :recent_changes_heading
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@recent_changes_heading = "Unpublished changes"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generates a decorated changelog.
|
28
|
+
def generate(exclude_recent = false)
|
29
|
+
# Traverse tags
|
30
|
+
tags = TagList.new(!exclude_recent)
|
31
|
+
output = String.new
|
32
|
+
tags.list.each_cons(2) do |current_tag, previous_tag|
|
33
|
+
output << generate_for(current_tag, previous_tag)
|
34
|
+
end
|
35
|
+
output
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a simple, undecorated list of changelog entries
|
39
|
+
# since the most recent tag.
|
40
|
+
def generate_recent
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def generate_for(current_tag, previous_tag)
|
46
|
+
tag = Tag.new(current_tag)
|
47
|
+
commit_changelog = CommitChangelog.new(current_tag, previous_tag)
|
48
|
+
|
49
|
+
# Combine changelog entries from tag annotation and commit messages
|
50
|
+
if tag.changelog
|
51
|
+
combined_changelog = tag.changelog.concat(commit_changelog.changelog)
|
52
|
+
else
|
53
|
+
combined_changelog = commit_changelog.changelog
|
54
|
+
end
|
55
|
+
combined_changelog.uniq! if combined_changelog
|
56
|
+
|
57
|
+
output = String.new
|
58
|
+
tag.heading = @recent_changes_heading unless tag.heading
|
59
|
+
if tag.heading
|
60
|
+
output << tag.heading + " (#{tag.date})\n"
|
61
|
+
output << "=" * 72 + "\n"
|
62
|
+
end
|
63
|
+
output << tag.text.join("\n") + "\n" if tag.text
|
64
|
+
output << combined_changelog.join("\n") + "\n" if combined_changelog
|
65
|
+
output << end_separator if tag.heading or tag.text or combined_changelog
|
66
|
+
output
|
67
|
+
end
|
68
|
+
|
69
|
+
def end_separator
|
70
|
+
"\n" + ("* " * 36) +"\n\n\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# vim: nospell
|
data/lib/git.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# git.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require_relative 'tag_list'
|
15
|
+
|
16
|
+
# A static wrapper class for git
|
17
|
+
class Git
|
18
|
+
|
19
|
+
# Determines whether the (current) directory is a git repository
|
20
|
+
def self.is_git_repository?(dir = nil)
|
21
|
+
dir = Dir.pwd if dir.nil?
|
22
|
+
system("git status > /dev/null 2>&1")
|
23
|
+
$? == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves the first 99 lines of the annotation of a tag.
|
27
|
+
def self.get_tag_annotation(tag)
|
28
|
+
test_tag tag
|
29
|
+
`git tag -l -n99 #{tag}`.rstrip
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retrieves the date of a tag
|
33
|
+
def self.get_tag_date(tag)
|
34
|
+
test_tag tag
|
35
|
+
`git log -1 --format=format:%ai #{tag}`
|
36
|
+
end
|
37
|
+
|
38
|
+
# Retrieves commit messages and filters them
|
39
|
+
# Todo: Armor this against code injection!
|
40
|
+
def self.get_filtered_messages(from_commit, to_commit, filter)
|
41
|
+
`git log #{from_commit}..#{to_commit} -E --grep='#{filter}' --format=%b`
|
42
|
+
end
|
43
|
+
|
44
|
+
@@tags = nil
|
45
|
+
|
46
|
+
# Ensures lazy loading of the tag list to enable calling code
|
47
|
+
# to change the working directory first.
|
48
|
+
def self.tags
|
49
|
+
@@tags = TagList.new unless @@tags
|
50
|
+
@@tags
|
51
|
+
end
|
52
|
+
|
53
|
+
# Tests if the given tag exists and fails if it doesn't
|
54
|
+
def self.test_tag(tag)
|
55
|
+
fail "Invalid tag: #{tag}" unless tags.list.include?(tag)
|
56
|
+
end
|
57
|
+
private_class_method :test_tag, :tags
|
58
|
+
end
|
59
|
+
|
60
|
+
# vim: nospell
|
data/lib/git.rb~
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# git.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require_relative 'tag_list'
|
15
|
+
|
16
|
+
# A static wrapper class for git
|
17
|
+
class Git
|
18
|
+
|
19
|
+
# Determines whether the (current) directory is a git repository
|
20
|
+
def self.is_git_repository?(dir = nil)
|
21
|
+
dir = Dir.pwd if dir.nil?
|
22
|
+
system("git status > /dev/null 2>&1")
|
23
|
+
$? == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves the first 99 lines of the annotation of a tag.
|
27
|
+
def self.get_tag_annotation(tag)
|
28
|
+
test_tag tag
|
29
|
+
`git tag -l -n99 #{tag}`.rstrip
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retrieves the date of a tag
|
33
|
+
def self.get_tag_date(tag)
|
34
|
+
test_tag tag
|
35
|
+
`git log -1 --format=format:%ai #{tag}`
|
36
|
+
end
|
37
|
+
|
38
|
+
# Retrieves commit messages and filters them
|
39
|
+
# Todo: Armor this against code injection!
|
40
|
+
def self.get_filtered_messages(from_commit, to_commit, filter)
|
41
|
+
`git log #{from_commit}..#{to_commit} -E --grep='#{filter}' --format=%b`
|
42
|
+
end
|
43
|
+
|
44
|
+
@@tags = nil
|
45
|
+
|
46
|
+
def self.tags
|
47
|
+
@@tags = TagList.new unless @@tags
|
48
|
+
@@tags
|
49
|
+
end
|
50
|
+
|
51
|
+
# Tests if the given tag exists and fails if it doesn't
|
52
|
+
def self.test_tag(tag)
|
53
|
+
fail "Invalid tag: #{tag}" unless tags.list.include?(tag)
|
54
|
+
end
|
55
|
+
private_class_method :test_tag, :tags
|
56
|
+
end
|
57
|
+
|
58
|
+
# vim: nospell
|
data/lib/tag.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# tag.rb, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'date'
|
15
|
+
require_relative 'git'
|
16
|
+
require_relative 'changelog_filter'
|
17
|
+
|
18
|
+
# Represents a git tag and its annotation.
|
19
|
+
class Tag
|
20
|
+
# The heading of the tag annotation.
|
21
|
+
attr_accessor :heading
|
22
|
+
|
23
|
+
# Array of lines in the tag annotation that are not changelog entries.
|
24
|
+
attr_reader :text
|
25
|
+
|
26
|
+
# Array of lines in the tag annotation that are changelog entries.
|
27
|
+
attr_reader :changelog
|
28
|
+
|
29
|
+
# Author commit date of the tag
|
30
|
+
attr_reader :date
|
31
|
+
|
32
|
+
# Gets change information for a specific tagged version.
|
33
|
+
# This will prepend the summary for the annotated tag before
|
34
|
+
# the list of changes. If the tag annotation contains changelog
|
35
|
+
# entries, they are merged with the changelog entries filtered
|
36
|
+
# from the commit messages, and only unique entries are used.
|
37
|
+
def initialize(tag)
|
38
|
+
annotation = Git.get_tag_annotation(tag)
|
39
|
+
@date = Date.parse(Git.get_tag_date(tag))
|
40
|
+
if annotation
|
41
|
+
annotation = annotation.split("\n")
|
42
|
+
@heading = annotation.shift
|
43
|
+
@heading = @heading.split(' ')[1..-1].join(' ') if @heading
|
44
|
+
filter = ChangelogFilter.FromArray(annotation)
|
45
|
+
@text = filter.other_text.remove_indent
|
46
|
+
@changelog = filter.changelog
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# vim: nospell
|
data/lib/tag_list.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# TagList, part of Create-changelog
|
2
|
+
# Copyright 2015 Daniel Kraus
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# Builds a list of tags in the current git repository.
|
16
|
+
# The tags are enclosed by the sha1 of the first commit
|
17
|
+
# and optionally "HEAD" to allow traversing the list
|
18
|
+
# with each_con to obtain start and end points of
|
19
|
+
# developmental epochs.
|
20
|
+
class TagList
|
21
|
+
# Returns an array of tag names surrounded by HEAD
|
22
|
+
# at the top and the sha1 of the first commit at the
|
23
|
+
# bottom.
|
24
|
+
attr_reader :list
|
25
|
+
|
26
|
+
# Instantiates the tag list.
|
27
|
+
# include_head indicates whether or not to include
|
28
|
+
# the most recent changes
|
29
|
+
def initialize(include_head = true)
|
30
|
+
@include_head = include_head
|
31
|
+
@list = build_list
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the most recent tag in the git repository,
|
35
|
+
# or the sha1 of the initial commit if there is no tag.
|
36
|
+
def latest_tag
|
37
|
+
# Index 0 is HEAD
|
38
|
+
# Index 1 is most recent tag or first commit
|
39
|
+
@list[1]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Returns the sha1 of the initial commit.
|
45
|
+
# In fact, this function returns all parentless commits
|
46
|
+
# of the repository. Usually there should be not more than
|
47
|
+
# one such commit.
|
48
|
+
# See http://stackoverflow.com/a/1007545/270712
|
49
|
+
def get_initial_commit
|
50
|
+
`git rev-list --max-parents=0 HEAD`.chomp
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_list
|
54
|
+
tags = []
|
55
|
+
tags << get_initial_commit
|
56
|
+
tags += `git tag`.split("\n").map { |s| s.rstrip }
|
57
|
+
tags << "HEAD" if @include_head
|
58
|
+
tags.reverse
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# vim: nospell
|
data/lib/version.rb
ADDED
data/lib/version.rb~
ADDED
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: create_changelog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Kraus
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: "\t\tRuby program with command-line interface that creates a changelog
|
14
|
+
from log\n\t\tlines in a git repository that can be read and understood by end users.\n"
|
15
|
+
email: krada@gmx.net
|
16
|
+
executables:
|
17
|
+
- ccl
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- CHANGELOG.md
|
22
|
+
- README.md
|
23
|
+
- bin/ccl
|
24
|
+
- bin/ccl~
|
25
|
+
- lib/array.rb
|
26
|
+
- lib/changelog_filter.rb
|
27
|
+
- lib/changelog_filter.rb~
|
28
|
+
- lib/commit_changelog.rb
|
29
|
+
- lib/create_changelog.rb
|
30
|
+
- lib/git.rb
|
31
|
+
- lib/git.rb~
|
32
|
+
- lib/tag.rb
|
33
|
+
- lib/tag_list.rb
|
34
|
+
- lib/version.rb
|
35
|
+
- lib/version.rb~
|
36
|
+
homepage: https://github.com/bovender/create-changelog
|
37
|
+
licenses:
|
38
|
+
- Apache License version 2
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.2.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Creates end-user-friendly changelog from git messages.
|
60
|
+
test_files: []
|