diff options
Diffstat (limited to 'src/env_loader.zig')
-rw-r--r-- | src/env_loader.zig | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/src/env_loader.zig b/src/env_loader.zig index 7c2c38a99..7f0be98a7 100644 --- a/src/env_loader.zig +++ b/src/env_loader.zig @@ -231,7 +231,7 @@ pub const Loader = struct { if (behavior == .prefix) { while (iter.next()) |entry| { - const value: string = entry.value_ptr.*; + const value: string = entry.value_ptr.value; if (strings.startsWith(entry.key_ptr.*, prefix)) { const key_str = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable; @@ -282,12 +282,12 @@ pub const Loader = struct { } } else { while (iter.next()) |entry| { - const value: string = if (entry.value_ptr.*.len == 0) empty_string_value else entry.value_ptr.*; + const value: string = if (entry.value_ptr.value.len == 0) empty_string_value else entry.value_ptr.value; const key = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable; e_strings[0] = js_ast.E.String{ - .data = if (entry.value_ptr.*.len > 0) - @as([*]u8, @ptrFromInt(@intFromPtr(entry.value_ptr.*.ptr)))[0..value.len] + .data = if (entry.value_ptr.value.len > 0) + @as([*]u8, @ptrFromInt(@intFromPtr(entry.value_ptr.value.ptr)))[0..value.len] else &[_]u8{}, }; @@ -370,7 +370,6 @@ pub const Loader = struct { // .env goes last pub fn load( this: *Loader, - fs: *Fs.FileSystem.RealFS, dir: *Fs.FileSystem.DirEntry, comptime suffix: enum { development, production, @"test" }, ) !void { @@ -380,19 +379,19 @@ pub const Loader = struct { switch (comptime suffix) { .development => { if (dir.hasComptimeQuery(".env.development.local")) { - try this.loadEnvFile(fs, dir_handle, ".env.development.local", false); + try this.loadEnvFile(dir_handle, ".env.development.local", false, true); Analytics.Features.dotenv = true; } }, .production => { if (dir.hasComptimeQuery(".env.production.local")) { - try this.loadEnvFile(fs, dir_handle, ".env.production.local", false); + try this.loadEnvFile(dir_handle, ".env.production.local", false, true); Analytics.Features.dotenv = true; } }, .@"test" => { if (dir.hasComptimeQuery(".env.test.local")) { - try this.loadEnvFile(fs, dir_handle, ".env.test.local", false); + try this.loadEnvFile(dir_handle, ".env.test.local", false, true); Analytics.Features.dotenv = true; } }, @@ -400,7 +399,7 @@ pub const Loader = struct { if (comptime suffix != .@"test") { if (dir.hasComptimeQuery(".env.local")) { - try this.loadEnvFile(fs, dir_handle, ".env.local", false); + try this.loadEnvFile(dir_handle, ".env.local", false, false); Analytics.Features.dotenv = true; } } @@ -408,26 +407,26 @@ pub const Loader = struct { switch (comptime suffix) { .development => { if (dir.hasComptimeQuery(".env.development")) { - try this.loadEnvFile(fs, dir_handle, ".env.development", false); + try this.loadEnvFile(dir_handle, ".env.development", false, true); Analytics.Features.dotenv = true; } }, .production => { if (dir.hasComptimeQuery(".env.production")) { - try this.loadEnvFile(fs, dir_handle, ".env.production", false); + try this.loadEnvFile(dir_handle, ".env.production", false, true); Analytics.Features.dotenv = true; } }, .@"test" => { if (dir.hasComptimeQuery(".env.test")) { - try this.loadEnvFile(fs, dir_handle, ".env.test", false); + try this.loadEnvFile(dir_handle, ".env.test", false, true); Analytics.Features.dotenv = true; } }, } if (dir.hasComptimeQuery(".env")) { - try this.loadEnvFile(fs, dir_handle, ".env", false); + try this.loadEnvFile(dir_handle, ".env", false, false); Analytics.Features.dotenv = true; } @@ -487,8 +486,13 @@ pub const Loader = struct { Output.flush(); } - pub fn loadEnvFile(this: *Loader, fs: *Fs.FileSystem.RealFS, dir: std.fs.Dir, comptime base: string, comptime override: bool) !void { - _ = fs; + pub fn loadEnvFile( + this: *Loader, + dir: std.fs.Dir, + comptime base: string, + comptime override: bool, + comptime conditional: bool, + ) !void { if (@field(this, base) != null) { return; } @@ -565,6 +569,7 @@ pub const Loader = struct { this.map, override, false, + conditional, ); @field(this, base) = source; @@ -789,6 +794,7 @@ const Parser = struct { map: *Map, comptime override: bool, comptime is_process: bool, + comptime conditional: bool, ) void { var count = map.map.count(); while (this.pos < this.src.len) { @@ -804,19 +810,25 @@ const Parser = struct { // https://github.com/oven-sh/bun/issues/1262 if (comptime !override) continue; } else { - allocator.free(entry.value_ptr.*); + allocator.free(entry.value_ptr.value); } } - entry.value_ptr.* = allocator.dupe(u8, value) catch unreachable; + entry.value_ptr.* = .{ + .value = allocator.dupe(u8, value) catch unreachable, + .conditional = conditional, + }; } if (comptime !is_process) { var it = map.iter(); while (it.next()) |entry| { if (count > 0) { count -= 1; - } else if (expandValue(map, entry.value_ptr.*)) |value| { - allocator.free(entry.value_ptr.*); - entry.value_ptr.* = allocator.dupe(u8, value) catch unreachable; + } else if (expandValue(map, entry.value_ptr.value)) |value| { + allocator.free(entry.value_ptr.value); + entry.value_ptr.* = .{ + .value = allocator.dupe(u8, value) catch unreachable, + .conditional = conditional, + }; } } } @@ -828,14 +840,19 @@ const Parser = struct { map: *Map, comptime override: bool, comptime is_process: bool, + comptime conditional: bool, ) void { var parser = Parser{ .src = source.contents }; - parser._parse(allocator, map, override, is_process); + parser._parse(allocator, map, override, is_process, conditional); } }; pub const Map = struct { - const HashTable = bun.StringArrayHashMap(string); + const HashTableValue = struct { + value: string, + conditional: bool, + }; + const HashTable = bun.StringArrayHashMap(HashTableValue); map: HashTable, @@ -848,10 +865,10 @@ pub const Map = struct { var it = env_map.iterator(); var i: usize = 0; while (it.next()) |pair| : (i += 1) { - const env_buf = try arena.allocSentinel(u8, pair.key_ptr.len + pair.value_ptr.len + 1, 0); + const env_buf = try arena.allocSentinel(u8, pair.key_ptr.len + pair.value_ptr.value.len + 1, 0); bun.copy(u8, env_buf, pair.key_ptr.*); env_buf[pair.key_ptr.len] = '='; - bun.copy(u8, env_buf[pair.key_ptr.len + 1 ..], pair.value_ptr.*); + bun.copy(u8, env_buf[pair.key_ptr.len + 1 ..], pair.value_ptr.value); envp_buf[i] = env_buf.ptr; } std.debug.assert(i == envp_count); @@ -864,7 +881,10 @@ pub const Map = struct { var iter_ = this.map.iterator(); while (iter_.next()) |entry| { - try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.*)); + // Allow var from .env.development or .env.production to be loaded again. Also don't clone empty vars. + if (!entry.value_ptr.conditional and entry.value_ptr.value.len > 0) { + try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.value)); + } } return env_map; @@ -879,7 +899,10 @@ pub const Map = struct { } pub inline fn put(this: *Map, key: string, value: string) !void { - try this.map.put(key, value); + try this.map.put(key, .{ + .value = value, + .conditional = false, + }); } pub fn jsonStringify(self: *const @This(), writer: anytype) !void { @@ -907,22 +930,28 @@ pub const Map = struct { this: *const Map, key: string, ) ?string { - return this.map.get(key); + return if (this.map.get(key)) |entry| entry.value else null; } pub fn get_( this: *const Map, key: string, ) ?string { - return this.map.get(key); + return if (this.map.get(key)) |entry| entry.value else null; } pub inline fn putDefault(this: *Map, key: string, value: string) !void { - _ = try this.map.getOrPutValue(key, value); + _ = try this.map.getOrPutValue(key, .{ + .value = value, + .conditional = false, + }); } pub inline fn getOrPut(this: *Map, key: string, value: string) !void { - _ = try this.map.getOrPutValue(key, value); + _ = try this.map.getOrPutValue(key, .{ + .value = value, + .conditional = false, + }); } }; |