diff --git a/fixtures/default_config.json b/fixtures/default_config.json new file mode 100644 index 0000000..5e91902 --- /dev/null +++ b/fixtures/default_config.json @@ -0,0 +1,20 @@ +{ + "keys": [ + { + "private": "/home/spencer/.ssh/id_ed25519", + "public": "/home/spencer/.ssh/id_ed25519.pub" + } + ], + "scan": { + "matcher": "\\.env", + "exclude": [ + "*\\.envrc", + "\\.local", + "node_modules", + "vendor" + ], + "include": [ + "~" + ] + } +} diff --git a/src/config.zig b/src/config.zig new file mode 100644 index 0000000..36c41a8 --- /dev/null +++ b/src/config.zig @@ -0,0 +1,102 @@ +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"