From 93df2d56465fb658305e4b31e721fe5bfa10783f Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 13:59:58 +0100 Subject: [PATCH 1/9] ParserFile: use a File instead of a filename - spec: can use StringIOs instead of loose files --- lib/github_changelog_generator/parser_file.rb | 23 ++++++++++---- spec/files/github_changelog_params_327 | 2 -- spec/files/github_changelog_params_empty | 0 spec/files/github_changelog_params_incorrect | 2 -- spec/files/github_changelog_params_override | 3 -- spec/unit/parse_file_spec.rb | 31 +++++++++++-------- 6 files changed, 35 insertions(+), 26 deletions(-) delete mode 100644 spec/files/github_changelog_params_327 delete mode 100644 spec/files/github_changelog_params_empty delete mode 100644 spec/files/github_changelog_params_incorrect delete mode 100644 spec/files/github_changelog_params_override diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index 40c2498..a85d969 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -6,21 +6,32 @@ module GitHubChangelogGenerator class ParserFile FILENAME = ".github_changelog_generator" - def initialize(options) + attr_reader :file + + # @param options [Hash] + # @param file [nil,IO] + def initialize(options, file = read_default_file) @options = options + @file = file + end + + def read_default_file + File.open(path) if path.exist? + end + + def path + @path ||= Pathname(File.expand_path(FILENAME)) end # Destructively change @options using data in configured options file. def parse! - file.each_line { |line| parse_line!(line) } if file.exist? + return unless file + file.each_line { |line| parse_line!(line) } + file.close end private - def file - @file ||= Pathname(File.expand_path(@options[:params_file] || FILENAME)) - end - def parse_line!(line) option_name, value = extract_pair(line) @options[option_key_for(option_name)] = convert_value(value, option_name) 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..24171fc 100644 --- a/spec/unit/parse_file_spec.rb +++ b/spec/unit/parse_file_spec.rb @@ -8,8 +8,8 @@ describe GitHubChangelogGenerator::ParserFile do 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(:parse) { GitHubChangelogGenerator::ParserFile.new(options, StringIO.new("")) } it "does not change the options" do expect { parse.parse! }.to_not change { options } @@ -17,17 +17,21 @@ describe GitHubChangelogGenerator::ParserFile do 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) } + let(:file) { StringIO.new("unreleased_label: staging\nunreleased: false") } + let(:parse) do + GitHubChangelogGenerator::ParserFile.new(options, file) + end it { expect { parse.parse! }.to raise_error(GitHubChangelogGenerator::ParserError) } 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(:parse) { GitHubChangelogGenerator::ParserFile.new(options, file) } it "changes the options" do expect { parse.parse! }.to change { options } @@ -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(< Date: Sat, 19 Mar 2016 15:09:08 +0100 Subject: [PATCH 2/9] ParserFile: Drop unused public method --- lib/github_changelog_generator/parser_file.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index a85d969..0fc58e9 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -16,14 +16,11 @@ module GitHubChangelogGenerator end def read_default_file + path = Pathname(File.expand_path(FILENAME)) File.open(path) if path.exist? end - def path - @path ||= Pathname(File.expand_path(FILENAME)) - end - - # Destructively change @options using data in configured options file. + # Set @options using configuration file lines. def parse! return unless file file.each_line { |line| parse_line!(line) } From 2e8e2a62e18317b37a99c469c9322c8fabf9a885 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 15:13:12 +0100 Subject: [PATCH 3/9] ParserFile: removed public method --- lib/github_changelog_generator/parser_file.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index 0fc58e9..da50af1 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -6,8 +6,6 @@ module GitHubChangelogGenerator class ParserFile FILENAME = ".github_changelog_generator" - attr_reader :file - # @param options [Hash] # @param file [nil,IO] def initialize(options, file = read_default_file) @@ -22,9 +20,9 @@ module GitHubChangelogGenerator # Set @options using configuration file lines. def parse! - return unless file - file.each_line { |line| parse_line!(line) } - file.close + return unless @file + @file.each_line { |line| parse_line!(line) } + @file.close end private @@ -33,7 +31,7 @@ module GitHubChangelogGenerator 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, "Config file problem on line \"#{line.gsub(/[\n\r]+/, '')}\"" end # Returns a the option name as a symbol and its string value sans newlines. From 29b5ef3d53926734bffe23c900be75bfe0ac0227 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 15:18:20 +0100 Subject: [PATCH 4/9] ParserFile: config failure line number --- lib/github_changelog_generator/parser_file.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index da50af1..c36b6ae 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -21,17 +21,17 @@ module GitHubChangelogGenerator # Set @options using configuration file lines. def parse! return unless @file - @file.each_line { |line| parse_line!(line) } + @file.each_with_index { |line, i| parse_line!(line, i + 1) } @file.close end private - 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 problem on line \"#{line.gsub(/[\n\r]+/, '')}\"" + raise ParserError, "Config file parsing failed on line ##{line_number}: \"#{line.gsub(/[\n\r]+/, '')}\"" end # Returns a the option name as a symbol and its string value sans newlines. From a997d2417d71bf92c438627b8110a2e8aff68314 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 15:20:48 +0100 Subject: [PATCH 5/9] Spec: Config parse fail message tested --- spec/unit/parse_file_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/unit/parse_file_spec.rb b/spec/unit/parse_file_spec.rb index 24171fc..5eac4c4 100644 --- a/spec/unit/parse_file_spec.rb +++ b/spec/unit/parse_file_spec.rb @@ -19,11 +19,11 @@ describe GitHubChangelogGenerator::ParserFile do context "when file is incorrect" do let(:options) { {} } let(:options_before_change) { options.dup } - let(:file) { StringIO.new("unreleased_label: staging\nunreleased: false") } + let(:file) { StringIO.new("unreleased_label=staging\nunreleased: false") } let(:parse) do GitHubChangelogGenerator::ParserFile.new(options, file) end - it { expect { parse.parse! }.to raise_error(GitHubChangelogGenerator::ParserError) } + it { expect { parse.parse! }.to raise_error(/line #2/) } end context "when override default values" do From 0b3248418441ac68a09621e49a61052800a06e4b Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 15:22:45 +0100 Subject: [PATCH 6/9] Spec: rename local to noun --- spec/unit/parse_file_spec.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/unit/parse_file_spec.rb b/spec/unit/parse_file_spec.rb index 5eac4c4..735f32e 100644 --- a/spec/unit/parse_file_spec.rb +++ b/spec/unit/parse_file_spec.rb @@ -2,17 +2,17 @@ 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) { {} } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options, StringIO.new("")) } + 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 @@ -20,10 +20,10 @@ describe GitHubChangelogGenerator::ParserFile do let(:options) { {} } let(:options_before_change) { options.dup } let(:file) { StringIO.new("unreleased_label=staging\nunreleased: false") } - let(:parse) do + let(:parser) do GitHubChangelogGenerator::ParserFile.new(options, file) end - it { expect { parse.parse! }.to raise_error(/line #2/) } + it { expect { parser.parse! }.to raise_error(/line #2/) } end context "when override default values" do @@ -31,10 +31,10 @@ describe GitHubChangelogGenerator::ParserFile do let(:options) { {}.merge(default_options) } let(:options_before_change) { options.dup } let(:file) { StringIO.new("unreleased_label=staging\nunreleased=false\nheader==== Changelog ===") } - let(:parse) { GitHubChangelogGenerator::ParserFile.new(options, file) } + 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, @@ -50,13 +50,13 @@ EOF ) end it "reads exclude_labels into an Array" do - expect { parse.parse! }.to change { options[:exclude_labels] } + expect { parser.parse! }.to change { options[:exclude_labels] } .from(default_options[:exclude_labels]) .to(["73a91042-da6f-11e5-9335-1040f38d7f90", "7adf83b4-da6f-11e5-ae18-1040f38d7f90"]) end it "translates given header_label into the :header option" do - expect { parse.parse! }.to change { options[:header] } + expect { parser.parse! }.to change { options[:header] } .from(default_options[:header]) .to("# My changelog") end From 6b64d4e4a20e55be2d7b9bca70335d29f6310c11 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 15:50:05 +0100 Subject: [PATCH 7/9] Docs --- lib/github_changelog_generator/parser_file.rb | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index c36b6ae..d71a71b 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -3,22 +3,28 @@ 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" - - # @param options [Hash] - # @param file [nil,IO] + # @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 = read_default_file) @options = options @file = file end - def read_default_file - path = Pathname(File.expand_path(FILENAME)) - File.open(path) if path.exist? - end - - # Set @options using configuration file lines. + # Sets options using configuration file content def parse! return unless @file @file.each_with_index { |line, i| parse_line!(line, i + 1) } @@ -27,6 +33,13 @@ module GitHubChangelogGenerator private + FILENAME = ".github_changelog_generator" + + def read_default_file + path = Pathname(File.expand_path(FILENAME)) + File.open(path) if path.exist? + end + def parse_line!(line, line_number) option_name, value = extract_pair(line) @options[option_key_for(option_name)] = convert_value(value, option_name) From 1a289c872dd8172ba71ed760f3b13cf3313df533 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 16:09:34 +0100 Subject: [PATCH 8/9] ParserFile: rename private method --- lib/github_changelog_generator/parser_file.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index d71a71b..f5097d4 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -19,7 +19,7 @@ module GitHubChangelogGenerator class ParserFile # @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 = read_default_file) + def initialize(options, file = open_settings_file) @options = options @file = file end @@ -35,7 +35,7 @@ module GitHubChangelogGenerator FILENAME = ".github_changelog_generator" - def read_default_file + def open_settings_file path = Pathname(File.expand_path(FILENAME)) File.open(path) if path.exist? end From 7c2b95d24b48fcdbb2a675eb44abfe2567d8e0d3 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Sat, 19 Mar 2016 16:17:10 +0100 Subject: [PATCH 9/9] ParserFile: shorter error message due to context --- lib/github_changelog_generator/parser_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/github_changelog_generator/parser_file.rb b/lib/github_changelog_generator/parser_file.rb index f5097d4..d08ddfe 100644 --- a/lib/github_changelog_generator/parser_file.rb +++ b/lib/github_changelog_generator/parser_file.rb @@ -44,7 +44,7 @@ module GitHubChangelogGenerator option_name, value = extract_pair(line) @options[option_key_for(option_name)] = convert_value(value, option_name) rescue - raise ParserError, "Config file parsing failed on line ##{line_number}: \"#{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.