Skip to content

[Dotenv] Use default value when referenced variable is not set #31546

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

Merged
merged 1 commit into from
Aug 6, 2019

Conversation

j92
Copy link
Contributor

@j92 j92 commented May 19, 2019

Q A
Branch? 4.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #...
License MIT
Doc PR symfony/symfony-docs#11956

In bash you have the option to define a default variable like this:

FOO=${VARIABLE:-default} 

When VARIABLE is not set

FOO=${VARIABLE:-default} #FOO=default

When VARIABLE is set:

VARIABLE=test
FOO=${VARIABLE:-default} #FOO=test

If others find this also a good idea, I will write documentation and add the Doc PR. But first I would like some feedback to check if anyone agrees with this feature.

@nicolas-grekas
Copy link
Member

That's nice. We can support things that the shell supports I think yes.
Can you add tests with the empty string? How does the shell behave when a car exists as the empty string also?
For the added regexp, why make it case insensitive? I think it's not needed.

@j92
Copy link
Contributor Author

j92 commented May 19, 2019

@nicolas-grekas Thanks for the feedback! I added the test for the empty string and indeed the added regexp does not have to be case insensitive.

I'm not sure what you mean by:

How does the shell behave when a car exists as the empty string also?

@nicolas-grekas
Copy link
Member

s/car/var - a var can be defined but empty, what's the behavior in this situation?

@j92
Copy link
Contributor Author

j92 commented May 20, 2019

FOO=
BAR=${FOO:-test}

In this case, the value of BAR will be 'test'.

(?!\() # no opening parenthesis
(?P<opening_brace>\{)? # optional brace
(?P<name>'.self::VARNAME_REGEX.')? # var name
(?P<default_value>(?:(:-)([^\}]+)))? # optional default value
Copy link
Member

Choose a reason for hiding this comment

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

no need for the extra brackets I believe: (?P<default_value>:-[^\}]+)?
but more generally, the parsing logic doesn't handle quoted/interpolated values
eg. ${ABC:-a\'aa} or worse ${ABC:-a\'a{a}a} (which results in a'a{aa})
an idea could be to not deal with these and reject more chars than only }?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good to not deal with these cases. It's a fallback mechanism which should contain simple values. Let's keep it KISS for now.

I will update the regex. And should we reject }{\' characters with a FormatException?

Copy link
Member

Choose a reason for hiding this comment

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

I think so yes. I would also exclude double quotes and $, and maybe more special chars (I don't know them all)?

Copy link
Contributor Author

@j92 j92 Jul 10, 2019

Choose a reason for hiding this comment

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

@nicolas-grekas I removed the braces from the regex. The regex strips only the last } from the default value and checks later with strpbrk('"{}$) for the invalid characters. This way we can throw a FormatException instead of simply ignoring the default value.

I hope my solution is okay, as my knowledge of regexes is not great. Please let me know what you think.

@nicolas-grekas nicolas-grekas added this to the next milestone May 20, 2019
@nicolas-grekas nicolas-grekas changed the base branch from master to 4.4 June 2, 2019 20:11
@fabpot
Copy link
Member

fabpot commented Jul 8, 2019

@j92 It looks like this pull request is almost finished. You needed to update the regex. Do you have time to finish this work?

@j92
Copy link
Contributor Author

j92 commented Jul 10, 2019

@fabpot Thanks for the reminder. I updated the PR. When the code is correct, I will also update the documentation.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

2nd round :)

@@ -456,6 +457,14 @@ private function resolveVariables($value)
$value = (string) getenv($name);
}

if ('' === $value && isset($matches['default_value'])) {
Copy link
Member

Choose a reason for hiding this comment

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

we should also check that there is both an opening and closing bracket
and when on is missing, we should append the content of the default_value index as a regular string
please add a test case covering this situation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nicolas-grekas If you are talking about the following case:
BAR=${FOO:-TEST, it is already handled with a FormatException : Unclosed braces on variable expansion.

Copy link
Member

Choose a reason for hiding this comment

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

yes, thanks for the precision
one more question: can we enter this "if" when there's no opening bracket? I feel like yes, while this should fail, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, I added a check for a missing opening brace and the following case:

BAR=$FOO:-a

now throws a FormatException with Variable expansion "$FOO:-a" should be wrapped in braces

@j92
Copy link
Contributor Author

j92 commented Jul 11, 2019

@nicolas-grekas Thanks for helping out, I was stuck.

@j92 j92 force-pushed the default-value branch from c6ad5a7 to 642374f Compare July 13, 2019 08:33
@j92
Copy link
Contributor Author

j92 commented Jul 13, 2019

@xabbuh Thanks for the feedback, it's applied. And I am curious to hear your opinion about the excluded characters.

["FOO=\nBAR=\${FOO:-\'a{a}a}", "Unsupported character \"'\" found in the default value of variable \"\$FOO\". in \".env\" at line 2.\n...\\nBAR=\${FOO:-\'a{a}a}...\n ^ line 2 offset 24"],
["FOO=\nBAR=\${FOO:-a\$a}", "Unsupported character \"\$\" found in the default value of variable \"\$FOO\". in \".env\" at line 2.\n...FOO=\\nBAR=\${FOO:-a\$a}...\n ^ line 2 offset 20"],
["FOO=\nBAR=\${FOO:-a\"a}", "Unclosed braces on variable expansion in \".env\" at line 2.\n...FOO=\\nBAR=\${FOO:-a\"a}...\n ^ line 2 offset 17"],
["FOO=\nBAR=\$FOO:-a", "Variable expansion \"\$FOO:-a\" should be wrapped in braces in \".env\" at line 2.\n...FOO=\\nBAR=\$FOO:-a...\n ^ line 2 offset 16"],
Copy link
Member

Choose a reason for hiding this comment

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

actually, this should be a legal value: it's just the $FOO var followed by the :-a string

Copy link
Member

Choose a reason for hiding this comment

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

indeed:

$ FOO=foo
$ BAR=$FOO:-a
$ echo $BAR
foo:-a

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nicolas-grekas

one more question: can we enter this "if" when there's no opening bracket? I feel like yes, while this should fail, isn't it?

My interpretation of your comment was that when there is no opening bracket, in the case of $FOO:-a for example, it should fail. Clearly I misunderstood your comment, sorry for that. Could you give me an example of the case that should fail? Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

my comment was certainly not clear, as I spotted this case after making it :)

@xabbuh
Copy link
Member

xabbuh commented Aug 6, 2019

Thank you @j92.

@xabbuh xabbuh merged commit 790dbad into symfony:4.4 Aug 6, 2019
xabbuh added a commit that referenced this pull request Aug 6, 2019
… not set (j92)

This PR was squashed before being merged into the 4.4 branch (closes #31546).

Discussion
----------

[Dotenv] Use default value when referenced variable is not set

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes <!-- please update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | #...   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | symfony/symfony-docs#11956 <!-- required for new features -->

In bash you have the option to define a default variable like this:
```bash
FOO=${VARIABLE:-default}
```

When VARIABLE is not set
```bash
FOO=${VARIABLE:-default} #FOO=default
```

When VARIABLE is set:
```bash
VARIABLE=test
FOO=${VARIABLE:-default} #FOO=test
```

If others find this also a good idea, I will write documentation and add the Doc PR. But first I would like some feedback to check if anyone agrees with this feature.

Commits
-------

790dbad [Dotenv] Use default value when referenced variable is not set
@j92 j92 deleted the default-value branch August 6, 2019 07:35
OskarStark added a commit to symfony/symfony-docs that referenced this pull request Aug 6, 2019
This PR was merged into the 4.4 branch.

Discussion
----------

Added small section about default values

<!--

If your pull request fixes a BUG, use the oldest maintained branch that contains
the bug (see https://symfony.com/roadmap for the list of maintained branches).

If your pull request documents a NEW FEATURE, use the same Symfony branch where
the feature was introduced (and `master` for features of unreleased versions).

-->

Added a short description and a code sample of how to use default values when referenced variables are not set. The feature PR is symfony/symfony#31546.

Commits
-------

1848e00 Added small section about default values
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.4 Oct 27, 2019
This was referenced Nov 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants