From b023c9b0e8b0948e44e42f9ee74ff7d6f24fa68a Mon Sep 17 00:00:00 2001 From: Jonathan Hoyt Date: Mon, 23 Apr 2018 09:12:28 -0700 Subject: [PATCH 1/5] Add failing test --- spec/dotenv/parser_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/dotenv/parser_spec.rb b/spec/dotenv/parser_spec.rb index e1b7dc1d..9b43b94d 100644 --- a/spec/dotenv/parser_spec.rb +++ b/spec/dotenv/parser_spec.rb @@ -147,6 +147,10 @@ def env(string) expect(env("\n\n\n # HERE GOES FOO \nfoo=bar")).to eql("foo" => "bar") end + it "ignores commented out variables" do + expect(env("# HELLO=world\n")).to eql({}) + end + it "parses # in quoted values" do expect(env('foo="ba#r"')).to eql("foo" => "ba#r") expect(env("foo='ba#r'")).to eql("foo" => "ba#r") From 294ab7bce28b6d3d946b7fdfa7e919514cffdda9 Mon Sep 17 00:00:00 2001 From: Jonathan Hoyt Date: Mon, 23 Apr 2018 09:13:15 -0700 Subject: [PATCH 2/5] Add second failing test --- spec/dotenv/parser_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/dotenv/parser_spec.rb b/spec/dotenv/parser_spec.rb index 9b43b94d..b1b8f80d 100644 --- a/spec/dotenv/parser_spec.rb +++ b/spec/dotenv/parser_spec.rb @@ -151,6 +151,10 @@ def env(string) expect(env("# HELLO=world\n")).to eql({}) end + it "ignores comment" do + expect(env("# Uncomment to activate:\n")).to eql({}) + end + it "parses # in quoted values" do expect(env('foo="ba#r"')).to eql("foo" => "ba#r") expect(env("foo='ba#r'")).to eql("foo" => "ba#r") From 7366df80ba16c1f151434ceb9a1f6024938087cd Mon Sep 17 00:00:00 2001 From: Jonathan Hoyt Date: Mon, 23 Apr 2018 09:17:48 -0700 Subject: [PATCH 3/5] Revert https://github.com/bkeepers/dotenv/pull/318 --- lib/dotenv/parser.rb | 22 +++++++++++----------- spec/dotenv/parser_spec.rb | 38 -------------------------------------- 2 files changed, 11 insertions(+), 49 deletions(-) diff --git a/lib/dotenv/parser.rb b/lib/dotenv/parser.rb index be770ed6..c287a480 100644 --- a/lib/dotenv/parser.rb +++ b/lib/dotenv/parser.rb @@ -12,19 +12,21 @@ class Parser [Dotenv::Substitutions::Variable, Dotenv::Substitutions::Command] LINE = / + \A \s* (?:export\s+)? # optional export ([\w\.]+) # key (?:\s*=\s*|:\s+?) # separator ( # optional value begin - '(?:\\'|[^'])*' # single quoted value + '(?:\'|[^'])*' # single quoted value | # or - "(?:\\"|[^"])*" # double quoted value + "(?:\"|[^"])*" # double quoted value | # or - [^#\r\n]+ # unquoted value + [^#\n]+ # unquoted value )? # value end \s* (?:\#.*)? # optional comment + \z /x class << self @@ -42,12 +44,7 @@ def initialize(string, is_load) end def call - # Process matches - @string.scan(LINE).each do |key, value| - @hash[key] = parse_value(value || "") - end - # Process non-matches - @string.gsub(LINE, "").split(/[\n\r]+/).each do |line| + @string.split(/[\n\r]+/).each do |line| parse_line(line) end @hash @@ -56,7 +53,10 @@ def call private def parse_line(line) - if line.split.first == "export" + if (match = line.match(LINE)) + key, value = match.captures + @hash[key] = parse_value(value || "") + elsif line.split.first == "export" if variable_not_set?(line) raise FormatError, "Line #{line.inspect} has an unset variable" end @@ -65,7 +65,7 @@ def parse_line(line) def parse_value(value) # Remove surrounding quotes - value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2') + value = value.strip.sub(/\A(['"])(.*)\1\z/, '\2') if Regexp.last_match(1) == '"' value = unescape_characters(expand_newlines(value)) diff --git a/spec/dotenv/parser_spec.rb b/spec/dotenv/parser_spec.rb index b1b8f80d..af7a06d7 100644 --- a/spec/dotenv/parser_spec.rb +++ b/spec/dotenv/parser_spec.rb @@ -169,44 +169,6 @@ def env(string) expect(env("foo=")).to eql("foo" => "") end - it "allows multi-line values in single quotes" do - env_file = %(OPTION_A=first line -export OPTION_B='line 1 -line 2 -line 3' -OPTION_C="last line" -OPTION_ESCAPED='line one -this is \\'quoted\\' -one more line') - - expected_result = { - "OPTION_A" => "first line", - "OPTION_B" => "line 1\nline 2\nline 3", - "OPTION_C" => "last line", - "OPTION_ESCAPED" => "line one\nthis is \\'quoted\\'\none more line" - } - expect(env(env_file)).to eql(expected_result) - end - - it "allows multi-line values in double quotes" do - env_file = %(OPTION_A=first line -export OPTION_B="line 1 -line 2 -line 3" -OPTION_C="last line" -OPTION_ESCAPED="line one -this is \\"quoted\\" -one more line") - - expected_result = { - "OPTION_A" => "first line", - "OPTION_B" => "line 1\nline 2\nline 3", - "OPTION_C" => "last line", - "OPTION_ESCAPED" => "line one\nthis is \"quoted\"\none more line" - } - expect(env(env_file)).to eql(expected_result) - end - if RUBY_VERSION > "1.8.7" it "parses shell commands interpolated in $()" do expect(env("echo=$(echo hello)")).to eql("echo" => "hello") From 14eae148d521995cc416393961d2b9ed3166a28e Mon Sep 17 00:00:00 2001 From: Jonathan Hoyt Date: Mon, 23 Apr 2018 20:49:36 -0700 Subject: [PATCH 4/5] Revert https://github.com/bkeepers/dotenv/pull/329 --- README.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/README.md b/README.md index d621a980..d350361f 100644 --- a/README.md +++ b/README.md @@ -116,21 +116,9 @@ export SECRET_KEY=YOURSECRETKEYGOESHERE If you need multiline variables, for example private keys, you can double quote strings and use the `\n` character for newlines: ```shell -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nHkVN9...\n-----END DSA PRIVATE KEY-----\n" +PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nHkVN9…\n-----END DSA PRIVATE KEY-----\n" ``` -Alternatively, multi-line values with line breaks are now supported for quoted values. - -```shell -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- -... -HkVN9... -... ------END DSA PRIVATE KEY-----" -``` - -This is particularly helpful when using the Heroku command line plugin [`heroku-config`](https://github.com/xavdid/heroku-config) to pull configuration variables down that may have line breaks. - ### Command Substitution You need to add the output of a command in one of your variables? Simply add it with `$(your_command)`: From 9ef782c6fa591e342cd3d95e5b900f3664cfc442 Mon Sep 17 00:00:00 2001 From: Jonathan Hoyt Date: Mon, 23 Apr 2018 20:59:11 -0700 Subject: [PATCH 5/5] Version 2.4.0 and update Changelog.md --- Changelog.md | 8 +++++++- lib/dotenv/version.rb | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index f60dfb82..28f8d9ee 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,12 @@ # Changelog -[Unreleased changes](https://github.com/bkeepers/dotenv/compare/v2.3.0...master) +[Unreleased changes](https://github.com/bkeepers/dotenv/compare/v2.4.0...master) + +## 2.4.0 - Apr 23, 2018 + +This release reverts `Parse multiline values` ([#318](https://github.com/bkeepers/dotenv/pull/318), [#329](https://github.com/bkeepers/dotenv/pull/329)) due to a parsing regression that was discovered after the last release ([#336](https://github.com/bkeepers/dotenv/issues/336), [#339](https://github.com/bkeepers/dotenv/issues/339), [#341](https://github.com/bkeepers/dotenv/issues/341)). + +[Full Changelog](https://github.com/bkeepers/dotenv/compare/v2.3.0...v2.4.0) ## 2.3.0 - Apr 19, 2018 diff --git a/lib/dotenv/version.rb b/lib/dotenv/version.rb index 1ba37463..6bfe634d 100644 --- a/lib/dotenv/version.rb +++ b/lib/dotenv/version.rb @@ -1,3 +1,3 @@ module Dotenv - VERSION = "2.3.0".freeze + VERSION = "2.4.0".freeze end