const std = @import("std"); /// Keys that are available for encryption keys: []const SSHKeyPair, /// Rules for how to match the scan command scan: ScanConfig = .default, pub const SSHKeyPair = struct { private: []const u8, public: []const u8, }; /// Configuration for the scan command pub const ScanConfig = struct { /// the file extension to look for matcher: []const u8, /// Glob patterns to ignore exclude: []const []const u8, /// paths to search in include: []const []const u8, const default: @This() = .{ .matcher = "\\.env", .exclude = &.{ "*\\.envrc", "\\.local", "node_modules", "vendor", }, .include = &.{"~"}, }; }; /// Load the Config from the file at path pub fn load(io: std.Io, gpa: std.mem.Allocator, path: []const u8) !std.json.Parsed(@This()) { // TODO: Read ~/.envr/config.json into buffer var file = try std.Io.Dir.cwd().openFile( io, path, .{ .mode = .read_only }, ); defer file.close(io); var buffer: [4096]u8 = undefined; var reader = file.reader(io, &buffer); var json_reader: std.json.Reader = .init(gpa, &reader.interface); defer json_reader.deinit(); return try std.json.parseFromTokenSource( @This(), gpa, &json_reader, .{}, ); } pub fn save( self: *@This(), io: std.Io, gpa: std.mem.Allocator, path: []const u8, ) !void { // FIXME: Implement _ = self; _ = io; _ = gpa; _ = path; } test "loading the default config from disk matches expected values" { const gpa = std.testing.allocator; const parsed = try load(std.testing.io, gpa, "./fixtures/default_config.json"); defer parsed.deinit(); const got = parsed.value; try std.testing.expectEqualDeep(got.scan, ScanConfig.default); } test "saving to a new file works" { // TODO: assert file doesn't exist var cfg: @This() = .{ .keys = &.{ //.from_path("~/.ssh/id_ed25519.pub") .{ .public = "~/.ssh/id_ed25519.pub", .private = "~/.ssh/id_ed25519", }}, }; try cfg.save(std.testing.io, std.testing.allocator, "/some/tmp/path"); // TODO: assert file contents matches expectations. } // TODO: test "saving to an existing fie updates the file"