tiny.smg.storage.project
Defined in storage.
API (4)
Actions
Public operations.
Source
Source: tools/smg/src/storage/project.zig
zig
const std = @import("std");const sys = @import("sys");const repo = @import("repo");const smg = @import("../root.zig");const storage = @import("root.zig");const paths = storage.paths;const store = storage.store;const text = smg.text;const fs_io = std.Options.debug_io;pub fn initProject( allocator: std.mem.Allocator, maybe_path: ?[]const u8, limits: smg.StorageLimits,) ![]const u8 { const root = if (maybe_path) |path| try sys.fs.realPathAlloc(allocator, path) else try sys.fs.cwdAlloc(allocator); var opened = try store.open(allocator, root, limits); opened.close(); try ensureGitExclude(allocator, root); return root;}pub fn findRoot(allocator: std.mem.Allocator) !?[]const u8 { const start = try sys.fs.cwdAlloc(allocator); return try findRootFrom(allocator, start);}pub fn initCurrentProject( allocator: std.mem.Allocator, limits: smg.StorageLimits,) ![]const u8 { if (try findRoot(allocator)) |root| return root; const start = try sys.fs.cwdAlloc(allocator); const root = (try checkoutRootFrom(allocator, start)) orelse start; return try initProject(allocator, root, limits);}fn findRootFrom(allocator: std.mem.Allocator, start: []const u8) !?[]const u8 { var repo_storage: [repo.default_capacity.storage_bytes]u8 = undefined; var resolver = try repo.Resolver.init(&repo_storage, repo.default_limits); resolver.activate(); defer _ = resolver.deinit(); const checkout_root = try checkoutRoot(allocator, &resolver, start); const store_dir = (try resolver.findStoreDirFrom(start, paths.smg_dir_name)) orelse return null; const root = std.fs.path.dirname(store_dir) orelse return null; if (checkout_root) |checkout| { if (!pathWithinRoot(checkout, root)) return null; } return try allocator.dupe(u8, root);}fn checkoutRootFrom(allocator: std.mem.Allocator, start: []const u8) !?[]const u8 { var repo_storage: [repo.default_capacity.storage_bytes]u8 = undefined; var resolver = try repo.Resolver.init(&repo_storage, repo.default_limits); resolver.activate(); defer _ = resolver.deinit(); return try checkoutRoot(allocator, &resolver, start);}fn checkoutRoot( allocator: std.mem.Allocator, resolver: *repo.Resolver, start: []const u8,) !?[]const u8 { const git_path = (try resolver.findStoreDirFrom(start, ".git")) orelse return null; const root = std.fs.path.dirname(git_path) orelse return null; return try allocator.dupe(u8, root);}fn pathWithinRoot(root: []const u8, path: []const u8) bool { if (std.mem.eql(u8, root, path)) return true; return path.len > root.len and std.mem.startsWith(u8, path, root) and std.fs.path.isSep(path[root.len]);}pub fn requireRoot(allocator: std.mem.Allocator) ![]const u8 { return (try findRoot(allocator)) orelse error.NoProject;}fn ensureGitExclude(allocator: std.mem.Allocator, root: []const u8) !void { const exclude = try std.fs.path.join(allocator, &.{ root, ".git", "info", "exclude" }); const raw = text.readFile(allocator, exclude, 1024 * 1024) catch return; var lines = std.mem.splitScalar(u8, raw, '\n'); while (lines.next()) |line| { if (std.mem.eql(u8, text.trim(line), ".smg/")) return; } var out: std.Io.Writer.Allocating = .init(allocator); errdefer out.deinit(); try out.writer.writeAll(raw); if (raw.len != 0 and raw[raw.len - 1] != '\n') try out.writer.writeByte('\n'); try out.writer.writeAll(".smg/\n"); try text.writeFile(exclude, out.written());}test "init project creates store directory" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); const root = try std.fmt.allocPrint(allocator, "/tmp/smg-storage-root-test-{x}", .{@as(u64, @intCast(@max(0, sys.time.realMilliTimestamp())))}); defer sys.fs.deleteTree(root) catch {}; try sys.fs.createDirPath(root); const initialized = try initProject(allocator, root, smg.default_limits.storage); try std.testing.expectEqualStrings(root, initialized); const store_dir = try std.fs.path.join(allocator, &.{ root, paths.smg_dir_name }); try std.testing.expect(sys.fs.exists(store_dir)); const database_path = try std.fs.path.join(allocator, &.{ store_dir, paths.database_file_name }); try std.testing.expect(sys.fs.exists(database_path)); var dir = try std.Io.Dir.openDirAbsolute(fs_io, store_dir, .{}); dir.close(fs_io);}test "linked checkout never inherits the main graph store" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); var temporary = std.testing.tmpDir(.{}); defer temporary.cleanup(); try temporary.dir.createDirPath(fs_io, "main/.git/worktrees/linked"); try temporary.dir.createDirPath(fs_io, "main/.smg"); try temporary.dir.createDirPath(fs_io, "linked/nested"); const main_git = try temporary.dir.realPathFileAlloc(fs_io, "main/.git", allocator); const linked_git = try std.fs.path.join(allocator, &.{ main_git, "worktrees", "linked" }); try temporary.dir.writeFile(fs_io, .{ .sub_path = "linked/.git", .data = try std.fmt.allocPrint(allocator, "gitdir: {s}\n", .{linked_git}), }); try temporary.dir.writeFile(fs_io, .{ .sub_path = "main/.git/worktrees/linked/commondir", .data = "../..\n", }); const nested = try temporary.dir.realPathFileAlloc(fs_io, "linked/nested", allocator); try std.testing.expectEqual(@as(?[]const u8, null), try findRootFrom(allocator, nested)); try temporary.dir.createDirPath(fs_io, "linked/.smg"); const linked = try temporary.dir.realPathFileAlloc(fs_io, "linked", allocator); try std.testing.expectEqualStrings(linked, (try findRootFrom(allocator, nested)).?);}Source: tools/smg/src/storage/root.zig:8
zig
pub const project = @import("project.zig");Audit
| Definitions | 5 |
|---|---|
| Public names | 9 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |