diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index 40c2498..d08ddfe 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -3,29 +3,48 @@ require "pathname" module GitHubChangelogGenerator ParserError = Class.new(StandardError) + # ParserFile is a configuration file reader which sets options in the + # given Hash. + # + # In your project's root, you can put a file named + # .github_changelog_generator to override defaults: + # + # Example: + # header_label=# My Super Changelog + # future-release=5.0.0 + # since-tag=1.0.0 + # + # The configuration format is some-key=value or some_key=value. + # class ParserFile - FILENAME = ".github_changelog_generator" - - def initialize(options) + # @param options [Hash] options to be configured from file contents + # @param file [nil,IO] configuration file handle, defaults to opening `.github_changelog_generator` + def initialize(options, file = open_settings_file) @options = options + @file = file end - # Destructively change @options using data in configured options file. + # Sets options using configuration file content def parse! - file.each_line { |line| parse_line!(line) } if file.exist? + return unless @file + @file.each_with_index { |line, i| parse_line!(line, i + 1) } + @file.close end private - def file - @file ||= Pathname(File.expand_path(@options[:params_file] || FILENAME)) + FILENAME = ".github_changelog_generator" + + def open_settings_file + path = Pathname(File.expand_path(FILENAME)) + File.open(path) if path.exist? end - def parse_line!(line) + def parse_line!(line, line_number) option_name, value = extract_pair(line) @options[option_key_for(option_name)] = convert_value(value, option_name) rescue - raise ParserError, "Config file #{file} is incorrect in line \"#{line.gsub(/[\n\r]+/, '')}\"" + raise ParserError, "Failed on line ##{line_number}: \"#{line.gsub(/[\n\r]+/, '')}\"" end # Returns a the option name as a symbol and its string value sans newlines. diff --git a/spec/files/github_changelog_params_327 b/spec/files/github_changelog_params_327 deleted file mode 100644 index 2506a61..0000000 --- a/spec/files/github_changelog_params_327 +++ /dev/null @@ -1,2 +0,0 @@ -exclude-labels=73a91042-da6f-11e5-9335-1040f38d7f90,7adf83b4-da6f-11e5-ae18-1040f38d7f90 -header_label=# My changelog diff --git a/spec/files/github_changelog_params_empty b/spec/files/github_changelog_params_empty deleted file mode 100644 index e69de29..0000000 diff --git a/spec/files/github_changelog_params_incorrect b/spec/files/github_changelog_params_incorrect deleted file mode 100644 index 35fa3d8..0000000 --- a/spec/files/github_changelog_params_incorrect +++ /dev/null @@ -1,2 +0,0 @@ -unreleased_label: staging -unreleased: false diff --git a/spec/files/github_changelog_params_override b/spec/files/github_changelog_params_override deleted file mode 100644 index c31e411..0000000 --- a/spec/files/github_changelog_params_override +++ /dev/null @@ -1,3 +0,0 @@ -unreleased_label=staging -unreleased=false -header==== Changelog === diff --git a/spec/unit/parse_file_spec.rb b/spec/unit/parse_file_spec.rb index 2e4f1a6..735f32e 100644 --- a/spec/unit/parse_file_spec.rb +++ b/spec/unit/parse_file_spec.rb @@ -2,35 +2,39 @@ describe GitHubChangelogGenerator::ParserFile do describe ".github_changelog_generator" do context "when no has file" do let(:options) { {} } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options) } - subject { parse.parse! } + let(:parser) { GitHubChangelogGenerator::ParserFile.new(options) } + subject { parser.parse! } it { is_expected.to be_nil } end context "when file is empty" do - let(:options) { { params_file: "spec/files/github_changelog_params_empty" } } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options) } + let(:options) { {} } + let(:parser) { GitHubChangelogGenerator::ParserFile.new(options, StringIO.new("")) } it "does not change the options" do - expect { parse.parse! }.to_not change { options } + expect { parser.parse! }.to_not change { options } end end context "when file is incorrect" do - let(:options) { { params_file: "spec/files/github_changelog_params_incorrect" } } + let(:options) { {} } let(:options_before_change) { options.dup } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options) } - it { expect { parse.parse! }.to raise_error(GitHubChangelogGenerator::ParserError) } + let(:file) { StringIO.new("unreleased_label=staging\nunreleased: false") } + let(:parser) do + GitHubChangelogGenerator::ParserFile.new(options, file) + end + it { expect { parser.parse! }.to raise_error(/line #2/) } end context "when override default values" do let(:default_options) { GitHubChangelogGenerator::Parser.default_options } - let(:options) { { params_file: "spec/files/github_changelog_params_override" }.merge(default_options) } + let(:options) { {}.merge(default_options) } let(:options_before_change) { options.dup } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options) } + let(:file) { StringIO.new("unreleased_label=staging\nunreleased=false\nheader==== Changelog ===") } + let(:parser) { GitHubChangelogGenerator::ParserFile.new(options, file) } it "changes the options" do - expect { parse.parse! }.to change { options } + expect { parser.parse! }.to change { options } .from(options_before_change) .to(options_before_change.merge(unreleased_label: "staging", unreleased: false, @@ -38,21 +42,22 @@ describe GitHubChangelogGenerator::ParserFile do end context "turns exclude-labels into an Array", bug: '#327' do - let(:options) do - { - params_file: "spec/files/github_changelog_params_327" - } + let(:file) do + StringIO.new(<