std: remove fs.getAppDataDir with no replacement

This API is a bit too opinionated for the Zig standard library.
Applications should contain this logic instead.
This commit is contained in:
Andrew Kelley 2025-12-30 13:34:18 -08:00
parent 96ba0ab930
commit e956948f99
6 changed files with 36 additions and 89 deletions

View file

@ -436,7 +436,6 @@ set(ZIG_STAGE2_SOURCES
lib/std/fmt.zig
lib/std/fmt/parse_float.zig
lib/std/fs.zig
lib/std/fs/get_app_data_dir.zig
lib/std/fs/path.zig
lib/std/hash.zig
lib/std/hash/auto_hash.zig

View file

@ -6,9 +6,6 @@ const std = @import("std.zig");
pub const path = @import("fs/path.zig");
pub const wasi = @import("fs/wasi.zig");
pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir;
pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError;
pub const base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*;
/// Base64 encoder, replacing the standard `+/` with `-_` so that it can be used in a file name on any filesystem.
@ -25,5 +22,4 @@ pub const max_name_bytes = std.Io.Dir.max_name_bytes;
test {
_ = path;
_ = @import("fs/test.zig");
_ = @import("fs/get_app_data_dir.zig");
}

View file

@ -1,66 +0,0 @@
const std = @import("../std.zig");
const builtin = @import("builtin");
const unicode = std.unicode;
const mem = std.mem;
const fs = std.fs;
const native_os = builtin.os.tag;
const posix = std.posix;
pub const GetAppDataDirError = error{
OutOfMemory,
AppDataDirUnavailable,
};
/// Caller owns returned memory.
/// TODO determine if we can remove the allocator requirement
pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 {
switch (native_os) {
.windows => {
const local_app_data_dir = std.process.getEnvVarOwned(allocator, "LOCALAPPDATA") catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => return error.AppDataDirUnavailable,
};
defer allocator.free(local_app_data_dir);
return fs.path.join(allocator, &[_][]const u8{ local_app_data_dir, appname });
},
.maccatalyst, .macos => {
const home_dir = posix.getenv("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
},
.linux, .freebsd, .netbsd, .dragonfly, .openbsd, .illumos, .serenity => {
if (posix.getenv("XDG_DATA_HOME")) |xdg| {
if (xdg.len > 0) {
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
}
}
const home_dir = posix.getenv("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname });
},
.haiku => {
var dir_path_buf: [std.fs.max_path_bytes]u8 = undefined;
const rc = std.c.find_directory(.B_USER_SETTINGS_DIRECTORY, -1, true, &dir_path_buf, dir_path_buf.len);
const settings_dir = try allocator.dupeZ(u8, mem.sliceTo(&dir_path_buf, 0));
defer allocator.free(settings_dir);
switch (rc) {
0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }),
else => return error.AppDataDirUnavailable,
}
},
else => @compileError("Unsupported OS"),
}
}
test getAppDataDir {
if (native_os == .wasi) return error.SkipZigTest;
// We can't actually validate the result
const dir = getAppDataDir(std.testing.allocator, "zig") catch return;
defer std.testing.allocator.free(dir);
}

View file

@ -743,6 +743,7 @@ pub const EnvVar = enum {
NO_COLOR,
CLICOLOR_FORCE,
XDG_CACHE_HOME,
LOCALAPPDATA,
HOME,
pub fn isSet(comptime ev: EnvVar) bool {

View file

@ -860,7 +860,14 @@ const MsvcLibDir = struct {
// %localappdata%\Microsoft\VisualStudio\
// %appdata%\Local\Microsoft\VisualStudio\
const visualstudio_folder_path = std.fs.getAppDataDir(gpa, "Microsoft\\VisualStudio\\") catch return error.PathNotFound;
const local_app_data_path = (std.zig.EnvVar.LOCALAPPDATA.get(gpa) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.InvalidWtf8 => return error.PathNotFound,
}) orelse return error.PathNotFound;
defer gpa.free(local_app_data_path);
const visualstudio_folder_path = try Dir.path.join(gpa, &.{
local_app_data_path, "Microsoft\\VisualStudio\\",
});
defer gpa.free(visualstudio_folder_path);
const vs_versions: []const []const u8 = vs_versions: {

View file

@ -1,5 +1,4 @@
const builtin = @import("builtin");
const build_options = @import("build_options");
const std = @import("std");
const Io = std.Io;
@ -8,6 +7,8 @@ const mem = std.mem;
const Allocator = std.mem.Allocator;
const Cache = std.Build.Cache;
const build_options = @import("build_options");
const Compilation = @import("Compilation.zig");
const Package = @import("Package.zig");
@ -101,26 +102,35 @@ pub fn findZigLibDirFromSelfExe(
}
/// Caller owns returned memory.
pub fn resolveGlobalCacheDir(allocator: Allocator) ![]u8 {
if (builtin.os.tag == .wasi)
@compileError("on WASI the global cache dir must be resolved with preopens");
pub fn resolveGlobalCacheDir(gpa: Allocator) ![]u8 {
if (try std.zig.EnvVar.ZIG_GLOBAL_CACHE_DIR.get(gpa)) |value| return value;
if (try std.zig.EnvVar.ZIG_GLOBAL_CACHE_DIR.get(allocator)) |value| return value;
const app_name = "zig";
const appname = "zig";
if (builtin.os.tag != .windows) {
if (std.zig.EnvVar.XDG_CACHE_HOME.getPosix()) |cache_root| {
if (cache_root.len > 0) {
return Dir.path.join(allocator, &.{ cache_root, appname });
switch (builtin.os.tag) {
.wasi => @compileError("on WASI the global cache dir must be resolved with preopens"),
.windows => {
const local_app_data_dir = (std.zig.EnvVar.LOCALAPPDATA.get(gpa) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.InvalidWtf8 => return error.AppDataDirUnavailable,
}) orelse return error.AppDataDirUnavailable;
defer gpa.free(local_app_data_dir);
return Dir.path.join(gpa, &.{ local_app_data_dir, app_name });
},
else => {
if (std.zig.EnvVar.XDG_CACHE_HOME.getPosix()) |cache_root| {
if (cache_root.len > 0) {
return Dir.path.join(gpa, &.{ cache_root, app_name });
}
}
}
if (std.zig.EnvVar.HOME.getPosix()) |home| {
return Dir.path.join(allocator, &.{ home, ".cache", appname });
}
if (std.zig.EnvVar.HOME.getPosix()) |home| {
if (home.len > 0) {
return Dir.path.join(gpa, &.{ home, ".cache", app_name });
}
}
return error.AppDataDirUnavailable;
},
}
return std.fs.getAppDataDir(allocator, appname);
}
/// Similar to `Dir.path.resolve`, but converts to a cwd-relative path, or, if that would