╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────╮ │4 const xit = @import("xit"); │ │5 const rp = xit.repo; │ │6 const tr = xit.tree; │ │7 -const rf = xit.ref; │ │8 -const hash = xit.hash; │ │7 const xitui = xit.xitui; │ │8 const wgt = xitui.widget; │ │9 const layout = xitui.layout;│ ╰───────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │12 const Focus = xitui.focus.Focus; │ │13 │ │14 const RefOrOid = ui.RoutablePage.RefOrOid; │ │17 -// the hex-oid length for the default repo options the on-disk repos use.│ │18 -const hex_len = hash.hexLen((rp.RepoOpts(.xit){}).hash); │ │15 │ │16 // one entry in the directory currently being viewed. │ │17 pub const Entry = struct { │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │58 const gpa = arena.child_allocator; │ │59 var repo = rp.Repo(.xit, .{}).open(io, gpa, .{ .path = repo_path }) catch return emptyResult(aa, identity, requested_ref_or_oid orelse .branch, requested_value, dir);│ │60 defer repo.deinit(io, gpa); │ │65 - │ │66 - // resolve the effective ref: the one named in the route, else HEAD's branch. │ │67 - // the value is duped immediately so it outlives the stack buffer head() fills. │ │68 - var resolved_ref_or_oid: RefOrOid = requested_ref_or_oid orelse .branch; │ │69 - var resolved_value: []const u8 = requested_value; │ │70 - if (requested_ref_or_oid == null) { │ │71 - var head_buf: [rf.MAX_REF_CONTENT_SIZE]u8 = undefined; │ │72 - if (repo.head(io, &head_buf)) |head| switch (head) { │ │73 - .ref => |ref| { │ │74 - resolved_ref_or_oid = .branch; │ │75 - resolved_value = try aa.dupe(u8, ref.name); │ │76 - }, │ │77 - .oid => |oid| { │ │78 - resolved_ref_or_oid = .object; │ │79 - resolved_value = try aa.dupe(u8, oid); │ │80 - }, │ │81 - } else |_| {} │ │82 - } │ │61 │ │84 - // resolve the ref to the commit oid whose tree we list. a ref the route │ │85 - // named explicitly that doesn't resolve is a bad url (NotFound -> 404); the │ │86 - // default-branch path instead falls through to an empty listing below. │ │87 - const explicit = requested_ref_or_oid != null; │ │88 - var oid: [hex_len]u8 = undefined; │ │89 - switch (resolved_ref_or_oid) { │ │90 - .object => { │ │91 - if (resolved_value.len != hex_len) return unresolved(aa, identity, explicit, resolved_ref_or_oid, resolved_value, dir); │ │92 - @memcpy(&oid, resolved_value); │ │93 - }, │ │94 - .branch, .tag => { │ │95 - const ref_kind: rf.RefKind = if (resolved_ref_or_oid == .branch) .head else .tag; │ │96 - oid = (repo.readRef(io, .{ .kind = ref_kind, .name = resolved_value }) catch null) orelse │ │97 - return unresolved(aa, identity, explicit, resolved_ref_or_oid, resolved_value, dir); │ │98 - }, │ │99 - } │ │62 + // resolve the requested ref (or the default branch) to the commit oid whose │ │63 + // tree we list. a ref the route named explicitly that doesn't resolve is a │ │64 + // bad url (NotFound -> 404); the default-branch path falls through to empty. │ │65 + const resolved = (try ui.ResolvedRefOrOid.init(&repo, io, aa, requested_ref_or_oid, requested_value)) orelse { │ │66 + if (requested_ref_or_oid != null) return error.NotFound; │ │67 + return emptyResult(aa, identity, .branch, requested_value, dir); │ │68 + }; │ │69 │ │70 // read the tree at that commit. building the read-only state mirrors what │ │71 // repo.status does internally, but for an arbitrary commit rather than HEAD. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │103 - var moment = repo.core.latestMoment() catch return emptyResult(aa, identity, resolved_ref_or_oid, resolved_value, dir); │ │ 72 + var moment = repo.core.latestMoment() catch return emptyResult(aa, identity, resolved.ref_or_oid, resolved.value, dir); │ │ 73 const state = rp.Repo(.xit, .{}).State(.read_only){ .core = &repo.core, .extra = .{ .moment = &moment } }; │ │105 - var tree = tr.Tree(.xit, .{}).init(state, io, gpa, &oid) catch return emptyResult(aa, identity, resolved_ref_or_oid, resolved_value, dir); │ │ 74 + var tree = tr.Tree(.xit, .{}).init(state, io, gpa, &resolved.oid) catch return emptyResult(aa, identity, resolved.ref_or_oid, resolved.value, dir);│ │ 75 defer tree.deinit(); │ │ 76 │ │ 77 // collect the immediate children of `dir`. each committed path is a full │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────╮ │113 │ │114 return .{ │ │115 .identity = try aa.dupe(u8, identity), │ │147 - .ref_or_oid = resolved_ref_or_oid, │ │148 - .ref_or_oid_value = try aa.dupe(u8, resolved_value),│ │116 + .ref_or_oid = resolved.ref_or_oid, │ │117 + .ref_or_oid_value = resolved.value, │ │118 .dir = try aa.dupe(u8, dir), │ │119 .entries = entries, │ │120 }; │ ╰─────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │121 } │ │122 │ │154 -// a ref that didn't resolve: a 404 when the route named it explicitly, else an │ │155 -// empty listing (e.g. resolving an empty repo's default branch). │ │156 -fn unresolved(aa: std.mem.Allocator, identity: []const u8, explicit: bool, ref_or_oid: RefOrOid, ref_or_oid_value: []const u8, dir: []const u8) !Self {│ │157 - if (explicit) return error.NotFound; │ │158 - return emptyResult(aa, identity, ref_or_oid, ref_or_oid_value, dir); │ │159 -} │ │160 - │ │123 // an empty listing pinned to a ref, for the wasm / no-repo / unresolved paths. │ │124 fn emptyResult(aa: std.mem.Allocator, identity: []const u8, ref_or_oid: RefOrOid, ref_or_oid_value: []const u8, dir: []const u8) !Self { │ │125 return .{ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯