tag-changelog 0.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 +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +68 -0
- data/README.md +43 -0
- data/Rakefile +44 -0
- data/bin/tag-changelog +97 -0
- data/features/changelog.feature +8 -0
- data/features/step_definitions/changelog_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/lib/tag_changelog.rb +9 -0
- data/lib/tag_changelog/generate.rb +121 -0
- data/lib/tag_changelog/git/git.rb +152 -0
- data/lib/tag_changelog/git/tag.rb +37 -0
- data/lib/tag_changelog/git/tag_list.rb +74 -0
- data/lib/tag_changelog/templates/config.yml +37 -0
- data/lib/tag_changelog/version.rb +3 -0
- data/tag-changelog.gemspec +25 -0
- data/test/default_test.rb +14 -0
- data/test/test_helper.rb +9 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9293d2c322efcd8fb7411c8bcb7c47d161b7a985
|
4
|
+
data.tar.gz: 1569037ac2782b2b24564335f6e0515f52dce1d6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 364e78e00b586099fe42fb690fd0968ac0c56de31cf417d13ee07308f8619e3eeb57d20598eb1b3cad49a9f9a6dbe66b8d42f2a066b1eb032ad879bba2a581b9
|
7
|
+
data.tar.gz: 5ef46f7c023d99bdafc4598313782aeaf0d36cda7afd731424af110d8d28312a21ec3e7bec451f639df1c391a9f66af67ef04a8d53c9eaa4f7df7aada613a2ae
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tag-changelog (0.1.0)
|
5
|
+
gli (= 2.17.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
aruba (0.14.3)
|
11
|
+
childprocess (~> 0.8.0)
|
12
|
+
contracts (~> 0.9)
|
13
|
+
cucumber (>= 1.3.19)
|
14
|
+
ffi (~> 1.9.10)
|
15
|
+
rspec-expectations (>= 2.99)
|
16
|
+
thor (~> 0.19)
|
17
|
+
backports (3.11.1)
|
18
|
+
builder (3.2.3)
|
19
|
+
childprocess (0.8.0)
|
20
|
+
ffi (~> 1.0, >= 1.0.11)
|
21
|
+
coderay (1.1.2)
|
22
|
+
contracts (0.16.0)
|
23
|
+
cucumber (3.1.0)
|
24
|
+
builder (>= 2.1.2)
|
25
|
+
cucumber-core (~> 3.1.0)
|
26
|
+
cucumber-expressions (~> 5.0.4)
|
27
|
+
cucumber-wire (~> 0.0.1)
|
28
|
+
diff-lcs (~> 1.3)
|
29
|
+
gherkin (~> 5.0)
|
30
|
+
multi_json (>= 1.7.5, < 2.0)
|
31
|
+
multi_test (>= 0.1.2)
|
32
|
+
cucumber-core (3.1.0)
|
33
|
+
backports (>= 3.8.0)
|
34
|
+
cucumber-tag_expressions (~> 1.1.0)
|
35
|
+
gherkin (>= 5.0.0)
|
36
|
+
cucumber-expressions (5.0.13)
|
37
|
+
cucumber-tag_expressions (1.1.1)
|
38
|
+
cucumber-wire (0.0.1)
|
39
|
+
diff-lcs (1.3)
|
40
|
+
ffi (1.9.21)
|
41
|
+
gherkin (5.0.0)
|
42
|
+
gli (2.17.1)
|
43
|
+
method_source (0.9.0)
|
44
|
+
multi_json (1.13.1)
|
45
|
+
multi_test (0.1.2)
|
46
|
+
pry (0.11.3)
|
47
|
+
coderay (~> 1.1.0)
|
48
|
+
method_source (~> 0.9.0)
|
49
|
+
rake (12.3.0)
|
50
|
+
rdoc (6.0.1)
|
51
|
+
rspec-expectations (3.7.0)
|
52
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
53
|
+
rspec-support (~> 3.7.0)
|
54
|
+
rspec-support (3.7.1)
|
55
|
+
thor (0.20.0)
|
56
|
+
|
57
|
+
PLATFORMS
|
58
|
+
ruby
|
59
|
+
|
60
|
+
DEPENDENCIES
|
61
|
+
aruba
|
62
|
+
pry
|
63
|
+
rake
|
64
|
+
rdoc
|
65
|
+
tag-changelog!
|
66
|
+
|
67
|
+
BUNDLED WITH
|
68
|
+
1.13.6
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# tag-changelog
|
2
|
+
|
3
|
+
Tool to generate changelog based on Parallel6 specs
|
4
|
+
|
5
|
+
#### NAME
|
6
|
+
tag-changelog - Tool to generate changelog based on Parallel6 specs
|
7
|
+
|
8
|
+
#### SYNOPSIS
|
9
|
+
tag-changelog [global options] command [command options] [arguments...]
|
10
|
+
|
11
|
+
#### VERSION
|
12
|
+
0.0.1
|
13
|
+
|
14
|
+
#### GLOBAL OPTIONS
|
15
|
+
--help - Show this message
|
16
|
+
--version - Display the program version
|
17
|
+
|
18
|
+
#### COMMANDS
|
19
|
+
generate - Generate changelog and write to CHANGELOG.md (default).
|
20
|
+
help - Shows a list of commands or help for one command
|
21
|
+
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
All you need to do is cd into project's directory where you need to generate
|
26
|
+
changelog and run:
|
27
|
+
|
28
|
+
```
|
29
|
+
$ tag-changelog generate
|
30
|
+
```
|
31
|
+
|
32
|
+
This will execute the `generate` command with the default params. Please see below
|
33
|
+
for a list of options you can pass to the command.
|
34
|
+
|
35
|
+
#### generate command options
|
36
|
+
-c, --config=file - Configuration file to categorize commit messages in YML format. Must be an absolute path. (default: gem's own config.yml)
|
37
|
+
-d, --dir=directory - Git repository directory (must be an absolute path). Defaults to working directory. (default: current working directory)
|
38
|
+
-f, --filter=regexp - Regexp to categorize commits from git log. (default: (\[+\s?+[cfbhrCFBHR]{1}+\s?+\]))
|
39
|
+
--[no-]group - Group commit messages in categories (defined in configuration file). (default: enabled)
|
40
|
+
--[no-]head - Include HEAD as a tag. Useful when new tag is not released yet (as a preview). Can be disabled. (default: enabled)
|
41
|
+
-o, --output=file - Output destination. (default: CHANGELOG.md)
|
42
|
+
--[no-]pull-requests-only - Only list merged pull requests. Can be disabled to list all commits. (default: enabled)
|
43
|
+
-s, --skip=tag_list - Skip tags (may be used more than once, default: none)
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rdoc/task'
|
5
|
+
require 'cucumber'
|
6
|
+
require 'cucumber/rake/task'
|
7
|
+
Rake::RDocTask.new do |rd|
|
8
|
+
rd.main = "README.rdoc"
|
9
|
+
rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
|
10
|
+
rd.title = 'Your application title'
|
11
|
+
end
|
12
|
+
|
13
|
+
spec = eval(File.read('changelog.gemspec'))
|
14
|
+
|
15
|
+
Gem::PackageTask.new(spec) do |pkg|
|
16
|
+
end
|
17
|
+
CUKE_RESULTS = 'results.html'
|
18
|
+
CLEAN << CUKE_RESULTS
|
19
|
+
desc 'Run features'
|
20
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
21
|
+
opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
|
22
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
23
|
+
t.cucumber_opts = opts
|
24
|
+
t.fork = false
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run features tagged as work-in-progress (@wip)'
|
28
|
+
Cucumber::Rake::Task.new('features:wip') do |t|
|
29
|
+
tag_opts = ' --tags ~@pending'
|
30
|
+
tag_opts = ' --tags @wip'
|
31
|
+
t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
|
32
|
+
t.fork = false
|
33
|
+
end
|
34
|
+
|
35
|
+
task :cucumber => :features
|
36
|
+
task 'cucumber:wip' => 'features:wip'
|
37
|
+
task :wip => 'features:wip'
|
38
|
+
require 'rake/testtask'
|
39
|
+
Rake::TestTask.new do |t|
|
40
|
+
t.libs << "test"
|
41
|
+
t.test_files = FileList['test/*_test.rb']
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => [:test,:features]
|
data/bin/tag-changelog
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
# begin # XXX: Remove this begin/rescue before distributing your app
|
4
|
+
require 'tag_changelog'
|
5
|
+
# rescue LoadError
|
6
|
+
# STDERR.puts "In development, you need to use `bundle exec bin/changelog` to run your app"
|
7
|
+
# STDERR.puts "At install-time, RubyGems will make sure lib, etc. are in the load path"
|
8
|
+
# STDERR.puts "Feel free to remove this message from bin/changelog now"
|
9
|
+
# exit 64
|
10
|
+
# end
|
11
|
+
|
12
|
+
include GLI::App
|
13
|
+
|
14
|
+
program_desc 'Tool to generate changelog based on Parallel6 specs'
|
15
|
+
|
16
|
+
version TagChangelog::VERSION
|
17
|
+
|
18
|
+
subcommand_option_handling :normal
|
19
|
+
arguments :strict
|
20
|
+
|
21
|
+
desc 'Generate changelog and write to CHANGELOG.md (default).'
|
22
|
+
command :generate do |c|
|
23
|
+
c.desc 'Configuration file to categorize commit messages in YML format. Must be an absolute path.'
|
24
|
+
c.default_value File.expand_path("../../lib/tag_changelog/templates/config.yml", __FILE__)
|
25
|
+
c.arg_name 'file'
|
26
|
+
c.flag [:c, :config]
|
27
|
+
|
28
|
+
c.desc 'Git repository directory (must be an absolute path). Defaults to working directory.'
|
29
|
+
c.default_value Dir.pwd
|
30
|
+
c.arg_name 'directory'
|
31
|
+
c.flag [:d, :dir]
|
32
|
+
|
33
|
+
c.desc 'Output destination.'
|
34
|
+
c.default_value 'CHANGELOG.md'
|
35
|
+
c.arg_name 'file'
|
36
|
+
c.flag [:o, :output]
|
37
|
+
|
38
|
+
c.desc 'Regexp to categorize commits from git log.'
|
39
|
+
c.default_value '(\[+\s?+[cfbhrCFBHR]{1}+\s?+\])'
|
40
|
+
c.arg_name 'regexp'
|
41
|
+
c.flag [:f, :filter]
|
42
|
+
|
43
|
+
c.desc 'Skip tags'
|
44
|
+
c.arg_name 'tag_list'
|
45
|
+
c.flag [:s, :skip], multiple: true
|
46
|
+
|
47
|
+
c.desc 'Group commit messages in categories (defined in configuration file).'
|
48
|
+
c.default_value true
|
49
|
+
c.switch "group"
|
50
|
+
|
51
|
+
c.desc 'Include HEAD as a tag. Useful when new tag is not released yet (as a preview). Can be disabled.'
|
52
|
+
c.default_value true
|
53
|
+
c.switch "head"
|
54
|
+
|
55
|
+
c.desc 'Only list merged pull requests. Can be disabled to list all commits.'
|
56
|
+
c.default_value true
|
57
|
+
c.switch "pull-requests-only"
|
58
|
+
|
59
|
+
c.action do |global_options,options,args|
|
60
|
+
# Your command logic here
|
61
|
+
# If you have any errors, just raise them
|
62
|
+
# raise "that command made no sense"
|
63
|
+
Dir.chdir(options[:dir]) do
|
64
|
+
puts "Changelog will be written to: #{[options[:dir], options[:output]].join('/')}"
|
65
|
+
TagChangelog::Generate.run(options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
pre do |global,command,options,args|
|
71
|
+
# Pre logic here
|
72
|
+
# Return true to proceed; false to abort and not call the
|
73
|
+
# chosen command
|
74
|
+
# Use skips_pre before a command to skip this block
|
75
|
+
# on that command only
|
76
|
+
# true
|
77
|
+
abort "FATAL: Git is not installed." unless Git::Git.is_installed?
|
78
|
+
Dir.chdir(options[:dir]) do
|
79
|
+
abort "FATAL: Not a git repository." unless Git::Git.is_git_repository?
|
80
|
+
abort "FATAL: No commits in git repository." if Git::Git.is_empty_repository?
|
81
|
+
true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
post do |global,command,options,args|
|
86
|
+
# Post logic here
|
87
|
+
# Use skips_post before a command to skip this
|
88
|
+
# block on that command only
|
89
|
+
end
|
90
|
+
|
91
|
+
on_error do |exception|
|
92
|
+
# Error logic here
|
93
|
+
# return false to skip default error handling
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
exit run(ARGV)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
|
3
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
4
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
5
|
+
|
6
|
+
Before do
|
7
|
+
# Using "announce" causes massive warnings on 1.9.2
|
8
|
+
@puts = true
|
9
|
+
@original_rubylib = ENV['RUBYLIB']
|
10
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
After do
|
14
|
+
ENV['RUBYLIB'] = @original_rubylib
|
15
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'tag_changelog/version'
|
3
|
+
|
4
|
+
# Add requires for other files you add to your project here, so
|
5
|
+
# you just need to require this one file in your bin file
|
6
|
+
require 'tag_changelog/git/git'
|
7
|
+
require 'tag_changelog/git/tag_list'
|
8
|
+
require 'tag_changelog/git/tag'
|
9
|
+
require 'tag_changelog/generate'
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# A class to manipulate output destination of changelog and to write its contents.
|
2
|
+
module TagChangelog
|
3
|
+
class Generate
|
4
|
+
def self.run(options)
|
5
|
+
new(options).run
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
@output = open_output_file
|
11
|
+
@tags_list = build_tags_list(options)
|
12
|
+
@filter = Regexp.new(options[:filter], true)
|
13
|
+
@commit_messages_filter = set_commits_filter(options)
|
14
|
+
@group = options[:group]
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
output << "# Changelog\n\n"
|
19
|
+
tags_list.each_cons(2) do |current_tag, previous_tag|
|
20
|
+
tag = Git::Tag.new(current_tag)
|
21
|
+
messages = get_commit_messages(previous_tag, current_tag)
|
22
|
+
output << "## #{tag.version}" + " (#{tag.date})\n"
|
23
|
+
output << messages.to_text
|
24
|
+
output << "\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :options,
|
31
|
+
:output,
|
32
|
+
:tags_list,
|
33
|
+
:filter,
|
34
|
+
:commit_messages_filter,
|
35
|
+
:group
|
36
|
+
|
37
|
+
def output_file_exists?
|
38
|
+
File.exists?(options[:output])
|
39
|
+
end
|
40
|
+
|
41
|
+
def open_output_file
|
42
|
+
puts "#{options[:output]} doesn't exist in #{options[:dir]}... creating it" unless output_file_exists?
|
43
|
+
File.open(options[:output], "w+")
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_tags_list(options)
|
47
|
+
Git::TagList.new(options[:head]).list.reject do |tag|
|
48
|
+
tag if options[:skip].include?(tag)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_commits_filter(options)
|
53
|
+
options["pull-requests-only"] ? 'Merge pull request' : nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_commit_messages(previous_tag, current_tag)
|
57
|
+
messages = Git::Git.get_filtered_messages(previous_tag,
|
58
|
+
current_tag,
|
59
|
+
commit_messages_filter).split("\n")
|
60
|
+
# if not filtering merged pull requests only
|
61
|
+
# we need to remove the commit sha (first 9 chars in each row)
|
62
|
+
messages = messages.map { |msg| msg[10..-1] } unless commit_messages_filter
|
63
|
+
messages = categorize_messages(messages, build_categories) if group
|
64
|
+
messages = MessageList.new(messages, group)
|
65
|
+
end
|
66
|
+
|
67
|
+
def categorize_messages(messages, categories)
|
68
|
+
uncategorized = categories.detect { |cat| cat["header"] == "Uncategorized" }
|
69
|
+
messages.each do |msg|
|
70
|
+
matching_category = categories.detect do |category|
|
71
|
+
next unless category["filters"]
|
72
|
+
category["filters"].map { |ftr| msg.include?(ftr) }.include?(true)
|
73
|
+
end
|
74
|
+
if matching_category
|
75
|
+
msg = msg.gsub!(filter, matching_category["bullet"])
|
76
|
+
matching_category["messages"].push(msg)
|
77
|
+
else
|
78
|
+
uncategorized["messages"].push("* #{msg}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
categories
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_categories
|
86
|
+
categories = YAML.load_file(options[:config])
|
87
|
+
categories.each { |category| category["messages"] = [] }
|
88
|
+
categories
|
89
|
+
end
|
90
|
+
|
91
|
+
class MessageList
|
92
|
+
attr_reader :messages, :grouped
|
93
|
+
|
94
|
+
def initialize(messages = [], grouped = true)
|
95
|
+
@messages = messages
|
96
|
+
@grouped = grouped
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_text
|
100
|
+
if grouped
|
101
|
+
messages.map do |category|
|
102
|
+
category["messages"].any? ? print_category(category) : nil
|
103
|
+
end.reject(&:nil?).join("")
|
104
|
+
else
|
105
|
+
print_lines(messages).reject(&:nil?).join("")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def print_category(category)
|
110
|
+
[
|
111
|
+
"#### #{category['header']}",
|
112
|
+
print_lines(category["messages"]).join(""),
|
113
|
+
].join("\n")
|
114
|
+
end
|
115
|
+
|
116
|
+
def print_lines(lines)
|
117
|
+
lines.map { |line| "#{line}\n" }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,152 @@
|
|
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
|
+
module Git
|
18
|
+
class Git
|
19
|
+
|
20
|
+
# Determines whether Git is installed
|
21
|
+
#
|
22
|
+
# @return [bool]
|
23
|
+
# True if Git is installed, false if not.
|
24
|
+
#
|
25
|
+
def self.is_installed?
|
26
|
+
`git --version`
|
27
|
+
$? == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
# Determines whether the (current) directory is a git repository
|
31
|
+
#
|
32
|
+
# @param [String] dir
|
33
|
+
# Directory to check; if nil, uses the current directory.
|
34
|
+
#
|
35
|
+
# @return [bool]
|
36
|
+
# True if the directory is a Git repository, false if not.
|
37
|
+
def self.is_git_repository?(dir = nil)
|
38
|
+
dir = Dir.pwd if dir.nil?
|
39
|
+
system("git status > /dev/null 2>&1")
|
40
|
+
$? == 0
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determines if the repository in the current directory is empty.
|
44
|
+
#
|
45
|
+
def self.is_empty_repository?
|
46
|
+
`git show HEAD > /dev/null 2>&1`
|
47
|
+
$? != 0
|
48
|
+
end
|
49
|
+
|
50
|
+
# Retrieves the name of the current branch.
|
51
|
+
#
|
52
|
+
# @return [String]
|
53
|
+
# Current branch.
|
54
|
+
def self.current_branch
|
55
|
+
`git name-rev --name-only HEAD`.strip
|
56
|
+
end
|
57
|
+
|
58
|
+
# Launches the text editor that Git uses for commit messages,
|
59
|
+
# and passes file as a command line argument to it.
|
60
|
+
#
|
61
|
+
# @see https://github.com/git/git/blob/master/editor.c
|
62
|
+
# Git's editor.c on GitHub
|
63
|
+
#
|
64
|
+
# @param [String] file
|
65
|
+
# Filename to pass to the editor.
|
66
|
+
#
|
67
|
+
# @return [int]
|
68
|
+
# Exit code of the editor process, or false if no editor found.
|
69
|
+
#
|
70
|
+
def self.launch_editor(file)
|
71
|
+
# const char *editor = getenv("GIT_EDITOR");
|
72
|
+
editor = ENV['GIT_EDITOR']
|
73
|
+
|
74
|
+
# const char *terminal = getenv("TERM");
|
75
|
+
terminal = ENV['TERM'];
|
76
|
+
|
77
|
+
# int terminal_is_dumb = !terminal || !strcmp(terminal, "dumb");
|
78
|
+
terminal_is_dumb = !terminal || terminal == 'dumb'
|
79
|
+
|
80
|
+
# if (!editor && editor_program)
|
81
|
+
editor = `git config --get core.editor`.rstrip if editor.nil? || editor.empty?
|
82
|
+
|
83
|
+
# if (!editor && !terminal_is_dumb)
|
84
|
+
# editor = getenv("VISUAL");
|
85
|
+
editor = ENV['VISUAL'] if (editor.nil? || editor.empty?) && !terminal_is_dumb
|
86
|
+
|
87
|
+
# if (!editor)
|
88
|
+
# editor = getenv("EDITOR");
|
89
|
+
editor = ENV['EDITOR'] if (editor.nil? || editor.empty?)
|
90
|
+
|
91
|
+
# if (!editor && terminal_is_dumb)
|
92
|
+
# return NULL;
|
93
|
+
# if (!editor)
|
94
|
+
# editor = DEFAULT_EDITOR;
|
95
|
+
# Use vi, Git's hard-coded default
|
96
|
+
editor = 'vi' if (editor.nil? || editor.empty?) && !terminal_is_dumb
|
97
|
+
|
98
|
+
if editor && !editor.empty?
|
99
|
+
system "#{editor} '#{file}'"
|
100
|
+
$?
|
101
|
+
else
|
102
|
+
false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Retrieves the first 99 lines of the annotation of a tag.
|
107
|
+
#
|
108
|
+
def self.get_tag_annotation(tag)
|
109
|
+
test_tag tag
|
110
|
+
`git tag --sort refname -l -n99 #{tag}`.rstrip
|
111
|
+
end
|
112
|
+
|
113
|
+
# Retrieves the author date of a tag
|
114
|
+
#
|
115
|
+
def self.get_tag_date(tag)
|
116
|
+
test_tag tag
|
117
|
+
`git log -1 --format=format:%ai #{tag}`
|
118
|
+
end
|
119
|
+
|
120
|
+
# Retrieves commit messages and filters them
|
121
|
+
# Todo: Armor this against code injection!
|
122
|
+
def self.get_filtered_messages(from_commit, to_commit, filter = nil)
|
123
|
+
if filter
|
124
|
+
`git log #{from_commit}..#{to_commit} -E --grep='#{filter}' --format=%b`
|
125
|
+
else
|
126
|
+
`git log #{from_commit}..#{to_commit} --oneline`
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Retrieves one commit message and filters it
|
131
|
+
# Todo: Armor this against code injection!
|
132
|
+
def self.get_filtered_message(commit, filter)
|
133
|
+
`git log #{commit} -E --grep='#{filter}' --format=%b`
|
134
|
+
end
|
135
|
+
|
136
|
+
@@tags = nil
|
137
|
+
|
138
|
+
# Ensures lazy loading of the tag list to enable calling code
|
139
|
+
# to change the working directory first.
|
140
|
+
def self.tags
|
141
|
+
@@tags = TagList.new unless @@tags
|
142
|
+
@@tags
|
143
|
+
end
|
144
|
+
|
145
|
+
# Tests if the given tag exists and fails if it doesn't
|
146
|
+
def self.test_tag(tag)
|
147
|
+
fail "Invalid tag: #{tag}" unless tags.list.include?(tag)
|
148
|
+
end
|
149
|
+
private_class_method :test_tag, :tags
|
150
|
+
end
|
151
|
+
end
|
152
|
+
# vim: nospell
|
@@ -0,0 +1,37 @@
|
|
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
|
+
|
17
|
+
module Git
|
18
|
+
# Represents a Git tag and its annotation.
|
19
|
+
class Tag
|
20
|
+
# Author commit date of the tag
|
21
|
+
attr_reader :date
|
22
|
+
|
23
|
+
# Tag version
|
24
|
+
attr_reader :version
|
25
|
+
|
26
|
+
# Gets change information for a specific tagged version.
|
27
|
+
#
|
28
|
+
# @param [String] tag
|
29
|
+
# Tag for which to instantiate the class.
|
30
|
+
def initialize(tag)
|
31
|
+
@version = tag
|
32
|
+
@date = Date.parse(Git.get_tag_date(tag))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# vim: nospell
|
@@ -0,0 +1,74 @@
|
|
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
|
+
module Git
|
21
|
+
class TagList
|
22
|
+
# Returns an array of tag names surrounded by HEAD
|
23
|
+
# at the top and the sha1 of the first commit at the
|
24
|
+
# bottom.
|
25
|
+
attr_reader :list
|
26
|
+
|
27
|
+
# Instantiates the tag list.
|
28
|
+
#
|
29
|
+
# @param [bool] include_head
|
30
|
+
# Indicates whether or not to include the most recent changes.
|
31
|
+
#
|
32
|
+
def initialize(include_head = true)
|
33
|
+
@include_head = include_head
|
34
|
+
@list = build_list
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the most recent tag in the git repository,
|
38
|
+
# or the sha1 of the initial commit if there is no tag.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
#
|
42
|
+
def latest_tag
|
43
|
+
# Index 0 is HEAD
|
44
|
+
# Index 1 is most recent tag or first commit
|
45
|
+
@list[1]
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Returns the sha1 of the initial commit.
|
51
|
+
# In fact, this function returns all parentless commits
|
52
|
+
# of the repository. Usually there should be not more than
|
53
|
+
# one such commit.
|
54
|
+
# See http://stackoverflow.com/a/1007545/270712
|
55
|
+
#
|
56
|
+
def get_initial_commit
|
57
|
+
`git rev-list --max-parents=0 HEAD`.chomp
|
58
|
+
end
|
59
|
+
|
60
|
+
# Builds a list of Git tags and encloses it with HEAD and the
|
61
|
+
# Sha-1 of the initial commit.
|
62
|
+
#
|
63
|
+
# @return [Array]
|
64
|
+
# Array of tags, surrounded by HEAD and the Sha-1 of the initial commit.
|
65
|
+
def build_list
|
66
|
+
tags = []
|
67
|
+
tags << get_initial_commit
|
68
|
+
tags += `git tag --sort v:refname`.split("\n").map { |s| s.rstrip }
|
69
|
+
tags << "HEAD" if @include_head
|
70
|
+
tags.reverse
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# vim: nospell
|
@@ -0,0 +1,37 @@
|
|
1
|
+
- bullet: "[F]"
|
2
|
+
filters:
|
3
|
+
- "[F]"
|
4
|
+
- "[ F ]"
|
5
|
+
- "[f]"
|
6
|
+
- "[ f ]"
|
7
|
+
header: "Features"
|
8
|
+
- bullet: "[C]"
|
9
|
+
filters:
|
10
|
+
- "[C]"
|
11
|
+
- "[ C ]"
|
12
|
+
- "[c]"
|
13
|
+
- "[ c ]"
|
14
|
+
header: "Configuration"
|
15
|
+
- bullet: "[B]"
|
16
|
+
filters:
|
17
|
+
- "[B]"
|
18
|
+
- "[ B ]"
|
19
|
+
- "[b]"
|
20
|
+
- "[ b ]"
|
21
|
+
header: "Bug Fixes"
|
22
|
+
- bullet: "[H]"
|
23
|
+
filters:
|
24
|
+
- "[H]"
|
25
|
+
- "[ H ]"
|
26
|
+
- "[h]"
|
27
|
+
- "[ h ]"
|
28
|
+
header: "Hotfixes"
|
29
|
+
- bullet: "[R]"
|
30
|
+
filters:
|
31
|
+
- "[R]"
|
32
|
+
- "[ R ]"
|
33
|
+
- "[r]"
|
34
|
+
- "[ r ]"
|
35
|
+
header: "Refactored"
|
36
|
+
- bullet: "[U]"
|
37
|
+
header: "Uncategorized"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','tag_changelog','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'tag-changelog'
|
5
|
+
s.version = TagChangelog::VERSION
|
6
|
+
s.license = 'MIT'
|
7
|
+
s.author = 'Parallel6'
|
8
|
+
s.email = 'contact@parallel6.com'
|
9
|
+
s.homepage = 'http://clinical6.com'
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.summary = 'Tool to generate changelog based on Parallel6 specs'
|
12
|
+
s.files = `git ls-files`.split("
|
13
|
+
")
|
14
|
+
s.require_paths << 'lib'
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.extra_rdoc_files = []
|
17
|
+
s.rdoc_options << '--title' << 'tag-changelog' << '--main' << 'README.rdoc' << '-ri'
|
18
|
+
s.bindir = 'bin'
|
19
|
+
s.executables << 'tag-changelog'
|
20
|
+
s.add_development_dependency('rake')
|
21
|
+
s.add_development_dependency('rdoc')
|
22
|
+
s.add_development_dependency('aruba')
|
23
|
+
s.add_development_dependency('pry')
|
24
|
+
s.add_runtime_dependency('gli','2.17.1')
|
25
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tag-changelog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Parallel6
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rdoc
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aruba
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: gli
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.17.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.17.1
|
83
|
+
description:
|
84
|
+
email: contact@parallel6.com
|
85
|
+
executables:
|
86
|
+
- tag-changelog
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- CHANGELOG.md
|
91
|
+
- Gemfile
|
92
|
+
- Gemfile.lock
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- bin/tag-changelog
|
96
|
+
- features/changelog.feature
|
97
|
+
- features/step_definitions/changelog_steps.rb
|
98
|
+
- features/support/env.rb
|
99
|
+
- lib/tag_changelog.rb
|
100
|
+
- lib/tag_changelog/generate.rb
|
101
|
+
- lib/tag_changelog/git/git.rb
|
102
|
+
- lib/tag_changelog/git/tag.rb
|
103
|
+
- lib/tag_changelog/git/tag_list.rb
|
104
|
+
- lib/tag_changelog/templates/config.yml
|
105
|
+
- lib/tag_changelog/version.rb
|
106
|
+
- tag-changelog.gemspec
|
107
|
+
- test/default_test.rb
|
108
|
+
- test/test_helper.rb
|
109
|
+
homepage: http://clinical6.com
|
110
|
+
licenses:
|
111
|
+
- MIT
|
112
|
+
metadata: {}
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options:
|
115
|
+
- "--title"
|
116
|
+
- tag-changelog
|
117
|
+
- "--main"
|
118
|
+
- README.rdoc
|
119
|
+
- "-ri"
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 2.5.1
|
136
|
+
signing_key:
|
137
|
+
specification_version: 4
|
138
|
+
summary: Tool to generate changelog based on Parallel6 specs
|
139
|
+
test_files: []
|