aboutsummaryrefslogtreecommitdiff
path: root/src/env_loader.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-20 01:02:15 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-09-20 01:02:15 -0700
commite94e6d8d95061c8bdb07ce96bc836689f49aafdd (patch)
tree803b7511c5ed822f8fffe306383b31363c764024 /src/env_loader.zig
parentf0bc50eb71d08b3e3429250e4317ed084b32391c (diff)
downloadbun-e94e6d8d95061c8bdb07ce96bc836689f49aafdd.tar.gz
bun-e94e6d8d95061c8bdb07ce96bc836689f49aafdd.tar.zst
bun-e94e6d8d95061c8bdb07ce96bc836689f49aafdd.zip
Allow .env files to define the same key multiple times
Fixes https://github.com/oven-sh/bun/issues/1262
Diffstat (limited to '')
-rw-r--r--src/env_loader.zig87
1 files changed, 55 insertions, 32 deletions
diff --git a/src/env_loader.zig b/src/env_loader.zig
index 2def850dc..97edbc3c2 100644
--- a/src/env_loader.zig
+++ b/src/env_loader.zig
@@ -955,6 +955,7 @@ pub const Parser = struct {
var lexer = Lexer.init(source);
var fbs = std.io.fixedBufferStream(&temporary_nested_value_buffer);
var writer = fbs.writer();
+ const start_count = map.map.count();
while (lexer.next(is_process)) |variable| {
if (variable.has_nested_value) {
@@ -967,7 +968,13 @@ pub const Parser = struct {
map.put(variable.key, allocator.dupe(u8, new_value) catch unreachable) catch unreachable;
} else {
var putter = map.map.getOrPut(variable.key) catch unreachable;
- if (!putter.found_existing) {
+ // Allow keys defined later in the same file to override keys defined earlier
+ // https://github.com/oven-sh/bun/issues/1262
+ if (!putter.found_existing or putter.index >= start_count) {
+ if (putter.found_existing and putter.value_ptr.len > 0) {
+ allocator.free(putter.value_ptr.*);
+ }
+
putter.value_ptr.* = allocator.dupe(u8, new_value) catch unreachable;
}
}
@@ -976,7 +983,16 @@ pub const Parser = struct {
if (comptime override) {
map.put(variable.key, variable.value) catch unreachable;
} else {
- map.putDefault(variable.key, variable.value) catch unreachable;
+ // Allow keys defined later in the same file to override keys defined earlier
+ // https://github.com/oven-sh/bun/issues/1262
+ var putter = map.map.getOrPut(variable.key) catch unreachable;
+ if (!putter.found_existing or putter.index >= start_count) {
+ if (putter.found_existing and putter.value_ptr.len > 0) {
+ allocator.free(putter.value_ptr.*);
+ }
+
+ putter.value_ptr.* = allocator.dupe(u8, variable.value) catch unreachable;
+ }
}
}
}
@@ -1111,39 +1127,46 @@ test "DotEnv Loader - basic" {
\\
\\EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING=""
\\
+ \\VALUE_WITH_MULTIPLE_VALUES_SET_IN_SAME_FILE=''
+ \\
+ \\VALUE_WITH_MULTIPLE_VALUES_SET_IN_SAME_FILE='good'
+ \\
;
const source = logger.Source.initPathString(".env", VALID_ENV);
var map = Map.init(default_allocator);
- Parser.parse(
- &source,
- default_allocator,
- &map,
- true,
- false,
- );
- try expectString(map.get("NESTED_VALUES_RESPECT_ESCAPING").?, "\\$API_KEY");
- try expectString(map.get("NESTED_VALUES_WITH_CURLY_BRACES_RESPECT_ESCAPING").?, "\\${API_KEY}");
-
- try expectString(map.get("NESTED_VALUE").?, "verysecure");
- try expectString(map.get("NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure");
- try expectString(map.get("NESTED_VALUE_WITHOUT_OPENING_CURLY_BRACE").?, "verysecure}");
- try expectString(map.get("RECURSIVE_NESTED_VALUE").?, "verysecure:verysecure");
- try expectString(map.get("RECURSIVE_NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure:verysecure");
-
- try expectString(map.get("API_KEY").?, "verysecure");
- try expectString(map.get("process.env.WAT").?, "ABCDEFGHIJKLMNOPQRSTUVWXYZZ10239457123");
- try expectString(map.get("DOUBLE-QUOTED_SHOULD_PRESERVE_NEWLINES").?, "\nya\n");
- try expectString(map.get("SINGLE_QUOTED_SHOULDNT_PRESERVE_NEWLINES").?, "yo");
- try expectString(map.get("SINGLE_QUOTED_DOESNT_PRESERVES_QUOTES").?, "yo");
- try expectString(map.get("UNQUOTED_SHOULDNT_PRESERVE_NEWLINES_AND_TRIMS_TRAILING_SPACE").?, "yo");
- try expect(map.get("LINES_WITHOUT_EQUAL_ARE_IGNORED") == null);
- try expectString(map.get("LEADING_SPACE_IS_TRIMMED").?, "yes");
- try expect(map.get("NO_VALUE_IS_EMPTY_STRING").?.len == 0);
- try expectString(map.get("IGNORING_DOESNT_BREAK_OTHER_LINES").?, "yes");
- try expectString(map.get("LEADING_SPACE_IN_UNQUOTED_VALUE_IS_TRIMMED").?, "yes");
- try expectString(map.get("SPACE_BEFORE_EQUALS_SIGN").?, "yes");
- try expectString(map.get("EMPTY_SINGLE_QUOTED_VALUE_IS_EMPTY_STRING").?, "");
- try expectString(map.get("EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING").?, "");
+ inline for (.{ true, false }) |override| {
+ Parser.parse(
+ &source,
+ default_allocator,
+ &map,
+ override,
+ false,
+ );
+ try expectString(map.get("NESTED_VALUES_RESPECT_ESCAPING").?, "\\$API_KEY");
+ try expectString(map.get("NESTED_VALUES_WITH_CURLY_BRACES_RESPECT_ESCAPING").?, "\\${API_KEY}");
+
+ try expectString(map.get("NESTED_VALUE").?, "verysecure");
+ try expectString(map.get("NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure");
+ try expectString(map.get("NESTED_VALUE_WITHOUT_OPENING_CURLY_BRACE").?, "verysecure}");
+ try expectString(map.get("RECURSIVE_NESTED_VALUE").?, "verysecure:verysecure");
+ try expectString(map.get("RECURSIVE_NESTED_VALUE_WITH_CURLY_BRACES").?, "verysecure:verysecure");
+
+ try expectString(map.get("API_KEY").?, "verysecure");
+ try expectString(map.get("process.env.WAT").?, "ABCDEFGHIJKLMNOPQRSTUVWXYZZ10239457123");
+ try expectString(map.get("DOUBLE-QUOTED_SHOULD_PRESERVE_NEWLINES").?, "\nya\n");
+ try expectString(map.get("SINGLE_QUOTED_SHOULDNT_PRESERVE_NEWLINES").?, "yo");
+ try expectString(map.get("SINGLE_QUOTED_DOESNT_PRESERVES_QUOTES").?, "yo");
+ try expectString(map.get("UNQUOTED_SHOULDNT_PRESERVE_NEWLINES_AND_TRIMS_TRAILING_SPACE").?, "yo");
+ try expect(map.get("LINES_WITHOUT_EQUAL_ARE_IGNORED") == null);
+ try expectString(map.get("LEADING_SPACE_IS_TRIMMED").?, "yes");
+ try expect(map.get("NO_VALUE_IS_EMPTY_STRING").?.len == 0);
+ try expectString(map.get("IGNORING_DOESNT_BREAK_OTHER_LINES").?, "yes");
+ try expectString(map.get("LEADING_SPACE_IN_UNQUOTED_VALUE_IS_TRIMMED").?, "yes");
+ try expectString(map.get("SPACE_BEFORE_EQUALS_SIGN").?, "yes");
+ try expectString(map.get("EMPTY_SINGLE_QUOTED_VALUE_IS_EMPTY_STRING").?, "");
+ try expectString(map.get("EMPTY_DOUBLE_QUOTED_VALUE_IS_EMPTY_STRING").?, "");
+ try expectString(map.get("VALUE_WITH_MULTIPLE_VALUES_SET_IN_SAME_FILE").?, "good");
+ }
}
test "DotEnv Loader - Nested values with curly braces" {