mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Respect XDG_CACHE_HOME
and useNSFileManager
for cache paths
This commit is contained in:
@ -101,7 +101,10 @@ fn initThread(gpa: Allocator) !void {
|
||||
sentry.c.sentry_options_set_before_send(opts, beforeSend, null);
|
||||
|
||||
// Determine the Sentry cache directory.
|
||||
const cache_dir = try internal_os.xdg.cache(alloc, .{ .subdir = "ghostty/sentry" });
|
||||
const cache_dir = if (builtin.os.tag == .macos)
|
||||
try internal_os.macos.cacheDir(alloc, "ghostty/sentry")
|
||||
else
|
||||
try internal_os.xdg.cache(alloc, .{ .subdir = "ghostty/sentry" });
|
||||
sentry.c.sentry_options_set_database_path_n(
|
||||
opts,
|
||||
cache_dir.ptr,
|
||||
|
109
src/os/macos.zig
109
src/os/macos.zig
@ -25,43 +25,23 @@ pub fn appSupportDir(
|
||||
alloc: Allocator,
|
||||
sub_path: []const u8,
|
||||
) AppSupportDirError![]const u8 {
|
||||
comptime assert(builtin.target.isDarwin());
|
||||
|
||||
const NSFileManager = objc.getClass("NSFileManager").?;
|
||||
const manager = NSFileManager.msgSend(
|
||||
objc.Object,
|
||||
objc.sel("defaultManager"),
|
||||
.{},
|
||||
);
|
||||
|
||||
const url = manager.msgSend(
|
||||
objc.Object,
|
||||
objc.sel("URLForDirectory:inDomain:appropriateForURL:create:error:"),
|
||||
.{
|
||||
NSSearchPathDirectory.NSApplicationSupportDirectory,
|
||||
NSSearchPathDomainMask.NSUserDomainMask,
|
||||
@as(?*anyopaque, null),
|
||||
true,
|
||||
@as(?*anyopaque, null),
|
||||
},
|
||||
);
|
||||
|
||||
// I don't think this is possible but just in case.
|
||||
if (url.value == null) return error.AppleAPIFailed;
|
||||
|
||||
// Get the UTF-8 string from the URL.
|
||||
const path = url.getProperty(objc.Object, "path");
|
||||
const c_str = path.getProperty(?[*:0]const u8, "UTF8String") orelse
|
||||
return error.AppleAPIFailed;
|
||||
const app_support_dir = std.mem.sliceTo(c_str, 0);
|
||||
|
||||
return try std.fs.path.join(alloc, &.{
|
||||
app_support_dir,
|
||||
return try makeCommonPath(alloc, .NSApplicationSupportDirectory, &.{
|
||||
build_config.bundle_id,
|
||||
sub_path,
|
||||
});
|
||||
}
|
||||
|
||||
pub const CacheDirError = Allocator.Error || error{AppleAPIFailed};
|
||||
|
||||
/// Return the path to the system cache directory with the given sub path joined.
|
||||
/// This allocates the result using the given allocator.
|
||||
pub fn cacheDir(
|
||||
alloc: Allocator,
|
||||
sub_path: []const u8,
|
||||
) CacheDirError![]const u8 {
|
||||
return try makeCommonPath(alloc, .NSCachesDirectory, &.{sub_path});
|
||||
}
|
||||
|
||||
pub const SetQosClassError = error{
|
||||
// The thread can't have its QoS class changed usually because
|
||||
// a different pthread API was called that makes it an invalid
|
||||
@ -110,9 +90,74 @@ pub const NSOperatingSystemVersion = extern struct {
|
||||
};
|
||||
|
||||
pub const NSSearchPathDirectory = enum(c_ulong) {
|
||||
NSCachesDirectory = 13,
|
||||
NSApplicationSupportDirectory = 14,
|
||||
};
|
||||
|
||||
pub const NSSearchPathDomainMask = enum(c_ulong) {
|
||||
NSUserDomainMask = 1,
|
||||
};
|
||||
|
||||
fn makeCommonPath(
|
||||
alloc: Allocator,
|
||||
directory: NSSearchPathDirectory,
|
||||
sub_paths: []const []const u8,
|
||||
) (error{AppleAPIFailed} || Allocator.Error)![]const u8 {
|
||||
comptime assert(builtin.target.isDarwin());
|
||||
|
||||
const NSFileManager = objc.getClass("NSFileManager").?;
|
||||
const manager = NSFileManager.msgSend(
|
||||
objc.Object,
|
||||
objc.sel("defaultManager"),
|
||||
.{},
|
||||
);
|
||||
|
||||
const url = manager.msgSend(
|
||||
objc.Object,
|
||||
objc.sel("URLForDirectory:inDomain:appropriateForURL:create:error:"),
|
||||
.{
|
||||
directory,
|
||||
NSSearchPathDomainMask.NSUserDomainMask,
|
||||
@as(?*anyopaque, null),
|
||||
true,
|
||||
@as(?*anyopaque, null),
|
||||
},
|
||||
);
|
||||
|
||||
if (url.value == null) return error.AppleAPIFailed;
|
||||
|
||||
const path = url.getProperty(objc.Object, "path");
|
||||
const c_str = path.getProperty(?[*:0]const u8, "UTF8String") orelse
|
||||
return error.AppleAPIFailed;
|
||||
const base_dir = std.mem.sliceTo(c_str, 0);
|
||||
|
||||
// Create a new array with base_dir as the first element
|
||||
var paths = try alloc.alloc([]const u8, sub_paths.len + 1);
|
||||
paths[0] = base_dir;
|
||||
@memcpy(paths[1..], sub_paths);
|
||||
defer alloc.free(paths);
|
||||
|
||||
return try std.fs.path.join(alloc, paths);
|
||||
}
|
||||
|
||||
test "cacheDir paths" {
|
||||
if (!builtin.target.isDarwin()) return;
|
||||
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
// Test base path
|
||||
{
|
||||
const cache_path = try cacheDir(alloc, "");
|
||||
defer alloc.free(cache_path);
|
||||
// We don't test the exact path since it comes from NSFileManager
|
||||
try testing.expect(std.mem.indexOf(u8, cache_path, "Caches") != null);
|
||||
}
|
||||
|
||||
// Test with subdir
|
||||
{
|
||||
const cache_path = try cacheDir(alloc, "ghostty");
|
||||
defer alloc.free(cache_path);
|
||||
try testing.expect(std.mem.indexOf(u8, cache_path, "Caches/ghostty") != null);
|
||||
}
|
||||
}
|
||||
|
@ -30,18 +30,9 @@ pub fn config(alloc: Allocator, opts: Options) ![]u8 {
|
||||
|
||||
/// Get the XDG cache directory. The returned value is allocated.
|
||||
pub fn cache(alloc: Allocator, opts: Options) ![]u8 {
|
||||
// On macOS we should use ~/Library/Caches instead of ~/.cache
|
||||
if (builtin.os.tag == .macos) {
|
||||
// Get our home dir if not provided
|
||||
const home = if (opts.home) |h| h else blk: {
|
||||
var buf: [1024]u8 = undefined;
|
||||
break :blk try homedir.home(&buf) orelse return error.NoHomeDir;
|
||||
};
|
||||
|
||||
if (posix.getenv("XDG_CACHE_HOME")) |env| {
|
||||
return try std.fs.path.join(alloc, &[_][]const u8{
|
||||
home,
|
||||
"Library",
|
||||
"Caches",
|
||||
env,
|
||||
opts.subdir orelse "",
|
||||
});
|
||||
}
|
||||
@ -164,28 +155,8 @@ test "cache directory paths" {
|
||||
const alloc = testing.allocator;
|
||||
const mock_home = "/Users/test";
|
||||
|
||||
// Test macOS path
|
||||
if (builtin.os.tag == .macos) {
|
||||
// Test base path
|
||||
{
|
||||
const cache_path = try cache(alloc, .{ .home = mock_home });
|
||||
defer alloc.free(cache_path);
|
||||
try testing.expectEqualStrings("/Users/test/Library/Caches", cache_path);
|
||||
}
|
||||
|
||||
// Test with subdir
|
||||
{
|
||||
const cache_path = try cache(alloc, .{
|
||||
.home = mock_home,
|
||||
.subdir = "ghostty",
|
||||
});
|
||||
defer alloc.free(cache_path);
|
||||
try testing.expectEqualStrings("/Users/test/Library/Caches/ghostty", cache_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Test Linux path (when XDG_CACHE_HOME is not set)
|
||||
if (builtin.os.tag == .linux) {
|
||||
// Test when XDG_CACHE_HOME is not set
|
||||
{
|
||||
// Test base path
|
||||
{
|
||||
const cache_path = try cache(alloc, .{ .home = mock_home });
|
||||
|
Reference in New Issue
Block a user