diff --git a/lib/github_changelog_generator/generator/generator_tags.rb b/lib/github_changelog_generator/generator/generator_tags.rb index 51d0c2b..9c8fd9d 100644 --- a/lib/github_changelog_generator/generator/generator_tags.rb +++ b/lib/github_changelog_generator/generator/generator_tags.rb @@ -7,35 +7,43 @@ module GitHubChangelogGenerator detect_since_tag detect_due_tag - all_tags = @fetcher.get_all_tags - included_tags = filter_excluded_tags(all_tags) - + all_tags = @fetcher.get_all_tags fetch_tags_dates(all_tags) # Creates a Hash @tag_times_hash - @sorted_tags = sort_tags_by_date(included_tags) - @filtered_tags = get_filtered_tags(included_tags) + all_sorted_tags = sort_tags_by_date(all_tags) - @tag_section_mapping = build_tag_section_mapping(@filtered_tags, sorted_tags) + @sorted_tags = filter_excluded_tags(all_sorted_tags) + @filtered_tags = get_filtered_tags(@sorted_tags) + + # Because we need to properly create compare links, we need a sorted list + # of all filtered tags (including the excluded ones). We'll exclude those + # tags from section headers inside the mapping function. + section_tags = get_filtered_tags(all_sorted_tags) + + @tag_section_mapping = build_tag_section_mapping(section_tags, @filtered_tags) @filtered_tags end - # @param [Array] filtered_tags are the tags that need a subsection output - # @param [Array] all_tags is the list of all tags ordered from newest -> oldest + # @param [Array] section_tags are the tags that need a subsection output + # @param [Array] filtered_tags is the list of filtered tags ordered from newest -> oldest # @return [Hash] key is the tag to output, value is an array of [Left Tag, Right Tag] # PRs to include in this section will be >= [Left Tag Date] and <= [Right Tag Date] # rubocop:disable Style/For - for allows us to be more concise - def build_tag_section_mapping(filtered_tags, _all_tags) + def build_tag_section_mapping(section_tags, filtered_tags) tag_mapping = {} - for i in 0..(filtered_tags.length - 1) - tag = filtered_tags[i] + for i in 0..(section_tags.length - 1) + tag = section_tags[i] # Don't create section header for the "since" tag next if @since_tag && tag["name"] == @since_tag # Don't create a section header for the first tag in between_tags - next if options[:between_tags] && tag == filtered_tags.last + next if options[:between_tags] && tag == section_tags.last - older_tag = filtered_tags[i + 1] + # Don't create a section header for excluded tags + next unless filtered_tags.include?(tag) + + older_tag = section_tags[i + 1] tag_mapping[tag] = [older_tag, tag] end tag_mapping diff --git a/spec/unit/generator/generator_tags_spec.rb b/spec/unit/generator/generator_tags_spec.rb index 8791a05..70d0d80 100644 --- a/spec/unit/generator/generator_tags_spec.rb +++ b/spec/unit/generator/generator_tags_spec.rb @@ -14,13 +14,21 @@ describe GitHubChangelogGenerator::Generator do end describe "#build_tag_section_mapping" do - let(:sorted_tags) { tags_from_strings(%w(8 7 6 5 4 3 2 1)) } - let(:filtered_tags) { generator.get_filtered_tags(sorted_tags) } + let(:all_tags) { tags_from_strings(%w(8 7 6 5 4 3 2 1)) } + let(:sorted_tags) { all_tags } + let(:options) { {} } let(:generator) { GitHubChangelogGenerator::Generator.new(options) } + before do + allow_any_instance_of(GitHubChangelogGenerator::OctoFetcher).to receive(:get_all_tags).and_return(all_tags) + allow(generator).to receive(:fetch_tags_dates).with(all_tags) + allow(generator).to receive(:sort_tags_by_date).with(all_tags).and_return(sorted_tags) + generator.fetch_and_filter_tags + end + subject do - generator.build_tag_section_mapping(filtered_tags, sorted_tags) + generator.tag_section_mapping end shared_examples_for "a section mapping" do @@ -45,6 +53,20 @@ describe GitHubChangelogGenerator::Generator do it_behaves_like "a section mapping" end + shared_examples_for "a changelog with some exclusions" do + let(:expected_mapping) do + { + tag_with_name("8") => [tag_with_name("7"), tag_with_name("8")], + tag_with_name("6") => [tag_with_name("5"), tag_with_name("6")], + tag_with_name("4") => [tag_with_name("3"), tag_with_name("4")], + tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")], + tag_with_name("1") => [nil, tag_with_name("1")] + } + end + + it_behaves_like "a section mapping" + end + context "with no constraints" do it_behaves_like "a full changelog" end @@ -120,6 +142,26 @@ describe GitHubChangelogGenerator::Generator do it_behaves_like "a section mapping" end + + context "with excluded tags" do + context "as a list of strings" do + let(:options) { { exclude_tags: %w(2 5 7) } } + + it_behaves_like "a changelog with some exclusions" + end + + context "as a regex" do + let(:options) { { exclude_tags: /[257]/ } } + + it_behaves_like "a changelog with some exclusions" + end + + context "as a regex string" do + let(:options) { { exclude_tags_regex: "[257]" } } + + it_behaves_like "a changelog with some exclusions" + end + end end describe "#filter_between_tags" do