authorgravatar for mrjbq7@gmail.comJohn Benediktsson <mrjbq7@gmail.com> 2025-02-04 21:19:02-08:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-02-06 15:00:48+01:00
log1c07eacc7f26d2545d4c2149e3e3513875951370
tree130b8ec167c7fc61cfdd852e0c1907dc553e092e
parent62e251dcaa366c15e1e591d859738bb0d735dc9a

std.process: adding hasNonEmptyEnvVar() and using for NO_COLOR


4 files changed, 50 insertions(+), 16 deletions(-)

lib/std/io/tty.zig+2-2
...@@ -12,9 +12,9 @@ const native_os = builtin.os.tag;...@@ -12,9 +12,9 @@ const native_os = builtin.os.tag;
12pub fn detectConfig(file: File) Config {12pub fn detectConfig(file: File) Config {
13 const force_color: ?bool = if (builtin.os.tag == .wasi)13 const force_color: ?bool = if (builtin.os.tag == .wasi)
14 null // wasi does not support environment variables14 null // wasi does not support environment variables
15 else if (process.hasEnvVarConstant("NO_COLOR"))15 else if (process.hasNonEmptyEnvVarConstant("NO_COLOR"))
16 false16 false
17 else if (process.hasEnvVarConstant("CLICOLOR_FORCE"))17 else if (process.hasNonEmptyEnvVarConstant("CLICOLOR_FORCE"))
18 true18 true
19 else19 else
20 null;20 null;
lib/std/process.zig+35
...@@ -431,6 +431,20 @@ pub fn hasEnvVarConstant(comptime key: []const u8) bool {...@@ -431,6 +431,20 @@ pub fn hasEnvVarConstant(comptime key: []const u8) bool {
431 }431 }
432}432}
433433
434/// On Windows, `key` must be valid UTF-8.
435pub fn hasNonEmptyEnvVarConstant(comptime key: []const u8) bool {
436 if (native_os == .windows) {
437 const key_w = comptime unicode.utf8ToUtf16LeStringLiteral(key);
438 const value = getenvW(key_w) orelse return false;
439 return value.len != 0;
440 } else if (native_os == .wasi and !builtin.link_libc) {
441 @compileError("hasNonEmptyEnvVarConstant is not supported for WASI without libc");
442 } else {
443 const value = posix.getenv(key) orelse return false;
444 return value.len != 0;
445 }
446}
447
434pub const ParseEnvVarIntError = std.fmt.ParseIntError || error{EnvironmentVariableNotFound};448pub const ParseEnvVarIntError = std.fmt.ParseIntError || error{EnvironmentVariableNotFound};
435449
436/// Parses an environment variable as an integer.450/// Parses an environment variable as an integer.
...@@ -477,6 +491,27 @@ pub fn hasEnvVar(allocator: Allocator, key: []const u8) HasEnvVarError!bool {...@@ -477,6 +491,27 @@ pub fn hasEnvVar(allocator: Allocator, key: []const u8) HasEnvVarError!bool {
477 }491 }
478}492}
479493
494/// On Windows, if `key` is not valid [WTF-8](https://simonsapin.github.io/wtf-8/),
495/// then `error.InvalidWtf8` is returned.
496pub fn hasNonEmptyEnvVar(allocator: Allocator, key: []const u8) HasEnvVarError!bool {
497 if (native_os == .windows) {
498 var stack_alloc = std.heap.stackFallback(256 * @sizeOf(u16), allocator);
499 const stack_allocator = stack_alloc.get();
500 const key_w = try unicode.wtf8ToWtf16LeAllocZ(stack_allocator, key);
501 defer stack_allocator.free(key_w);
502 const value = getenvW(key_w) orelse return false;
503 return value.len != 0;
504 } else if (native_os == .wasi and !builtin.link_libc) {
505 var envmap = getEnvMap(allocator) catch return error.OutOfMemory;
506 defer envmap.deinit();
507 const value = envmap.getPtr(key) orelse return false;
508 return value.len != 0;
509 } else {
510 const value = posix.getenv(key) orelse return false;
511 return value.len != 0;
512 }
513}
514
480/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.515/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.
481///516///
482/// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString.517/// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString.
lib/std/zig.zig+4-5
...@@ -697,6 +697,10 @@ pub const EnvVar = enum {...@@ -697,6 +697,10 @@ pub const EnvVar = enum {
697 XDG_CACHE_HOME,697 XDG_CACHE_HOME,
698 HOME,698 HOME,
699699
700 pub fn isSet(comptime ev: EnvVar) bool {
701 return std.process.hasNonEmptyEnvVarConstant(@tagName(ev));
702 }
703
700 pub fn get(ev: EnvVar, arena: std.mem.Allocator) !?[]u8 {704 pub fn get(ev: EnvVar, arena: std.mem.Allocator) !?[]u8 {
701 if (std.process.getEnvVarOwned(arena, @tagName(ev))) |value| {705 if (std.process.getEnvVarOwned(arena, @tagName(ev))) |value| {
702 return value;706 return value;
...@@ -709,11 +713,6 @@ pub const EnvVar = enum {...@@ -709,11 +713,6 @@ pub const EnvVar = enum {
709 pub fn getPosix(comptime ev: EnvVar) ?[:0]const u8 {713 pub fn getPosix(comptime ev: EnvVar) ?[:0]const u8 {
710 return std.posix.getenvZ(@tagName(ev));714 return std.posix.getenvZ(@tagName(ev));
711 }715 }
712
713 pub fn isSet(ev: EnvVar, arena: std.mem.Allocator) !bool {
714 const value = try ev.get(arena) orelse return false;
715 return value.len != 0;
716 }
717};716};
718717
719pub const SimpleComptimeReason = enum(u32) {718pub const SimpleComptimeReason = enum(u32) {
src/main.zig+9-9
...@@ -826,9 +826,9 @@ fn buildOutputType(...@@ -826,9 +826,9 @@ fn buildOutputType(
826 var listen: Listen = .none;826 var listen: Listen = .none;
827 var debug_compile_errors = false;827 var debug_compile_errors = false;
828 var verbose_link = (native_os != .wasi or builtin.link_libc) and828 var verbose_link = (native_os != .wasi or builtin.link_libc) and
829 try EnvVar.ZIG_VERBOSE_LINK.isSet(arena);829 EnvVar.ZIG_VERBOSE_LINK.isSet();
830 var verbose_cc = (native_os != .wasi or builtin.link_libc) and830 var verbose_cc = (native_os != .wasi or builtin.link_libc) and
831 try EnvVar.ZIG_VERBOSE_CC.isSet(arena);831 EnvVar.ZIG_VERBOSE_CC.isSet();
832 var verbose_air = false;832 var verbose_air = false;
833 var verbose_intern_pool = false;833 var verbose_intern_pool = false;
834 var verbose_generic_instances = false;834 var verbose_generic_instances = false;
...@@ -1006,9 +1006,9 @@ fn buildOutputType(...@@ -1006,9 +1006,9 @@ fn buildOutputType(
1006 // if set, default the color setting to .off or .on, respectively1006 // if set, default the color setting to .off or .on, respectively
1007 // explicit --color arguments will still override this setting.1007 // explicit --color arguments will still override this setting.
1008 // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/1621008 // Disable color on WASI per https://github.com/WebAssembly/WASI/issues/162
1009 var color: Color = if (native_os == .wasi or try EnvVar.NO_COLOR.isSet(arena))1009 var color: Color = if (native_os == .wasi or EnvVar.NO_COLOR.isSet())
1010 .off1010 .off
1011 else if (try EnvVar.CLICOLOR_FORCE.isSet(arena))1011 else if (EnvVar.CLICOLOR_FORCE.isSet())
1012 .on1012 .on
1013 else1013 else
1014 .auto;1014 .auto;
...@@ -4769,9 +4769,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4769,9 +4769,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4769 var reference_trace: ?u32 = null;4769 var reference_trace: ?u32 = null;
4770 var debug_compile_errors = false;4770 var debug_compile_errors = false;
4771 var verbose_link = (native_os != .wasi or builtin.link_libc) and4771 var verbose_link = (native_os != .wasi or builtin.link_libc) and
4772 try EnvVar.ZIG_VERBOSE_LINK.isSet(arena);4772 EnvVar.ZIG_VERBOSE_LINK.isSet();
4773 var verbose_cc = (native_os != .wasi or builtin.link_libc) and4773 var verbose_cc = (native_os != .wasi or builtin.link_libc) and
4774 try EnvVar.ZIG_VERBOSE_CC.isSet(arena);4774 EnvVar.ZIG_VERBOSE_CC.isSet();
4775 var verbose_air = false;4775 var verbose_air = false;
4776 var verbose_intern_pool = false;4776 var verbose_intern_pool = false;
4777 var verbose_generic_instances = false;4777 var verbose_generic_instances = false;
...@@ -4954,7 +4954,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4954,7 +4954,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4954 }4954 }
49554955
4956 const work_around_btrfs_bug = native_os == .linux and4956 const work_around_btrfs_bug = native_os == .linux and
4957 try EnvVar.ZIG_BTRFS_WORKAROUND.isSet(arena);4957 EnvVar.ZIG_BTRFS_WORKAROUND.isSet();
4958 const root_prog_node = std.Progress.start(.{4958 const root_prog_node = std.Progress.start(.{
4959 .disable_printing = (color == .off),4959 .disable_printing = (color == .off),
4960 .root_name = "Compile Build Script",4960 .root_name = "Compile Build Script",
...@@ -5461,7 +5461,7 @@ fn jitCmd(...@@ -5461,7 +5461,7 @@ fn jitCmd(
5461 fatal("unable to find self exe path: {s}", .{@errorName(err)});5461 fatal("unable to find self exe path: {s}", .{@errorName(err)});
5462 };5462 };
54635463
5464 const optimize_mode: std.builtin.OptimizeMode = if (try EnvVar.ZIG_DEBUG_CMD.isSet(arena))5464 const optimize_mode: std.builtin.OptimizeMode = if (EnvVar.ZIG_DEBUG_CMD.isSet())
5465 .Debug5465 .Debug
5466 else5466 else
5467 .ReleaseFast;5467 .ReleaseFast;
...@@ -6976,7 +6976,7 @@ fn cmdFetch(...@@ -6976,7 +6976,7 @@ fn cmdFetch(
69766976
6977 const color: Color = .auto;6977 const color: Color = .auto;
6978 const work_around_btrfs_bug = native_os == .linux and6978 const work_around_btrfs_bug = native_os == .linux and
6979 try EnvVar.ZIG_BTRFS_WORKAROUND.isSet(arena);6979 EnvVar.ZIG_BTRFS_WORKAROUND.isSet();
6980 var opt_path_or_url: ?[]const u8 = null;6980 var opt_path_or_url: ?[]const u8 = null;
6981 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);6981 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
6982 var debug_hash: bool = false;6982 var debug_hash: bool = false;