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.
Files changed (62) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +332 -285
  4. data/Rakefile +1 -1
  5. data/bin/git-generate-changelog +1 -1
  6. data/lib/github_changelog_generator.rb +10 -6
  7. data/lib/github_changelog_generator/generator/entry.rb +218 -0
  8. data/lib/github_changelog_generator/generator/generator.rb +124 -125
  9. data/lib/github_changelog_generator/generator/generator_fetcher.rb +139 -23
  10. data/lib/github_changelog_generator/generator/generator_processor.rb +59 -27
  11. data/lib/github_changelog_generator/generator/generator_tags.rb +25 -21
  12. data/lib/github_changelog_generator/generator/section.rb +124 -0
  13. data/lib/github_changelog_generator/helper.rb +1 -1
  14. data/lib/github_changelog_generator/octo_fetcher.rb +233 -96
  15. data/lib/github_changelog_generator/options.rb +74 -2
  16. data/lib/github_changelog_generator/parser.rb +118 -74
  17. data/lib/github_changelog_generator/parser_file.rb +7 -3
  18. data/lib/github_changelog_generator/reader.rb +2 -2
  19. data/lib/github_changelog_generator/task.rb +4 -3
  20. data/lib/github_changelog_generator/version.rb +1 -1
  21. data/man/git-generate-changelog.1 +144 -45
  22. data/man/git-generate-changelog.1.html +157 -84
  23. data/man/git-generate-changelog.html +19 -7
  24. data/man/git-generate-changelog.md +151 -84
  25. data/spec/files/github-changelog-generator.md +114 -114
  26. data/spec/{install-gem-in-bundler.gemfile → install_gem_in_bundler.gemfile} +2 -0
  27. data/spec/spec_helper.rb +2 -6
  28. data/spec/unit/generator/entry_spec.rb +766 -0
  29. data/spec/unit/generator/generator_processor_spec.rb +103 -41
  30. data/spec/unit/generator/generator_spec.rb +47 -0
  31. data/spec/unit/generator/generator_tags_spec.rb +51 -24
  32. data/spec/unit/generator/section_spec.rb +34 -0
  33. data/spec/unit/octo_fetcher_spec.rb +247 -197
  34. data/spec/unit/options_spec.rb +24 -0
  35. data/spec/unit/parse_file_spec.rb +2 -2
  36. data/spec/unit/reader_spec.rb +4 -4
  37. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
  38. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -1
  39. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -1
  40. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -1
  41. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -1
  42. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -1
  43. 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
  44. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -1
  45. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -1
  46. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -1
  47. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -1
  48. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -1
  49. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -1
  50. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -1
  51. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -1
  52. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -1
  53. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -1
  54. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -1
  55. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -1
  56. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -1
  57. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -1
  58. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -1
  59. metadata +71 -38
  60. data/bin/ghclgen +0 -5
  61. data/lib/github_changelog_generator/generator/generator_generation.rb +0 -180
  62. 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
- print " \r"
27
- threads << Thread.new do
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
- threads.each(&:join)
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
- issues.each_slice(MAX_THREAD_NUMBER) do |issues_slice|
42
- threads = []
43
- issues_slice.each do |issue|
44
- threads << Thread.new { find_closed_date_by_commit(issue) }
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
- threads.each(&:join)
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 labels with labels from options[:exclude_labels] array
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 [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
70
- # @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
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
- tag_in_range_new = if newer_tag_time.nil?
108
- true
109
- else
110
- time <= newer_tag_time
111
- end
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, t)
116
- tag_in_range_old = if older_tag_time.nil?
117
- true
118
- else
119
- t > older_tag_time
120
- end
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
- filtered_issues = filter_wo_labels(filtered_issues)
130
- filtered_issues
156
+ filter_wo_labels(filtered_issues)
131
157
  end
132
158
 
133
- # @return [Array] issues without labels or empty array if add_issues_wo_labels is false
134
- def filter_wo_labels(issues)
135
- if options[:add_issues_wo_labels]
136
- issues
137
- else
138
- issues.select { |issue| issue["labels"].map { |l| l["name"] }.any? }
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
- detect_since_tag
8
- detect_due_tag
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 = filter_excluded_tags(all_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 @since_tag && tag["name"] == @since_tag
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 detect_since_tag
96
+ def since_tag
102
97
  @since_tag ||= options.fetch(:since_tag) { version_of_first_item }
103
98
  end
104
99
 
105
- def detect_due_tag
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 = detect_since_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
- Helper.log.warn "Warning: can't find tag #{tag}, specified with --since-tag option."
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 = detect_due_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
- Helper.log.warn "Warning: can't find tag #{tag}, specified with --due-tag option."
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