diff options
Diffstat (limited to '')
| -rw-r--r-- | src/Content.zig | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/src/Content.zig b/src/Content.zig deleted file mode 100644 index 120d8b5..0000000 --- a/src/Content.zig +++ /dev/null @@ -1,210 +0,0 @@ -const std = @import("std"); -const os = @import("os.zig"); - -const Content = @This(); -const log = std.log.scoped(.Content); - -pub const Digest = [64]u8; - -io: std.Io, -arena: *std.heap.ArenaAllocator, -root: std.Io.Dir, - -pub fn init(io: std.Io, allocator: std.mem.Allocator, root_dir: std.Io.Dir) !Content { - const arena = try allocator.create(std.heap.ArenaAllocator); - errdefer allocator.destroy(arena); - arena.* = std.heap.ArenaAllocator.init(allocator); - - return .{ - .io = io, - .arena = arena, - .root = root_dir, - }; -} - -pub fn deinit(self: *Content) void { - self.root.close(self.io); - const allocator = self.arena.child_allocator; - self.arena.deinit(); - allocator.destroy(self.arena); -} - -pub fn digest(self: *Content, dir: std.Io.Dir, sub_path: []const u8) !Digest { - // generate sha256 digest - // TODO: use zig-based hashing? - const command = blk: { - var buf: [std.os.linux.PATH_MAX + 10]u8 = undefined; - @memcpy(buf[0..10], "sha256sum "); - @memcpy(buf[10 .. 10 + sub_path.len], sub_path); - break :blk buf[0 .. 10 + sub_path.len]; - }; - var buf: [std.os.linux.PATH_MAX + 64]u8 = undefined; - var w = std.Io.Writer.fixed(&buf); - try os.captureStdout(self.io, command, .{ .cwd = .{ .dir = dir } }, &w); - - // take only the digest - return buf[0..64].*; -} - -pub fn get(self: *Content, dgst: Digest) !?Digest { - const found = blk: { - self.root.access(self.io, &dgst, .{}) catch |err| switch (err) { - error.FileNotFound => break :blk false, - else => return err, - }; - break :blk true; - }; - if (found) { - return dgst; - } else { - return null; - } -} - -pub fn add(self: *Content, dir: std.Io.Dir, sub_path: []const u8) !Digest { - const dgst = try self.digest(dir, sub_path); - - return (try self.get(dgst)) orelse { - // create digest directory - try self.root.createDirPath(self.io, &dgst); - - log.debug("Added {s}", .{dgst}); - return dgst; - }; -} - -pub fn del(self: *Content, dgst: Digest) !void { - try self.root.deleteTree(self.io, &dgst); -} - -const Enumerator = struct { - content: *Content, - walker: std.Io.Dir.SelectiveWalker, - - pub fn deinit(self: *Enumerator) void { - self.walker.deinit(); - } - - pub fn next(self: *Enumerator) !?Digest { - if (try self.walker.next(self.content.io)) |e| { - switch (e.kind) { - // TODO: we should probably check that this is actually a digest - .directory => return e.basename[0..64].*, - else => return null, - } - } else { - return null; - } - } -}; - -pub fn enumerate(self: *Content, allocator: std.mem.Allocator) !Enumerator { - return .{ - .walker = try self.root.walkSelectively(allocator), - .content = self, - }; -} - -pub fn propSet(self: *Content, dgst: Digest, key: []const u8, val: ?[]const u8) !void { - const digest_dir = try self.root.openDir(self.io, &dgst, .{}); - defer digest_dir.close(self.io); - - if (val == null) { - return try digest_dir.deleteFile(self.io, key); - } - - return try digest_dir.writeFile(self.io, .{ - .sub_path = key, - .data = val.?, - }); -} - -pub fn propGet(self: *Content, dgst: Digest, key: []const u8, allocator: std.mem.Allocator) !?[]const u8 { - const digest_dir = try self.root.openDir(self.io, &dgst, .{}); - defer digest_dir.close(self.io); - - if (digest_dir.readFileAlloc(self.io, key, allocator, .unlimited)) |val| { - return val; - } else |err| switch (err) { - error.FileNotFound => return null, - else => return err, - } -} - -// fn checkLink(self: *Content, allocator: std.mem.Allocator, dgst: Digest) ![]const u8 { -// const link_target = try self.propGet(dgst, "link", allocator); -// // check target exists -// try std.Io.Dir.cwd().access(self.io, link_target, .{ .read = true }); -// return link_target; -// } - -test "e2e" { - std.testing.log_level = .debug; - - const DEMO_DIR: []const u8 = "/home/robert/tmp/rbc-demo/"; - const CONTENT_DIR: []const u8 = DEMO_DIR ++ ".content"; - - try std.Io.Dir.cwd().deleteTree(std.testing.io, CONTENT_DIR); - - const demo_dir = try std.Io.Dir.cwd().openDir(std.testing.io, DEMO_DIR, .{ .iterate = true }); - const content_dir = try std.Io.Dir.cwd().createDirPathOpen(std.testing.io, CONTENT_DIR, .{ .open_options = .{ .iterate = true } }); - - var cnt = try Content.init(std.testing.io, std.testing.allocator, content_dir); - defer cnt.deinit(); - - { - var walker = try demo_dir.walkSelectively(std.testing.allocator); - defer walker.deinit(); - - while (try walker.next(std.testing.io)) |e| { - switch (e.kind) { - .file => { - log.info("+ {s}", .{e.path}); - const dgst = try cnt.add(demo_dir, e.path); - try content_dir.access(std.testing.io, &dgst, .{}); - const rel = try std.fs.path.relativePosix(std.testing.allocator, DEMO_DIR, CONTENT_DIR, e.path); - defer std.testing.allocator.free(rel); - try cnt.propSet(dgst, "link", rel); - }, - else => {}, - } - } - } - - var etor = try cnt.enumerate(std.testing.allocator); - defer etor.deinit(); - - { - const dgst = try etor.next(); - try std.testing.expect(dgst != null); - - try cnt.propSet(dgst.?, "foo", "bar"); - const val1 = try cnt.propGet(dgst.?, "foo", std.testing.allocator); - try std.testing.expect(val1 != null); - defer std.testing.allocator.free(val1); - try std.testing.expect(std.mem.eql(u8, "bar", val1.?)); - - try cnt.propSet(dgst.?, "foo", null); - const val2 = try cnt.propGet(dgst.?, "foo", std.testing.allocator); - try std.testing.expect(val2 == null); - } - - { - const dgst = try etor.next(); - try std.testing.expect(dgst != null); - - try cnt.del(dgst.?); - const err = content_dir.access(std.testing.io, &dgst.?, .{}); - try std.testing.expectError(error.FileNotFound, err); - } - - while (try etor.next()) |dgst| { - log.info("? {s}", .{dgst}); - try content_dir.access(std.testing.io, &dgst, .{}); - const link = try cnt.propGet(dgst, "link", std.testing.allocator); - try std.testing.expect(link != null); - defer std.testing.allocator.free(link.?); - try content_dir.access(std.testing.io, link.?, .{}); - log.info("l {s}", .{link.?}); - } -} |