os: more error handling on reading the app support dir

This commit is contained in:
Mitchell Hashimoto
2024-11-25 16:04:16 -08:00
parent 10e37a3dee
commit adc59be977
2 changed files with 49 additions and 31 deletions

View File

@ -1809,14 +1809,10 @@ pub fn deinit(self: *Config) void {
/// Load the configuration according to the default rules:
///
/// 1. Defaults
/// 2. Configuration Files
/// 3. CLI flags
/// 4. Recursively defined configuration files
///
/// Configuration files are loaded in the follow order:
///
/// 1. XDG Config File
/// 2. "Application Support" Config File on macOS
/// 2. XDG config dir
/// 3. "Application Support" directory (macOS only)
/// 4. CLI flags
/// 5. Recursively defined configuration files
///
pub fn load(alloc_gpa: Allocator) !Config {
var result = try default(alloc_gpa);
@ -2423,8 +2419,8 @@ pub fn loadDefaultFiles(self: *Config, alloc: Allocator) !void {
defer alloc.free(xdg_path);
self.loadOptionalFile(alloc, xdg_path);
if (builtin.os.tag == .macos) {
const app_support_path = try internal_os.macos.getAppSupportDir(alloc, "config");
if (comptime builtin.os.tag == .macos) {
const app_support_path = try internal_os.macos.appSupportDir(alloc, "config");
defer alloc.free(app_support_path);
self.loadOptionalFile(alloc, app_support_path);
}

View File

@ -4,15 +4,9 @@ const assert = std.debug.assert;
const objc = @import("objc");
const Allocator = std.mem.Allocator;
pub const NSOperatingSystemVersion = extern struct {
major: i64,
minor: i64,
patch: i64,
};
/// Verifies that the running macOS system version is at least the given version.
pub fn isAtLeastVersion(major: i64, minor: i64, patch: i64) bool {
assert(builtin.target.isDarwin());
comptime assert(builtin.target.isDarwin());
const NSProcessInfo = objc.getClass("NSProcessInfo").?;
const info = NSProcessInfo.msgSend(objc.Object, objc.sel("processInfo"), .{});
@ -21,20 +15,24 @@ pub fn isAtLeastVersion(major: i64, minor: i64, patch: i64) bool {
});
}
pub const NSSearchPathDirectory = enum(c_ulong) {
NSApplicationSupportDirectory = 14,
};
pub const AppSupportDirError = Allocator.Error || error{AppleAPIFailed};
pub const NSSearchPathDomainMask = enum(c_ulong) {
NSUserDomainMask = 1,
};
/// Return the path to the application support directory for Ghostty
/// with the given sub path joined. This allocates the result using the
/// given allocator.
pub fn appSupportDir(
alloc: Allocator,
sub_path: []const u8,
) AppSupportDirError![]u8 {
comptime assert(builtin.target.isDarwin());
pub fn getAppSupportDir(alloc: Allocator, sub_path: []const u8) ![]u8 {
assert(builtin.target.isDarwin());
const err: ?*anyopaque = undefined;
const NSFileManager = objc.getClass("NSFileManager").?;
const manager = NSFileManager.msgSend(objc.Object, objc.sel("defaultManager"), .{});
const manager = NSFileManager.msgSend(
objc.Object,
objc.sel("defaultManager"),
.{},
);
const url = manager.msgSend(
objc.Object,
objc.sel("URLForDirectory:inDomain:appropriateForURL:create:error:"),
@ -43,12 +41,36 @@ pub fn getAppSupportDir(alloc: Allocator, sub_path: []const u8) ![]u8 {
NSSearchPathDomainMask.NSUserDomainMask,
@as(?*anyopaque, null),
true,
&err,
@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");
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, "com.mitchellh.ghostty", sub_path });
return try std.fs.path.join(alloc, &.{
app_support_dir,
"com.mitchellh.ghostty",
sub_path,
});
}
pub const NSOperatingSystemVersion = extern struct {
major: i64,
minor: i64,
patch: i64,
};
pub const NSSearchPathDirectory = enum(c_ulong) {
NSApplicationSupportDirectory = 14,
};
pub const NSSearchPathDomainMask = enum(c_ulong) {
NSUserDomainMask = 1,
};