╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭───────────────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
321 defer progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); 322 323 var object = try obj.Object(.xit, repo_opts).init(state, io, allocator, entry.key_ptr); 324 defer object.deinit(); 325 const key = try readPosting(repo_opts, allocator, &message, &object); 326 const removed = flags == Ancestry.one; 327 try srch.replace(DB, version, allocator, &key, if (removed) message.items else "", if (removed) "" else message.items); 328 } 329 progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); 330 } 331 332 // index every commit `tip` reaches into an empty `version`, as the walk 333 // reaches it. 334 // TODO: the walk holds every visited oid in memory. if that proves too costly 335 // for large repositories, consider indexing first-parent history only, which 336 // needs no visited set and matches the commits list. 337 fn indexHistory( 338 comptime repo_opts: rp.RepoOpts(.xit), 339 state: rp.Repo(.xit, repo_opts).State(.read_only), 340 io: std.Io, 341 allocator: std.mem.Allocator, 342 version: rp.Repo(.xit, repo_opts).DB.SortedMap(.read_write), 343 tip: *const [hash.hexLen(repo_opts.hash)]u8, 344 progress_ctx_maybe: ?repo_opts.ProgressCtx, 345 ) !void { 346 const DB = rp.Repo(.xit, repo_opts).DB; 347 348 var message: std.ArrayList(u8) = .empty; 349 defer message.deinit(allocator); 350 351 // a whole history has no count until it is walked, so it reports the 352 // commits indexed so far 353 progress.report(repo_opts, io, progress_ctx_maybe, .{ .text = "Indexing commits" }); 354 progress.report(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = 0 } }); 355 var iter = try obj.ObjectIterator(.xit, repo_opts).init(state, io, allocator, .{ .kind = .commit }); 356 defer iter.deinit(); 357 try iter.include(tip); 358 while (try iter.next(allocator)) |object| { 359 defer object.deinit(); 360 if (progress.cancelled(repo_opts, progress_ctx_maybe)) return error.ClientGone; 361 const key = try readPosting(repo_opts, allocator, &message, object); 362 try srch.replace(DB, version, allocator, &key, "", message.items); 363 progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); 364 } 365 progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); 366 } 367 368 // replace `message` with the indexed prefix of `object`'s message and return 369 // the doc key it indexes under 370 fn readPosting( 371 comptime repo_opts: rp.RepoOpts(.xit), 372 allocator: std.mem.Allocator, 373 message: *std.ArrayList(u8), 374 object: *obj.Object(.xit, repo_opts), 375 ) ![docKeyLen(repo_opts.hash)]u8 { 376 message.clearRetainingCapacity(); 377 object.readMessage(allocator, message, .limited(srch.max_indexed_bytes)) catch |err| switch (err) { 378 // only the indexed prefix matters 379 error.StreamTooLong => {}, 380 else => |e| return e, 381 }; 382 return docKey(repo_opts.hash, object.content.commit.metadata.timestamp, &object.oid); 383 } 384