╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │70 if (!gop.found_existing) gop.value_ptr.* = is_dir else if (is_dir) gop.value_ptr.* = true; │ │71 } │ │72 │ │73 - // sort directories first, then alphabetically, and dupe into the page arena. │ │74 - const Pair = struct { name: []const u8, is_dir: bool }; │ │75 - var pairs = try gpa.alloc(Pair, children.count()); │ │76 - defer gpa.free(pairs); │ │77 - for (children.keys(), children.values(), 0..) |name, is_dir, i| pairs[i] = .{ .name = name, .is_dir = is_dir };│ │78 - std.mem.sort(Pair, pairs, {}, struct { │ │79 - fn lessThan(_: void, a: Pair, b: Pair) bool { │ │80 - if (a.is_dir != b.is_dir) return a.is_dir; │ │81 - return std.mem.lessThan(u8, a.name, b.name); │ │73 + // committed paths come out sorted (tree objects are written in sorted │ │74 + // order), so the deduped children are already in name order. just group │ │75 + // directories before files, keeping that order within each group, and dupe │ │76 + // into the page arena. │ │77 + const entries = try aa.alloc(Entry, children.count()); │ │78 + var i: usize = 0; │ │79 + for ([_]bool{ true, false }) |want_dir| { │ │80 + for (children.keys(), children.values()) |name, is_dir| { │ │81 + if (is_dir == want_dir) { │ │82 + entries[i] = .{ .name = try aa.dupe(u8, name), .is_dir = is_dir }; │ │83 + i += 1; │ │84 + } │ │85 } │ │83 - }.lessThan); │ │84 - │ │85 - const entries = try aa.alloc(Entry, pairs.len); │ │86 - for (pairs, 0..) |pair, i| entries[i] = .{ .name = try aa.dupe(u8, pair.name), .is_dir = pair.is_dir }; │ │86 + } │ │87 │ │88 return .{ .identity = empty.identity, .dir = empty.dir, .entries = entries }; │ │89 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯