╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │451 inline else => |*repo| try repo.uploadPack(io, allocator, reader, writer, .{ .protocol_version = protocol_version }, &sideband), │ │452 } │ │453 } else { │ │451 - const target = (try evt.Repo.readByOwnerAndName(evt.AdminDB, evt.admin_repo_opts.hash, admin_moment, &admin_arena, owner_repo.owner, owner_repo.name)) orelse │ │454 + const target = (try evt.readRepoById(io, allocator, &admin_arena, handler.repo_root_path, fork_record.event.repo_user_id[0..evt.event_id_size], fork_record.event.repo_id)) orelse│ │455 return writeError(sess, "repo not found"); │ │453 - if (!std.mem.eql(u8, fork_record.event.repo_id, &target.event_id)) return writeError(sess, "patch draft belongs to another repo"); │ │454 - const target_id = std.fmt.bytesToHex(target.event_id, .lower); │ │456 + if (!std.mem.eql(u8, target.event.name, forker_repo.name)) return writeError(sess, "patch draft belongs to another repo"); │ │457 + const target_id = std.fmt.bytesToHex(fork_record.event.repo_id[0..evt.event_id_size].*, .lower); │ │458 const target_path = try std.fs.path.join(allocator, &.{ handler.repo_root_path, &target_id }); │ │459 defer allocator.free(target_path); │ │460 const author: evt.CommitAuthor = .{ .name = user.event.name, .email = user.event.email }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────╮ │547 io: std.Io, │ │548 arena: *std.heap.ArenaAllocator,│ │549 admin_repo_path: []const u8, │ │550 + repo_root_path: []const u8, │ │551 owner_name: []const u8, │ │552 repo_name: []const u8, │ │553 service: GitService, │ ╰─────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │561 defer admin.deinit(io, allocator); │ │562 │ │563 const moment = try evt.currentMoment(evt.admin_repo_opts, &admin); │ │560 - const repo = (try evt.Repo.readByOwnerAndName(evt.AdminDB, evt.admin_repo_opts.hash, moment, arena, owner_name, repo_name)) orelse {│ │564 + const repo = (try evt.readRepoByOwnerAndName(io, allocator, arena, moment, repo_root_path, owner_name, repo_name)) orelse { │ │565 if (service == .upload_pack) return .not_found; │ │566 const owner = (try evt.User.readByName(io, allocator, admin_repo_path, arena, owner_name)) orelse return .not_found; │ │567 return if (isKeyInAuthorizedKeys(owner.event.ssh_keys, fingerprint)) │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/test/event/admin.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │20 │ │21 const repo_opts: rp.RepoOpts(.xit) = .{ .is_test = true }; │ │22 const Repo = rp.Repo(.xit, repo_opts); │ │23 - var repo = try Repo.init(io, allocator, .{ .path = temp_path }); │ │23 + const admin_path = try std.fs.path.join(allocator, &.{ temp_path, "admin" });│ │24 + defer allocator.free(admin_path); │ │25 + var repo = try Repo.init(io, allocator, .{ .path = admin_path }); │ │26 defer repo.deinit(io, allocator); │ │27 + const user_path = try std.fs.path.join(allocator, &.{ temp_path, "user" }); │ │28 + defer allocator.free(user_path); │ │29 + var user_repo = try Repo.init(io, allocator, .{ .path = user_path }); │ │30 + defer user_repo.deinit(io, allocator); │ │31 │ │32 var arena = std.heap.ArenaAllocator.init(allocator); │ │33 defer arena.deinit(); │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │70 }, │ │71 }, │ │72 }, │ │67 - .{ │ │68 - .id = std.fmt.bytesToHex(repo_event_id, .lower), │ │69 - .author = author, │ │70 - .event = .{ │ │71 - .repo = .{ │ │72 - .user_id = &user_event_id, │ │73 - .name = "ziglings", │ │74 - .description = "Learn the Zig programming language by fixing tiny broken programs",│ │75 - }, │ │73 + }; │ │74 + const repo_event = evt.EventWithId{ │ │75 + .id = std.fmt.bytesToHex(repo_event_id, .lower), │ │76 + .author = author, │ │77 + .event = .{ │ │78 + .repo = .{ │ │79 + .user_id = &user_event_id, │ │80 + .name = "ziglings", │ │81 + .description = "Learn the Zig programming language by fixing tiny broken programs", │ │82 }, │ │83 }, │ │84 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │85 │ │80 - // commit and consume the seed events │ │86 + // commit and consume the seed events. users go in the admin repo, repos in │ │87 + // their owner's user repo. │ │88 try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &events_to_consume);│ │89 + try evt.consume(.server, .user, .xit, repo_opts, io, allocator, &user_repo, evt.events_ref, &.{repo_event});│ │90 │ │91 { │ │92 const haxy_moment = try evt.currentMoment(repo_opts, &repo); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │102 │ │103 // the password was correctly edited │ │104 try std.testing.expectEqualStrings(events_to_consume[1].event.user.?.password_hash, user_event.event.password_hash); │ │105 + } │ │106 │ │107 + { │ │108 + const haxy_moment = try evt.currentMoment(repo_opts, &user_repo); │ │109 + │ │110 // get the map of repos │ │111 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound;│ │112 const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │114 // get the repo out of the map │ │115 const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; │ │116 const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │105 - const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │117 + const repo_record = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │118 │ │107 - try std.testing.expectEqualSlices(u8, &user_event_id, repo_event.event.user_id); │ │108 - try std.testing.expectEqualStrings("ziglings", repo_event.event.name); │ │119 + try std.testing.expectEqualSlices(u8, &user_event_id, repo_record.event.user_id); │ │120 + try std.testing.expectEqualStrings("ziglings", repo_record.event.name); │ │121 │ │122 // get the repos created by the user │ │111 - const user_id_to_repo_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repo-id-set")) orelse return error.NotFound;│ │112 - const user_id_to_repo_id_set = try Repo.DB.HashMap(.read_only).init(user_id_to_repo_id_set_cursor); │ │113 - │ │114 - const user_repos_cursor = try user_id_to_repo_id_set.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; │ │123 + const user_repos_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Repo.active_id_set_key)) orelse return error.NotFound; │ │124 const user_repos = try Repo.DB.SortedSet(.read_only).init(user_repos_cursor); │ │125 │ │126 try std.testing.expectEqual(1, try user_repos.count()); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │127 │ │128 // the set is keyed by orderKeyDesc([created-order][event-id]) │ │120 - const order_key = evt.orderKeyDesc(repo_event.created_order, &repo_event_id); │ │129 + const order_key = evt.orderKeyDesc(repo_record.created_order, &repo_event_id); │ │130 try std.testing.expect(try user_repos.contains(&order_key)); │ │131 + │ │132 + // the repo resolves by its name alone │ │133 + const found = (try evt.Repo.readByName(Repo.DB, repo_opts.hash, haxy_moment, &arena, "ziglings")) orelse return error.NotFound;│ │134 + try std.testing.expectEqualSlices(u8, &repo_event_id, &found.event_id); │ │135 } │ │136 │ │137 // │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │147 }; │ │148 │ │149 // commit and consume the removal │ │137 - try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &events_to_consume2); │ │150 + try evt.consume(.server, .user, .xit, repo_opts, io, allocator, &user_repo, evt.events_ref, &events_to_consume2); │ │151 │ │152 { │ │140 - const haxy_moment = try evt.currentMoment(repo_opts, &repo); │ │153 + const haxy_moment = try evt.currentMoment(repo_opts, &user_repo); │ │154 │ │155 // get the map of repos │ │156 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯