Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #64 Multiline variables #65

Closed
wants to merge 9 commits into from

Conversation

esttorhe
Copy link

@esttorhe esttorhe commented Dec 19, 2018

Fixes #64

This PR handles multi-line values by single quote delimiter '.

The parsing of the whole .env file is pretty naive (as expressed in the README) but does the work. I tried to add as little code as possible and change as little as possible just to support this.

All tests are passing and 3 new ones were added (1 success and 2 different failing scenarios)

@esttorhe
Copy link
Author

Hold on reviewing; I identified an edge case that needs to be addressed first

@kiambogo
Copy link

Any update on this? Also experiencing this issue. What was the edge case you found?

@esttorhe
Copy link
Author

@kiambogo this fix works perfect unless you have = inside the multiline value.

Unfortunately the current implementation for identifying keys and values is pretty naive; I tried «piggy backing» on top of the current implementation and just tried to add support for multi-line; the problem is that this implementation relies on finding the next «key-value pair» in order to close the multiline value; thus, if you have a = inside the algorithm will assume you got a new key-value pair and will cut the parsing short returning an incorrect value for the key and generating a new and invalid key-value pair from the env

@kiambogo
Copy link

Thanks for the info @esttorhe ! Bummer, as I'm trying to add a PEM encoded RSA private key which indeed includes = in its value. I would think that a solution could be to wrap the value in quotation marks to aid in identifying when the value has ended. As you mentioned if the current implementation is pretty naive I'm guessing that it would have to be heavily refactored to take this into account.

@esttorhe
Copy link
Author

@kiambogo same use case as me; that's why I added the support and noticed the issue.

I think the naive implementation could still be used for a first version just requiring the use of either " or ' to signal the beginning of a multiline; after that we can add some better support for this to remove the naive implementation for a more solid one.

@esttorhe
Copy link
Author

esttorhe commented Feb 5, 2019

@joho Any chance to get a review?

Copy link
Owner

@joho joho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it took me a while to review. Unfortunately I don't want to merge as-is.

I think in general the tests are fine and the string juggling within parseLine (though I think you'll need to split parseLine into two functions, one for handling single lines and another for handling multilines.

The logic in Parse is where it needs the most work - I can't follow what it does very well as a reader and so I'm not confident it's free of edge cases etc. An design approach that might work is to have the regular parseLine return a specific error stating that the line is the beginning of a multiline, and have an error check. If it matches, pass that line and any subsequent lines into a parseMultiline until that hits the end of the value.

Other approaches can definitely work but I just want to see less jumbled special case logic up in Parse if possible.

@@ -209,7 +246,7 @@ func readFile(filename string) (envMap map[string]string, err error) {
return Parse(file)
}

func parseLine(line string, envMap map[string]string) (key string, value string, err error) {
func parseLine(line string, envMap map[string]string, isMultiline bool) (key string, value string, multilineValue bool, err error) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd appreciate if you could find a way to restructure this to not rely on a boolean flag as I'm in Fowler's camp on the topic https://www.martinfowler.com/bliki/FlagArgument.html


if err != nil {
return
}
envMap[key] = value

if multilineValue == true && isMultilineValue == false && len(key) <= 0 {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to admit I'm really confused by the two multilineValue booleans, and I'm not sure if that's a structural problem or a naming problem of the variables.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah; this is a fair comment. I'm not particularly happy with the implementation and thus wanted to get some feedback from you since is your codebase.

I'll close this PR and will refactor in a cleaner way probably this weekend.

🙇

@esttorhe esttorhe closed this Aug 12, 2019
@esttorhe esttorhe deleted the multiline_variables branch August 12, 2019 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Doesn't support multiline vars
3 participants