Skip to content

Commit f3802fe

Browse files
split NoEnvVars into DoNotSetEnvVars (replaces NoEnvVars) and ExcludeEnvVars (with backing field IncludeEnvVars; same logic like the others);
mark NoEnvVars obsolete, switch the tests to DoNotSetEnvVars, and let all NoEnvVars point to DoNotSetEnvVars-implementations add some explaining comments for LoadOptions
1 parent 522672a commit f3802fe

File tree

6 files changed

+116
-47
lines changed

6 files changed

+116
-47
lines changed

src/DotNetEnv/Env.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,14 @@ private static IEnumerable<KeyValuePair<string, string>> LoadContents(string con
8383

8484
previousValues = previousValues?.ToArray() ?? Array.Empty<KeyValuePair<string, string>>();
8585

86-
var envVarSnapshot = Environment.GetEnvironmentVariables().Cast<DictionaryEntry>()
87-
.Select(entry => new KeyValuePair<string, string>(entry.Key.ToString(), entry.Value.ToString()))
88-
.ToArray();
89-
9086
var dictionaryOption = options.ClobberExistingVars
9187
? CreateDictionaryOption.TakeLast
9288
: CreateDictionaryOption.TakeFirst;
9389

94-
var actualValues = new ConcurrentDictionary<string, string>(envVarSnapshot.Concat(previousValues)
95-
.ToDotEnvDictionary(dictionaryOption));
90+
var actualValues =
91+
(options.IncludeEnvVars ? GetEnvVarSnapshot() : Array.Empty<KeyValuePair<string, string>>())
92+
.Concat(previousValues)
93+
.ToDotEnvDictionary(dictionaryOption);
9694

9795
var pairs = Parsers.ParseDotenvFile(contents, options.ClobberExistingVars, actualValues);
9896

@@ -111,23 +109,31 @@ private static IEnumerable<KeyValuePair<string, string>> LoadContents(string con
111109
return unClobberedPairs.ToDotEnvDictionary(dictionaryOption);
112110
}
113111

114-
public static string GetString(string key, string fallback = default(string)) =>
112+
private static KeyValuePair<string, string>[] GetEnvVarSnapshot() =>
113+
Environment.GetEnvironmentVariables().Cast<DictionaryEntry>()
114+
.Select(entry => new KeyValuePair<string, string>(entry.Key.ToString(), entry.Value.ToString()))
115+
.ToArray();
116+
117+
public static string GetString(string key, string fallback = null) =>
115118
Environment.GetEnvironmentVariable(key) ?? fallback;
116119

117-
public static bool GetBool(string key, bool fallback = default(bool)) =>
120+
public static bool GetBool(string key, bool fallback = false) =>
118121
bool.TryParse(Environment.GetEnvironmentVariable(key), out var value) ? value : fallback;
119122

120-
public static int GetInt(string key, int fallback = default(int)) =>
123+
public static int GetInt(string key, int fallback = 0) =>
121124
int.TryParse(Environment.GetEnvironmentVariable(key), out var value) ? value : fallback;
122125

123-
public static double GetDouble(string key, double fallback = default(double)) =>
126+
public static double GetDouble(string key, double fallback = 0) =>
124127
double.TryParse(Environment.GetEnvironmentVariable(key), NumberStyles.Any, CultureInfo.InvariantCulture,
125128
out var value)
126129
? value
127130
: fallback;
128131

129-
public static LoadOptions NoEnvVars() => LoadOptions.NoEnvVars();
132+
[Obsolete("Use DoNotSetEnvVars instead")]
133+
public static LoadOptions NoEnvVars() => DoNotSetEnvVars();
134+
public static LoadOptions DoNotSetEnvVars() => LoadOptions.DoNotSetEnvVars();
130135
public static LoadOptions NoClobber() => LoadOptions.NoClobber();
131136
public static LoadOptions TraversePath() => LoadOptions.TraversePath();
137+
public static LoadOptions ExcludeEnvVars() => LoadOptions.ExcludeEnvVars();
132138
}
133139
}

src/DotNetEnv/LoadOptions.cs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23

34
namespace DotNetEnv
@@ -6,43 +7,64 @@ public class LoadOptions
67
{
78
public static readonly LoadOptions DEFAULT = new LoadOptions();
89

10+
/// <summary>Whether Environment Variables are set or not (process only; not persistent).</summary>
911
public bool SetEnvVars { get; }
12+
/// <summary>When set, the last found occurence is taken, otherwise the first.</summary>
1013
public bool ClobberExistingVars { get; }
14+
/// <summary>
15+
/// When set, only the exact given path of env files is taken. <br />
16+
/// Otherwise, the filename gets extracted and searched in every parent directory until a match is found.
17+
/// </summary>
1118
public bool OnlyExactPath { get; }
19+
/// <summary>Whether Environment Variables are included for Interpolation.</summary>
20+
public bool IncludeEnvVars { get; }
1221

1322
public LoadOptions(
1423
bool setEnvVars = true,
1524
bool clobberExistingVars = true,
16-
bool onlyExactPath = true
25+
bool onlyExactPath = true,
26+
bool includeEnvVars = true
1727
) {
1828
SetEnvVars = setEnvVars;
1929
ClobberExistingVars = clobberExistingVars;
2030
OnlyExactPath = onlyExactPath;
31+
IncludeEnvVars = includeEnvVars;
2132
}
2233

2334
public LoadOptions(
2435
LoadOptions old,
2536
bool? setEnvVars = null,
2637
bool? clobberExistingVars = null,
27-
bool? onlyExactPath = null
38+
bool? onlyExactPath = null,
39+
bool? includeEnvVars = null
2840
) {
2941
SetEnvVars = setEnvVars ?? old.SetEnvVars;
3042
ClobberExistingVars = clobberExistingVars ?? old.ClobberExistingVars;
3143
OnlyExactPath = onlyExactPath ?? old.OnlyExactPath;
44+
IncludeEnvVars = includeEnvVars ?? old.IncludeEnvVars;
3245
}
3346

34-
public static LoadOptions NoEnvVars (LoadOptions options = null) =>
35-
options == null ? DEFAULT.NoEnvVars() : options.NoEnvVars();
47+
[Obsolete("Use DoNotSetEnvVars instead")]
48+
public static LoadOptions NoEnvVars(LoadOptions options = null) =>
49+
DoNotSetEnvVars(options);
50+
public static LoadOptions DoNotSetEnvVars (LoadOptions options = null) =>
51+
options == null ? DEFAULT.DoNotSetEnvVars() : options.DoNotSetEnvVars();
3652

3753
public static LoadOptions NoClobber (LoadOptions options = null) =>
3854
options == null ? DEFAULT.NoClobber() : options.NoClobber();
3955

4056
public static LoadOptions TraversePath (LoadOptions options = null) =>
4157
options == null ? DEFAULT.TraversePath() : options.TraversePath();
4258

43-
public LoadOptions NoEnvVars () => new LoadOptions(this, setEnvVars: false);
59+
public static LoadOptions ExcludeEnvVars (LoadOptions options = null) =>
60+
options == null ? DEFAULT.ExcludeEnvVars() : options.ExcludeEnvVars();
61+
62+
[Obsolete("Use DoNotSetEnvVars instead")]
63+
public LoadOptions NoEnvVars () => DoNotSetEnvVars();
64+
public LoadOptions DoNotSetEnvVars () => new LoadOptions(this, setEnvVars: false);
4465
public LoadOptions NoClobber () => new LoadOptions(this, clobberExistingVars: false);
4566
public LoadOptions TraversePath () => new LoadOptions(this, onlyExactPath: false);
67+
public LoadOptions ExcludeEnvVars () => new LoadOptions(this, includeEnvVars: false);
4668

4769
public IEnumerable<KeyValuePair<string, string>> Load (string path = null) => Env.Load(path, this);
4870
public IEnumerable<KeyValuePair<string, string>> LoadMulti (string[] paths) => Env.LoadMulti(paths, this);

test/DotNetEnv.Tests/EnvConfigurationTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void Dispose()
4949
public void AddSourceToBuilderAndLoad()
5050
{
5151
configuration = new ConfigurationBuilder()
52-
.AddDotNetEnv(options: LoadOptions.NoEnvVars())
52+
.AddDotNetEnv(options: LoadOptions.DoNotSetEnvVars())
5353
.Build();
5454

5555
Assert.Empty(configuration["EMPTY"]);
@@ -65,7 +65,7 @@ public void AddSourceToBuilderAndLoadDotenvHigherSkip()
6565
{
6666
// ./DotNetEnv.Tests/bin/Debug/netcoreapp3.1/DotNetEnv.Tests.dll -- get to the ./ (root of `test` folder)
6767
configuration = new ConfigurationBuilder()
68-
.AddDotNetEnv("../../../../", LoadOptions.NoEnvVars())
68+
.AddDotNetEnv("../../../../", LoadOptions.DoNotSetEnvVars())
6969
.Build();
7070

7171
Assert.Null(configuration["NAME"]);
@@ -76,7 +76,7 @@ public void AddSourceToBuilderAndLoadDotenvHigherSkip()
7676
public void AddSourceToBuilderAndLoadMulti()
7777
{
7878
configuration = new ConfigurationBuilder()
79-
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.NoEnvVars())
79+
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.DoNotSetEnvVars())
8080
.Build();
8181

8282
Assert.Equal("Other", configuration["NAME"]);
@@ -87,7 +87,7 @@ public void AddSourceToBuilderAndLoadMulti()
8787
public void AddSourceToBuilderAndLoadMultiWithNoClobber()
8888
{
8989
configuration = new ConfigurationBuilder()
90-
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.NoEnvVars().NoClobber())
90+
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.DoNotSetEnvVars().NoClobber())
9191
.Build();
9292

9393
Assert.Equal("Toni", configuration["NAME"]);
@@ -100,7 +100,7 @@ public void AddSourceToBuilderAndLoadMultiWithNoClobber()
100100
public void AddSourceToBuilderAndLoadMultiWithClobber()
101101
{
102102
configuration = new ConfigurationBuilder()
103-
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.NoEnvVars())
103+
.AddDotNetEnvMulti(new[] { "./.env", "./.env2" }, LoadOptions.DoNotSetEnvVars())
104104
.Build();
105105

106106
Assert.Equal("Other", configuration["NAME"]);
@@ -113,7 +113,7 @@ public void AddSourceToBuilderAndLoadMultiWithClobber()
113113
public void AddSourceToBuilderAndFileDoesNotExist()
114114
{
115115
configuration = new ConfigurationBuilder()
116-
.AddDotNetEnv("./.env_DNE", LoadOptions.NoEnvVars())
116+
.AddDotNetEnv("./.env_DNE", LoadOptions.DoNotSetEnvVars())
117117
.Build();
118118

119119
Assert.Empty(configuration.AsEnumerable());
@@ -123,7 +123,7 @@ public void AddSourceToBuilderAndFileDoesNotExist()
123123
public void AddSourceToBuilderAndGetSection()
124124
{
125125
configuration = new ConfigurationBuilder()
126-
.AddDotNetEnv("./.env_sections", LoadOptions.NoEnvVars())
126+
.AddDotNetEnv("./.env_sections", LoadOptions.DoNotSetEnvVars())
127127
.Build();
128128

129129
var section = configuration.GetSection("SECTION");

test/DotNetEnv.Tests/EnvTests.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.IO;
45
using System.Runtime.InteropServices;
@@ -150,13 +151,13 @@ public void LoadMultiTest()
150151
[Fact]
151152
public void LoadMultiTestNoEnvVars()
152153
{
153-
var pairs = DotNetEnv.Env.NoEnvVars().LoadMulti(new[] { "./.env", "./.env2" });
154+
var pairs = DotNetEnv.Env.DoNotSetEnvVars().LoadMulti(new[] { "./.env", "./.env2" });
154155
Assert.Equal("Other", pairs.LastOrDefault(x => x.Key == "NAME").Value);
155156
Environment.SetEnvironmentVariable("NAME", null);
156-
pairs = DotNetEnv.Env.NoEnvVars().NoClobber().LoadMulti(new[] { "./.env", "./.env2" });
157+
pairs = DotNetEnv.Env.DoNotSetEnvVars().NoClobber().LoadMulti(new[] { "./.env", "./.env2" });
157158
Assert.Equal("Toni", pairs.FirstOrDefault(x => x.Key == "NAME").Value);
158159
Environment.SetEnvironmentVariable("NAME", "Person");
159-
pairs = DotNetEnv.Env.NoEnvVars().NoClobber().LoadMulti(new[] { "./.env", "./.env2" });
160+
pairs = DotNetEnv.Env.DoNotSetEnvVars().NoClobber().LoadMulti(new[] { "./.env", "./.env2" });
160161
Assert.Null(pairs.FirstOrDefault(x => x.Key == "NAME").Value); // value from EnvironmentVariables is not contained with NoClobber
161162
}
162163

@@ -178,7 +179,7 @@ public void LoadNoClobberTest()
178179
}
179180

180181
[Fact]
181-
public void LoadNoSetEnvVarsTest()
182+
public void LoadDoNoSetEnvVarsTest()
182183
{
183184
var expected = "totally the original value";
184185
Environment.SetEnvironmentVariable("NAME", null);
@@ -206,6 +207,21 @@ public void LoadNoRequireEnvTest()
206207
// it didn't throw an exception and crash for a missing file
207208
}
208209

210+
[Fact]
211+
public void ExcludeEnvVarsTest()
212+
{
213+
const string envVarName = "URL";
214+
const string initialEnvVarValue = "totally the original value";
215+
const string envFileValue = "https://github.com/tonerdo";
216+
217+
Environment.SetEnvironmentVariable(envVarName, initialEnvVarValue);
218+
219+
var result = Env.Load("./.env", Env.ExcludeEnvVars());
220+
221+
Assert.Contains(new KeyValuePair<string, string>(envVarName, envFileValue), result);
222+
Assert.NotEqual(initialEnvVarValue, Environment.GetEnvironmentVariable(envVarName));
223+
}
224+
209225
[Fact]
210226
public void LoadOsCasingTest()
211227
{
@@ -275,11 +291,11 @@ public void ParseInterpolatedTest()
275291
}
276292

277293
[Fact]
278-
public void ParseInterpolatedNoEnvVarsTest()
294+
public void ParseInterpolatedDoNotSetEnvVarsTest()
279295
{
280296
System.Environment.SetEnvironmentVariable("EXISTING_ENVIRONMENT_VARIABLE", "value");
281297
System.Environment.SetEnvironmentVariable("DNE_VAR", null);
282-
var environmentDictionary = DotNetEnv.Env.NoEnvVars().Load("./.env_embedded").ToDotEnvDictionary();
298+
var environmentDictionary = DotNetEnv.Env.DoNotSetEnvVars().Load("./.env_embedded").ToDotEnvDictionary();
283299

284300
Assert.Equal("test", environmentDictionary["TEST"]);
285301
Assert.Equal("test1", environmentDictionary["TEST1"]);

test/DotNetEnv.Tests/LoadOptionsTests.cs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,51 @@ namespace DotNetEnv.Tests
77
public class LoadOptionsTests
88
{
99
/// <summary>
10-
/// Data: _, optionsUnderTest, expectedSetEnvVars, expectedClobberExistingVars, expectedOnlyExactPath
10+
/// Data: _, optionsUnderTest, expectedSetEnvVars, expectedClobberExistingVars, expectedOnlyExactPath, expectedIncludeEnvVars
1111
/// </summary>
12-
public static readonly TheoryData<string, LoadOptions, bool , bool, bool>
13-
LoadOptionTestCombinations = new IndexedTheoryData<LoadOptions, bool, bool, bool>()
12+
public static readonly TheoryData<string, LoadOptions, bool , bool, bool, bool>
13+
LoadOptionTestCombinations = new IndexedTheoryData<LoadOptions, bool, bool, bool, bool>()
1414
{
15-
{ Env.NoEnvVars(), false, true, true },
16-
{ Env.NoClobber(), true, false, true },
17-
{ Env.TraversePath(), true, true, false },
18-
{ LoadOptions.NoEnvVars(), false, true, true },
19-
{ LoadOptions.NoClobber(), true, false, true },
20-
{ LoadOptions.TraversePath(), true, true, false },
21-
{ new LoadOptions(), true, true, true },
22-
{ new LoadOptions().NoEnvVars(), false, true, true },
23-
{ new LoadOptions().NoClobber(), true, false, true },
24-
{ new LoadOptions().TraversePath(), true, true, false },
25-
{ Env.NoEnvVars().NoClobber().TraversePath(), false, false, false },
26-
{ Env.NoClobber().TraversePath(), true, false, false },
27-
{ Env.NoEnvVars().NoClobber(), false, false, true },
28-
{ Env.NoEnvVars().TraversePath(), false, true, false },
15+
{ Env.DoNotSetEnvVars(), false, true, true, true },
16+
{ Env.NoClobber(), true, false, true, true },
17+
{ Env.TraversePath(), true, true, false, true },
18+
{ Env.ExcludeEnvVars(), true, true, true, false },
19+
20+
{ LoadOptions.DoNotSetEnvVars(), false, true, true, true },
21+
{ LoadOptions.NoClobber(), true, false, true, true },
22+
{ LoadOptions.TraversePath(), true, true, false, true },
23+
{ LoadOptions.ExcludeEnvVars(), true, true, true, false },
24+
25+
{ new LoadOptions(), true, true, true, true },
26+
{ new LoadOptions().DoNotSetEnvVars(), false, true, true, true },
27+
{ new LoadOptions().NoClobber(), true, false, true, true },
28+
{ new LoadOptions().TraversePath(), true, true, false, true },
29+
{ new LoadOptions().ExcludeEnvVars(), true, true, true, false },
30+
31+
{ Env.DoNotSetEnvVars().NoClobber().TraversePath().ExcludeEnvVars(), false, false, false, false },
32+
33+
{ Env.DoNotSetEnvVars().NoClobber().TraversePath(), false, false, false, true },
34+
{ Env.DoNotSetEnvVars().NoClobber().ExcludeEnvVars(), false, false, true, false },
35+
{ Env.DoNotSetEnvVars().TraversePath().ExcludeEnvVars(), false, true, false, false },
36+
{ Env.NoClobber().TraversePath().ExcludeEnvVars(), true, false, false, false },
37+
38+
{ Env.DoNotSetEnvVars().NoClobber(), false, false, true, true },
39+
{ Env.NoClobber().TraversePath(), true, false, false, true },
40+
{ Env.TraversePath().ExcludeEnvVars(), true, true, false, false },
41+
{ Env.DoNotSetEnvVars().ExcludeEnvVars(), false, true, true, false },
42+
{ Env.DoNotSetEnvVars().TraversePath(), false, true, false, true },
43+
{ Env.NoClobber().ExcludeEnvVars(), true, false, true, false },
2944
};
3045

3146
[Theory]
3247
[MemberData(nameof(LoadOptionTestCombinations))]
3348
public void LoadOptionsShouldHaveCorrectPropertiesSet(string _, LoadOptions optionsUnderTest,
34-
bool expectedSetEnvVars, bool expectedClobberExistingVars, bool expectedOnlyExactPath)
49+
bool expectedSetEnvVars, bool expectedClobberExistingVars, bool expectedOnlyExactPath, bool expectedIncludeEnvVars)
3550
{
3651
Assert.Equal(expectedSetEnvVars, optionsUnderTest.SetEnvVars);
3752
Assert.Equal(expectedClobberExistingVars, optionsUnderTest.ClobberExistingVars);
3853
Assert.Equal(expectedOnlyExactPath, optionsUnderTest.OnlyExactPath);
54+
Assert.Equal(expectedIncludeEnvVars, optionsUnderTest.IncludeEnvVars);
3955
}
4056
}
4157
}

test/DotNetEnv.Tests/XUnit/IndexedTheoryData.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,12 @@ public void Add(T1 p1, T2 p2, T3 p3, T4 p4, [CallerMemberName]string callerMembe
3838
AddRow($"{_index++,4}; {callerMemberName}:{callerLineNumber}", p1, p2, p3, p4);
3939
}
4040
}
41+
42+
public class IndexedTheoryData<T1, T2, T3, T4, T5> : TheoryData<string, T1, T2, T3, T4, T5>
43+
{
44+
private int _index = 0;
45+
public void Add(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, [CallerMemberName]string callerMemberName = null, [CallerLineNumber]int callerLineNumber = 0)
46+
{
47+
AddRow($"{_index++,4}; {callerMemberName}:{callerLineNumber}", p1, p2, p3, p4, p5);
48+
}
49+
}

0 commit comments

Comments
 (0)