github_changelog_generator 1.15.0.pre.beta → 1.16.1
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 +5 -5
- data/LICENSE +1 -1
- data/README.md +332 -285
- data/Rakefile +1 -1
- data/bin/git-generate-changelog +1 -1
- data/lib/github_changelog_generator.rb +10 -6
- data/lib/github_changelog_generator/generator/entry.rb +218 -0
- data/lib/github_changelog_generator/generator/generator.rb +124 -125
- data/lib/github_changelog_generator/generator/generator_fetcher.rb +139 -23
- data/lib/github_changelog_generator/generator/generator_processor.rb +59 -27
- data/lib/github_changelog_generator/generator/generator_tags.rb +25 -21
- data/lib/github_changelog_generator/generator/section.rb +124 -0
- data/lib/github_changelog_generator/helper.rb +1 -1
- data/lib/github_changelog_generator/octo_fetcher.rb +233 -96
- data/lib/github_changelog_generator/options.rb +74 -2
- data/lib/github_changelog_generator/parser.rb +118 -74
- data/lib/github_changelog_generator/parser_file.rb +7 -3
- data/lib/github_changelog_generator/reader.rb +2 -2
- data/lib/github_changelog_generator/task.rb +4 -3
- data/lib/github_changelog_generator/version.rb +1 -1
- data/man/git-generate-changelog.1 +144 -45
- data/man/git-generate-changelog.1.html +157 -84
- data/man/git-generate-changelog.html +19 -7
- data/man/git-generate-changelog.md +151 -84
- data/spec/files/github-changelog-generator.md +114 -114
- data/spec/{install-gem-in-bundler.gemfile → install_gem_in_bundler.gemfile} +2 -0
- data/spec/spec_helper.rb +2 -6
- data/spec/unit/generator/entry_spec.rb +766 -0
- data/spec/unit/generator/generator_processor_spec.rb +103 -41
- data/spec/unit/generator/generator_spec.rb +47 -0
- data/spec/unit/generator/generator_tags_spec.rb +51 -24
- data/spec/unit/generator/section_spec.rb +34 -0
- data/spec/unit/octo_fetcher_spec.rb +247 -197
- data/spec/unit/options_spec.rb +24 -0
- data/spec/unit/parse_file_spec.rb +2 -2
- data/spec/unit/reader_spec.rb +4 -4
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -1
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -1
- metadata +71 -38
- data/bin/ghclgen +0 -5
- data/lib/github_changelog_generator/generator/generator_generation.rb +0 -180
- data/spec/unit/generator/generator_generation_spec.rb +0 -73
@@ -2,14 +2,10 @@
|
|
2
2
|
|
3
3
|
module GitHubChangelogGenerator
|
4
4
|
class Generator
|
5
|
-
MAX_THREAD_NUMBER = 25
|
6
|
-
|
7
5
|
# Fetch event for issues and pull requests
|
8
6
|
# @return [Array] array of fetched issues
|
9
7
|
def fetch_events_for_issues_and_pr
|
10
|
-
if options[:verbose]
|
11
|
-
print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r"
|
12
|
-
end
|
8
|
+
print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r" if options[:verbose]
|
13
9
|
|
14
10
|
# Async fetching events:
|
15
11
|
@fetcher.fetch_events_async(@issues + @pull_requests)
|
@@ -18,34 +14,141 @@ module GitHubChangelogGenerator
|
|
18
14
|
# Async fetching of all tags dates
|
19
15
|
def fetch_tags_dates(tags)
|
20
16
|
print "Fetching tag dates...\r" if options[:verbose]
|
21
|
-
# Async fetching tags:
|
22
|
-
threads = []
|
23
17
|
i = 0
|
24
|
-
all = tags.count
|
25
18
|
tags.each do |tag|
|
26
|
-
|
27
|
-
|
28
|
-
get_time_of_tag(tag)
|
29
|
-
print "Fetching tags dates: #{i + 1}/#{all}\r" if options[:verbose]
|
30
|
-
i += 1
|
31
|
-
end
|
19
|
+
get_time_of_tag(tag)
|
20
|
+
i += 1
|
32
21
|
end
|
33
|
-
|
34
|
-
puts "Fetching tags dates: #{i}" if options[:verbose]
|
22
|
+
puts "Fetching tags dates: #{i}/#{tags.count}" if options[:verbose]
|
35
23
|
end
|
36
24
|
|
37
25
|
# Find correct closed dates, if issues was closed by commits
|
38
26
|
def detect_actual_closed_dates(issues)
|
39
27
|
print "Fetching closed dates for issues...\r" if options[:verbose]
|
40
28
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
29
|
+
i = 0
|
30
|
+
issues.each do |issue|
|
31
|
+
find_closed_date_by_commit(issue)
|
32
|
+
i += 1
|
33
|
+
end
|
34
|
+
puts "Fetching closed dates for issues: #{i}/#{issues.count}" if options[:verbose]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Adds a key "first_occurring_tag" to each PR with a value of the oldest
|
38
|
+
# tag that a PR's merge commit occurs in in the git history. This should
|
39
|
+
# indicate the release of each PR by git's history regardless of dates and
|
40
|
+
# divergent branches.
|
41
|
+
#
|
42
|
+
# @param [Array] tags The tags sorted by time, newest to oldest.
|
43
|
+
# @param [Array] prs The PRs to discover the tags of.
|
44
|
+
# @return [Nil] No return; PRs are updated in-place.
|
45
|
+
def add_first_occurring_tag_to_prs(tags, prs)
|
46
|
+
total = prs.count
|
47
|
+
|
48
|
+
prs_left = associate_tagged_prs(tags, prs, total)
|
49
|
+
prs_left = associate_release_branch_prs(prs_left, total)
|
50
|
+
prs_left = associate_rebase_comment_prs(tags, prs_left, total) if prs_left.any?
|
51
|
+
# PRs in prs_left will be untagged, not in release branch, and not
|
52
|
+
# rebased. They should not be included in the changelog as they probably
|
53
|
+
# have been merged to a branch other than the release branch.
|
54
|
+
@pull_requests -= prs_left
|
55
|
+
Helper.log.info "Associating PRs with tags: #{total}/#{total}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Associate merged PRs by the merge SHA contained in each tag. If the
|
59
|
+
# merge_commit_sha is not found in any tag's history, skip association.
|
60
|
+
#
|
61
|
+
# @param [Array] tags The tags sorted by time, newest to oldest.
|
62
|
+
# @param [Array] prs The PRs to associate.
|
63
|
+
# @return [Array] PRs without their merge_commit_sha in a tag.
|
64
|
+
def associate_tagged_prs(tags, prs, total)
|
65
|
+
@fetcher.fetch_tag_shas(tags)
|
66
|
+
|
67
|
+
i = 0
|
68
|
+
prs.reject do |pr|
|
69
|
+
found = false
|
70
|
+
# XXX Wish I could use merge_commit_sha, but gcg doesn't currently
|
71
|
+
# fetch that. See
|
72
|
+
# https://developer.github.com/v3/pulls/#get-a-single-pull-request vs.
|
73
|
+
# https://developer.github.com/v3/pulls/#list-pull-requests
|
74
|
+
if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" })
|
75
|
+
# Iterate tags.reverse (oldest to newest) to find first tag of each PR.
|
76
|
+
if (oldest_tag = tags.reverse.find { |tag| tag["shas_in_tag"].include?(event["commit_id"]) })
|
77
|
+
pr["first_occurring_tag"] = oldest_tag["name"]
|
78
|
+
found = true
|
79
|
+
i += 1
|
80
|
+
print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
|
81
|
+
end
|
82
|
+
else
|
83
|
+
# Either there were no events or no merged event. Github's api can be
|
84
|
+
# weird like that apparently. Check for a rebased comment before erroring.
|
85
|
+
no_events_pr = associate_rebase_comment_prs(tags, [pr], total)
|
86
|
+
raise StandardError, "No merge sha found for PR #{pr['number']} via the GitHub API" unless no_events_pr.empty?
|
87
|
+
|
88
|
+
found = true
|
89
|
+
i += 1
|
90
|
+
print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
|
45
91
|
end
|
46
|
-
|
92
|
+
found
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Associate merged PRs by the HEAD of the release branch. If no
|
97
|
+
# --release-branch was specified, then the github default branch is used.
|
98
|
+
#
|
99
|
+
# @param [Array] prs_left PRs not associated with any tag.
|
100
|
+
# @param [Integer] total The total number of PRs to associate; used for verbose printing.
|
101
|
+
# @return [Array] PRs without their merge_commit_sha in the branch.
|
102
|
+
def associate_release_branch_prs(prs_left, total)
|
103
|
+
if prs_left.any?
|
104
|
+
i = total - prs_left.count
|
105
|
+
prs_left.reject do |pr|
|
106
|
+
found = false
|
107
|
+
if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" }) && sha_in_release_branch(event["commit_id"])
|
108
|
+
found = true
|
109
|
+
i += 1
|
110
|
+
print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
|
111
|
+
end
|
112
|
+
found
|
113
|
+
end
|
114
|
+
else
|
115
|
+
prs_left
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Associate merged PRs by the SHA detected in github comments of the form
|
120
|
+
# "rebased commit: <sha>". For use when the merge_commit_sha is not in the
|
121
|
+
# actual git history due to rebase.
|
122
|
+
#
|
123
|
+
# @param [Array] tags The tags sorted by time, newest to oldest.
|
124
|
+
# @param [Array] prs_left The PRs not yet associated with any tag or branch.
|
125
|
+
# @return [Array] PRs without rebase comments.
|
126
|
+
def associate_rebase_comment_prs(tags, prs_left, total)
|
127
|
+
i = total - prs_left.count
|
128
|
+
# Any remaining PRs were not found in the list of tags by their merge
|
129
|
+
# commit and not found in any specified release branch. Fallback to
|
130
|
+
# rebased commit comment.
|
131
|
+
@fetcher.fetch_comments_async(prs_left)
|
132
|
+
prs_left.reject do |pr|
|
133
|
+
found = false
|
134
|
+
if pr["comments"] && (rebased_comment = pr["comments"].reverse.find { |c| c["body"].match(%r{rebased commit: ([0-9a-f]{40})}i) })
|
135
|
+
rebased_sha = rebased_comment["body"].match(%r{rebased commit: ([0-9a-f]{40})}i)[1]
|
136
|
+
if (oldest_tag = tags.reverse.find { |tag| tag["shas_in_tag"].include?(rebased_sha) })
|
137
|
+
pr["first_occurring_tag"] = oldest_tag["name"]
|
138
|
+
found = true
|
139
|
+
i += 1
|
140
|
+
elsif sha_in_release_branch(rebased_sha)
|
141
|
+
found = true
|
142
|
+
i += 1
|
143
|
+
else
|
144
|
+
raise StandardError, "PR #{pr['number']} has a rebased SHA comment but that SHA was not found in the release branch or any tags"
|
145
|
+
end
|
146
|
+
print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
|
147
|
+
else
|
148
|
+
puts "Warning: PR #{pr['number']} merge commit was not found in the release branch or tagged git history and no rebased SHA comment was found"
|
149
|
+
end
|
150
|
+
found
|
47
151
|
end
|
48
|
-
puts "Fetching closed dates for issues: Done!" if options[:verbose]
|
49
152
|
end
|
50
153
|
|
51
154
|
# Fill :actual_date parameter of specified issue by closed date of the commit, if it was closed by commit.
|
@@ -74,7 +177,7 @@ module GitHubChangelogGenerator
|
|
74
177
|
issue["actual_date"] = issue["closed_at"]
|
75
178
|
else
|
76
179
|
begin
|
77
|
-
commit = @fetcher.fetch_commit(event)
|
180
|
+
commit = @fetcher.fetch_commit(event["commit_id"])
|
78
181
|
issue["actual_date"] = commit["commit"]["author"]["date"]
|
79
182
|
|
80
183
|
# issue['actual_date'] = commit['author']['date']
|
@@ -84,5 +187,18 @@ module GitHubChangelogGenerator
|
|
84
187
|
end
|
85
188
|
end
|
86
189
|
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
# Detect if a sha occurs in the --release-branch. Uses the github repo
|
194
|
+
# default branch if not specified.
|
195
|
+
#
|
196
|
+
# @param [String] sha SHA to check.
|
197
|
+
# @return [Boolean] True if SHA is in the branch git history.
|
198
|
+
def sha_in_release_branch(sha)
|
199
|
+
branch = @options[:release_branch] || @fetcher.default_branch
|
200
|
+
shas_in_branch = @fetcher.commits_in_branch(branch)
|
201
|
+
shas_in_branch.include?(sha)
|
202
|
+
end
|
87
203
|
end
|
88
204
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module GitHubChangelogGenerator
|
4
4
|
class Generator
|
5
|
-
# delete all
|
5
|
+
# delete all issues with labels from options[:exclude_labels] array
|
6
6
|
# @param [Array] issues
|
7
7
|
# @return [Array] filtered array
|
8
8
|
def exclude_issues_by_labels(issues)
|
@@ -14,6 +14,19 @@ module GitHubChangelogGenerator
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# Only include issues without labels if options[:add_issues_wo_labels]
|
18
|
+
# @param [Array] issues
|
19
|
+
# @return [Array] filtered array
|
20
|
+
def exclude_issues_without_labels(issues)
|
21
|
+
return issues if issues.empty?
|
22
|
+
return issues if issues.first.key?("pull_request") && options[:add_pr_wo_labels]
|
23
|
+
return issues if !issues.first.key?("pull_request") && options[:add_issues_wo_labels]
|
24
|
+
|
25
|
+
issues.reject do |issue|
|
26
|
+
issue["labels"].empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
17
30
|
# @return [Array] filtered issues accourding milestone
|
18
31
|
def filter_by_milestone(filtered_issues, tag_name, all_issues)
|
19
32
|
remove_issues_in_milestones(filtered_issues)
|
@@ -56,6 +69,9 @@ module GitHubChangelogGenerator
|
|
56
69
|
# leave issues without milestones
|
57
70
|
if issue["milestone"].nil?
|
58
71
|
true
|
72
|
+
# remove issues of open milestones if option is set
|
73
|
+
elsif issue["milestone"]["state"] == "open"
|
74
|
+
@options[:issues_of_open_milestones]
|
59
75
|
else
|
60
76
|
# check, that this milestone in tag list:
|
61
77
|
@filtered_tags.find { |tag| tag["name"] == issue["milestone"]["title"] }.nil?
|
@@ -63,11 +79,22 @@ module GitHubChangelogGenerator
|
|
63
79
|
end
|
64
80
|
end
|
65
81
|
|
82
|
+
# Method filter issues, that belong only specified tag range
|
83
|
+
#
|
84
|
+
# @param [Array] issues issues to filter
|
85
|
+
# @param [Hash, Nil] newer_tag Tag to find PRs of. May be nil for unreleased section
|
86
|
+
# @return [Array] filtered issues
|
87
|
+
def filter_by_tag(issues, newer_tag = nil)
|
88
|
+
issues.select do |issue|
|
89
|
+
issue["first_occurring_tag"] == (newer_tag.nil? ? nil : newer_tag["name"])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
66
93
|
# Method filter issues, that belong only specified tag range
|
67
94
|
# @param [Array] issues issues to filter
|
68
95
|
# @param [Symbol] hash_key key of date value default is :actual_date
|
69
|
-
# @param [
|
70
|
-
# @param [
|
96
|
+
# @param [Hash, Nil] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
|
97
|
+
# @param [Hash, Nil] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
|
71
98
|
# @return [Array] filtered issues
|
72
99
|
def delete_by_time(issues, hash_key = "actual_date", older_tag = nil, newer_tag = nil)
|
73
100
|
# in case if not tags specified - return unchanged array
|
@@ -97,28 +124,28 @@ module GitHubChangelogGenerator
|
|
97
124
|
|
98
125
|
def ensure_older_tag(older_tag, newer_tag)
|
99
126
|
return older_tag if older_tag
|
127
|
+
|
100
128
|
idx = sorted_tags.index { |t| t["name"] == newer_tag["name"] }
|
101
129
|
# skip if we are already at the oldest element
|
102
130
|
return if idx == sorted_tags.size - 1
|
131
|
+
|
103
132
|
sorted_tags[idx - 1]
|
104
133
|
end
|
105
134
|
|
106
135
|
def tag_older_new_tag?(newer_tag_time, time)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
tag_in_range_new
|
136
|
+
if newer_tag_time.nil?
|
137
|
+
true
|
138
|
+
else
|
139
|
+
time <= newer_tag_time
|
140
|
+
end
|
113
141
|
end
|
114
142
|
|
115
|
-
def tag_newer_old_tag?(older_tag_time,
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
tag_in_range_old
|
143
|
+
def tag_newer_old_tag?(older_tag_time, time)
|
144
|
+
if older_tag_time.nil?
|
145
|
+
true
|
146
|
+
else
|
147
|
+
time > older_tag_time
|
148
|
+
end
|
122
149
|
end
|
123
150
|
|
124
151
|
# Include issues with labels, specified in :include_labels
|
@@ -126,37 +153,42 @@ module GitHubChangelogGenerator
|
|
126
153
|
# @return [Array] filtered array of issues
|
127
154
|
def include_issues_by_labels(issues)
|
128
155
|
filtered_issues = filter_by_include_labels(issues)
|
129
|
-
|
130
|
-
filtered_issues
|
156
|
+
filter_wo_labels(filtered_issues)
|
131
157
|
end
|
132
158
|
|
133
|
-
# @
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
159
|
+
# @param [Array] issues Issues & PRs to filter when without labels
|
160
|
+
# @return [Array] Issues & PRs without labels or empty array if
|
161
|
+
# add_issues_wo_labels or add_pr_wo_labels are false
|
162
|
+
def filter_wo_labels(items)
|
163
|
+
if items.any? && items.first.key?("pull_request")
|
164
|
+
return items if options[:add_pr_wo_labels]
|
165
|
+
elsif options[:add_issues_wo_labels]
|
166
|
+
return items
|
139
167
|
end
|
168
|
+
# The default is to filter items without labels
|
169
|
+
items.select { |item| item["labels"].map { |l| l["name"] }.any? }
|
140
170
|
end
|
141
171
|
|
172
|
+
# @todo Document this
|
142
173
|
def filter_by_include_labels(issues)
|
143
174
|
if options[:include_labels].nil?
|
144
175
|
issues
|
145
176
|
else
|
146
177
|
issues.select do |issue|
|
147
178
|
labels = issue["labels"].map { |l| l["name"] } & options[:include_labels]
|
148
|
-
labels.any?
|
179
|
+
labels.any? || issue["labels"].empty?
|
149
180
|
end
|
150
181
|
end
|
151
182
|
end
|
152
183
|
|
153
184
|
# General filtered function
|
154
185
|
#
|
155
|
-
# @param [Array] all_issues
|
186
|
+
# @param [Array] all_issues PRs or issues
|
156
187
|
# @return [Array] filtered issues
|
157
188
|
def filter_array_by_labels(all_issues)
|
158
189
|
filtered_issues = include_issues_by_labels(all_issues)
|
159
|
-
exclude_issues_by_labels(filtered_issues)
|
190
|
+
filtered_issues = exclude_issues_by_labels(filtered_issues)
|
191
|
+
exclude_issues_without_labels(filtered_issues)
|
160
192
|
end
|
161
193
|
|
162
194
|
# Filter issues according labels
|
@@ -4,22 +4,17 @@ module GitHubChangelogGenerator
|
|
4
4
|
class Generator
|
5
5
|
# fetch, filter tags, fetch dates and sort them in time order
|
6
6
|
def fetch_and_filter_tags
|
7
|
-
|
8
|
-
|
7
|
+
since_tag
|
8
|
+
due_tag
|
9
9
|
|
10
10
|
all_tags = @fetcher.get_all_tags
|
11
11
|
fetch_tags_dates(all_tags) # Creates a Hash @tag_times_hash
|
12
12
|
all_sorted_tags = sort_tags_by_date(all_tags)
|
13
13
|
|
14
|
-
@sorted_tags =
|
14
|
+
@sorted_tags = filter_included_tags(all_sorted_tags)
|
15
|
+
@sorted_tags = filter_excluded_tags(@sorted_tags)
|
15
16
|
@filtered_tags = get_filtered_tags(@sorted_tags)
|
16
|
-
|
17
|
-
# Because we need to properly create compare links, we need a sorted list
|
18
|
-
# of all filtered tags (including the excluded ones). We'll exclude those
|
19
|
-
# tags from section headers inside the mapping function.
|
20
|
-
section_tags = get_filtered_tags(all_sorted_tags)
|
21
|
-
|
22
|
-
@tag_section_mapping = build_tag_section_mapping(section_tags, @filtered_tags)
|
17
|
+
@tag_section_mapping = build_tag_section_mapping(@filtered_tags, @filtered_tags)
|
23
18
|
|
24
19
|
@filtered_tags
|
25
20
|
end
|
@@ -35,7 +30,7 @@ module GitHubChangelogGenerator
|
|
35
30
|
tag = section_tags[i]
|
36
31
|
|
37
32
|
# Don't create section header for the "since" tag
|
38
|
-
next if
|
33
|
+
next if since_tag && tag["name"] == since_tag
|
39
34
|
|
40
35
|
# Don't create a section header for the first tag in between_tags
|
41
36
|
next if options[:between_tags] && tag == section_tags.last
|
@@ -83,7 +78,7 @@ module GitHubChangelogGenerator
|
|
83
78
|
# @return [Array] link, name and time of the tag
|
84
79
|
def detect_link_tag_time(newer_tag)
|
85
80
|
# if tag is nil - set current time
|
86
|
-
newer_tag_time = newer_tag.nil? ? Time.new : get_time_of_tag(newer_tag)
|
81
|
+
newer_tag_time = newer_tag.nil? ? Time.new.getutc : get_time_of_tag(newer_tag)
|
87
82
|
|
88
83
|
# if it's future release tag - set this value
|
89
84
|
if newer_tag.nil? && options[:future_release]
|
@@ -98,11 +93,11 @@ module GitHubChangelogGenerator
|
|
98
93
|
end
|
99
94
|
|
100
95
|
# @return [Object] try to find newest tag using #Reader and :base option if specified otherwise returns nil
|
101
|
-
def
|
96
|
+
def since_tag
|
102
97
|
@since_tag ||= options.fetch(:since_tag) { version_of_first_item }
|
103
98
|
end
|
104
99
|
|
105
|
-
def
|
100
|
+
def due_tag
|
106
101
|
@due_tag ||= options.fetch(:due_tag, nil)
|
107
102
|
end
|
108
103
|
|
@@ -125,7 +120,7 @@ module GitHubChangelogGenerator
|
|
125
120
|
# @return [Array] filtered tags according :since_tag option
|
126
121
|
def filter_since_tag(all_tags)
|
127
122
|
filtered_tags = all_tags
|
128
|
-
tag =
|
123
|
+
tag = since_tag
|
129
124
|
if tag
|
130
125
|
if all_tags.map { |t| t["name"] }.include? tag
|
131
126
|
idx = all_tags.index { |t| t["name"] == tag }
|
@@ -135,7 +130,7 @@ module GitHubChangelogGenerator
|
|
135
130
|
[]
|
136
131
|
end
|
137
132
|
else
|
138
|
-
|
133
|
+
raise ChangelogGeneratorError, "Error: can't find tag #{tag}, specified with --since-tag option."
|
139
134
|
end
|
140
135
|
end
|
141
136
|
filtered_tags
|
@@ -145,7 +140,7 @@ module GitHubChangelogGenerator
|
|
145
140
|
# @return [Array] filtered tags according :due_tag option
|
146
141
|
def filter_due_tag(all_tags)
|
147
142
|
filtered_tags = all_tags
|
148
|
-
tag =
|
143
|
+
tag = due_tag
|
149
144
|
if tag
|
150
145
|
if all_tags.any? && all_tags.map { |t| t["name"] }.include?(tag)
|
151
146
|
idx = all_tags.index { |t| t["name"] == tag }
|
@@ -155,12 +150,23 @@ module GitHubChangelogGenerator
|
|
155
150
|
[]
|
156
151
|
end
|
157
152
|
else
|
158
|
-
|
153
|
+
raise ChangelogGeneratorError, "Error: can't find tag #{tag}, specified with --due-tag option."
|
159
154
|
end
|
160
155
|
end
|
161
156
|
filtered_tags
|
162
157
|
end
|
163
158
|
|
159
|
+
# @param [Array] all_tags all tags
|
160
|
+
# @return [Array] filtered tags according to :include_tags_regex option
|
161
|
+
def filter_included_tags(all_tags)
|
162
|
+
if options[:include_tags_regex]
|
163
|
+
regex = Regexp.new(options[:include_tags_regex])
|
164
|
+
all_tags.select { |tag| regex =~ tag["name"] }
|
165
|
+
else
|
166
|
+
all_tags
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
164
170
|
# @param [Array] all_tags all tags
|
165
171
|
# @return [Array] filtered tags according :exclude_tags or :exclude_tags_regex option
|
166
172
|
def filter_excluded_tags(all_tags)
|
@@ -208,9 +214,7 @@ module GitHubChangelogGenerator
|
|
208
214
|
end
|
209
215
|
|
210
216
|
def warn_if_tag_not_found(all_tags, tag)
|
211
|
-
unless all_tags.map { |t| t["name"] }.include?(tag)
|
212
|
-
Helper.log.warn "Warning: can't find tag #{tag}, specified with --exclude-tags option."
|
213
|
-
end
|
217
|
+
Helper.log.warn("Warning: can't find tag #{tag}, specified with --exclude-tags option.") unless all_tags.map { |t| t["name"] }.include?(tag)
|
214
218
|
end
|
215
219
|
end
|
216
220
|
end
|