╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ find.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
285 } else if (indexedOid(repo_opts.hash, tree_entry)) |bytes| { 286 try fileKey(allocator, key, path); 287 try files.put(key.items, .{ .bytes = bytes }); 288 progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); 289 } 290 } 291 } 292 293 // the tip an index entry covers, read from its key slot as hex. 294 fn readOid( 295 comptime repo_opts: rp.RepoOpts(.xit), 296 key_cursor: rp.Repo(.xit, repo_opts).DB.Cursor(.read_only), 297 ) ![hash.hexLen(repo_opts.hash)]u8 { 298 var oid: [hash.byteLen(repo_opts.hash)]u8 = undefined; 299 if ((try key_cursor.readBytes(&oid)).len != oid.len) return error.InvalidFileIndex; 300 return std.fmt.bytesToHex(oid, .lower); 301 } 302 303 // build a file's key: its lowercased basename, a separator, then its full path. 304 fn fileKey(allocator: std.mem.Allocator, key: *std.ArrayList(u8), path: []const u8) !void { 305 const slash = std.mem.lastIndexOfScalar(u8, path, '/'); 306 const base = if (slash) |i| path[i + 1 ..] else path; 307 key.clearRetainingCapacity(); 308 try key.ensureTotalCapacity(allocator, base.len + 1 + path.len); 309 for (base) |char| key.appendAssumeCapacity(std.ascii.toLower(char)); 310 key.appendAssumeCapacity(0); 311 key.appendSliceAssumeCapacity(path); 312 } 313 314 // the blob oid a tree entry is indexed under, or null for a submodule: its oid 315 // is a commit in another repo, not a file here. 316 fn indexedOid(comptime hash_kind: hash.HashKind, tree_entry: *const tr.TreeEntry(hash_kind)) ?[]const u8 { 317 if (tree_entry.mode.content.object_type == .gitlink) return null; 318 return &tree_entry.oid; 319 } 320 321 fn parseOid(comptime hash_kind: hash.HashKind, value: []const u8) ![hash.byteLen(hash_kind)]u8 { 322 const len = comptime hash.byteLen(hash_kind); 323 if (value.len != len) return error.InvalidFileIndex; 324 return value[0..len].*; 325 } 326