create_changelog 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ module CreateChangelog
2
+ VERSION = '1.1.0'
3
+ end
data/lib/version.rb~ ADDED
@@ -0,0 +1,3 @@
1
+ module CreateChangelog
2
+ VERSION = '1.0.0'
3
+ end
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: []