╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Discussion.zig ───────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
152 title: []const u8, 153 tags: []const u8, 154 description: []const u8, 155 author: evt.CommitAuthor, 156 ) !void { 157 if (!fieldsValid(title, tags)) return error.InvalidFields; 158 159 var arena = std.heap.ArenaAllocator.init(allocator); 160 defer arena.deinit(); 161 const discussion = (try readById(repo_kind, repo_opts, io, allocator, &arena, repo, id)) orelse return error.NotFound; 162 if (discussion.removed) return error.NotFound; 163 164 try evt.consume(host_kind, .repo, repo_kind, repo_opts, io, allocator, repo, evt.events_ref, &.{.{ 165 .id = std.fmt.bytesToHex(id.*, .lower), 166 .timestamp = @intCast(std.Io.Timestamp.now(io, .real).toSeconds()), 167 .author = author, 168 .event = .{ .discuss = .{ 169 .title = title, 170 .tags = tags, 171 .description = description, 172 } }, 173 }}); 174 } 175 176 fn removeFromTagSets(comptime DB: type, tags: DB.SortedMap(.read_write), names: []const u8, order_key: []const u8) !void { 177 var tag_iter = tagIterator(names); 178 while (tag_iter.next()) |tag| { 179 if (tag.len == 0 or tag.len > tag_max_len) continue; 180 const cursor = try tags.putCursor(tag); 181 const set = try DB.SortedSet(.read_write).init(cursor); 182 _ = try set.remove(order_key); 183 if (0 == try set.count()) _ = try tags.remove(tag); 184 } 185 } 186 187 fn addToTagSets(comptime DB: type, tags: DB.SortedMap(.read_write), names: []const u8, order_key: []const u8) !void { 188 var tag_iter = tagIterator(names); 189 while (tag_iter.next()) |tag| { 190 if (tag.len == 0 or tag.len > tag_max_len) continue; 191 const set = try DB.SortedSet(.read_write).init(try tags.putCursor(tag)); 192 try set.put(order_key); 193 } 194 } 195 196 pub fn readById( 197 comptime repo_kind: rp.RepoKind, 198 comptime repo_opts: rp.RepoOpts(repo_kind), 199 io: std.Io, 200 allocator: std.mem.Allocator, 201 arena: *std.heap.ArenaAllocator, 202 repo: *rp.Repo(repo_kind, repo_opts), 203 id: *const [evt.event_id_size]u8, 204 ) !?Record { 205 const DB = evt.EventDB(repo_opts.hash); 206 var event_db_maybe: ?evt.LocalEventDB(repo_opts.hash) = if (repo_kind == .git) try evt.LocalEventDB(repo_opts.hash).openReadOnly(io, allocator, repo.core.repo_dir) else null; 207 defer if (event_db_maybe) |*event_db| event_db.deinit(io, allocator); 208 const moment = (if (event_db_maybe) |*event_db| 209 evt.currentMomentFromDb(repo_opts.hash, event_db.db) 210 else if (repo_kind == .git) 211 return null 212 else 213 evt.currentMoment(repo_opts, repo)) catch return null; 214 const records_cursor = try moment.getCursor(hash.hashInt(repo_opts.hash, record_map_key)) orelse return null; 215 const records = try DB.HashMap(.read_only).init(records_cursor); 216 const record_cursor = try records.getCursor(hash.hashInt(repo_opts.hash, id)) orelse return null; 217 return try evt.read(Record, DB, repo_opts.hash, arena, try DB.HashMap(.read_only).init(record_cursor)); 218 } 219