feat: write default config.toml if it doesn't exist

also resolves panic on missing /zba or /zba/save directory by ensuring
those directories exist as soon as we know the data directory
This commit is contained in:
Rekai Nyangadzayi Musuka 2022-10-21 05:13:13 -03:00
parent 7944cd7abc
commit 583ed54ee3
2 changed files with 17 additions and 11 deletions

View File

@ -13,6 +13,7 @@ pub fn build(b: *std.build.Builder) void {
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
const exe = b.addExecutable("zba", "src/main.zig"); const exe = b.addExecutable("zba", "src/main.zig");
exe.setMainPkgPath("."); // Necessary so that src/main.zig can embed example.toml
exe.setTarget(target); exe.setTarget(target);
// Known Folders (%APPDATA%, XDG, etc.) // Known Folders (%APPDATA%, XDG, etc.)

View File

@ -37,7 +37,10 @@ pub fn main() anyerror!void {
const data_path = blk: { const data_path = blk: {
const result = known_folders.getPath(allocator, .data); const result = known_folders.getPath(allocator, .data);
const option = result catch |e| exitln("interrupted while attempting to find a data directory: {}", .{e}); const option = result catch |e| exitln("interrupted while attempting to find a data directory: {}", .{e});
break :blk option orelse exitln("no valid data directory could be found", .{}); const path = option orelse exitln("no valid data directory could be found", .{});
ensureDirectoriesExist(path) catch |e| exitln("failed to create directories under \"{s}\": {}", .{ path, e });
break :blk path;
}; };
defer allocator.free(data_path); defer allocator.free(data_path);
@ -86,7 +89,7 @@ pub fn handleArguments(allocator: Allocator, data_path: []const u8, result: *con
const bios_path = result.args.bios; const bios_path = result.args.bios;
if (bios_path) |path| log.info("BIOS path: {s}", .{path}) else log.warn("No BIOS provided", .{}); if (bios_path) |path| log.info("BIOS path: {s}", .{path}) else log.warn("No BIOS provided", .{});
const save_path = try savePath(allocator, data_path); const save_path = try std.fs.path.join(allocator, &[_][]const u8{ data_path, "zba", "save" });
log.info("Save path: {s}", .{save_path}); log.info("Save path: {s}", .{save_path});
return .{ return .{
@ -103,25 +106,27 @@ fn configFilePath(allocator: Allocator, data_path: []const u8) ![]const u8 {
// We try to create the file exclusively, meaning that we err out if the file already exists. // We try to create the file exclusively, meaning that we err out if the file already exists.
// All we care about is a file being there so we can just ignore that error in particular and // All we care about is a file being there so we can just ignore that error in particular and
// continue down the happy pathj // continue down the happy pathj
std.fs.accessAbsolute(path, .{}) catch { std.fs.accessAbsolute(path, .{}) catch |e| {
const file_handle = try std.fs.createFileAbsolute(path, .{}); if (e != error.FileNotFound) return e;
defer file_handle.close();
// TODO: Write Default valeus to config file const config_file = try std.fs.createFileAbsolute(path, .{});
defer config_file.close();
try config_file.writeAll(@embedFile("../example.toml"));
}; };
return path; return path;
} }
fn savePath(allocator: Allocator, data_path: []const u8) ![]const u8 { fn ensureDirectoriesExist(data_path: []const u8) !void {
var dir = try std.fs.openDirAbsolute(data_path, .{}); var dir = try std.fs.openDirAbsolute(data_path, .{});
defer dir.close(); defer dir.close();
// Will either make the path recursively, or just exit early since it already exists // We want to make sure: %APPDATA%/zba and %APPDATA%/zba/save exist
try dir.makePath("zba" ++ [_]u8{std.fs.path.sep} ++ "save"); // (~/.local/share/zba/save for linux, ??? for macOS)
// FIXME: Do we have to allocate? :sad: // Will recursively create directories
return try std.fs.path.join(allocator, &[_][]const u8{ data_path, "zba", "save" }); try dir.makePath("zba" ++ [_]u8{std.fs.path.sep} ++ "save");
} }
fn romPath(result: *const clap.Result(clap.Help, &params, clap.parsers.default)) []const u8 { fn romPath(result: *const clap.Result(clap.Help, &params, clap.parsers.default)) []const u8 {