╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │203 pub const empty: Window = .{ .items = &.{}, .prev_id = null, .next_id = null, .count = 0 };│ │204 }; │ │205 │ │206 -// "owner/name", so the view can build /repo/owner/name/patches/... links. │ │206 +// "owner:name", so the view can build /owner:name/patches/... links. │ │207 identity: []const u8, │ │208 default_target_branch: []const u8 = "", │ │209 // the url-encoded label the lists are filtered to ("" = unfiltered). │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │263 // a fork route's identity names the forker and the target repo │ │264 fn forkIdentity(buffer: []u8, identity: []const u8, entry: PatchWithId) ![]const u8 { │ │265 const repo_identity = ui.RoutablePage.RepoIdentity.parse(identity) orelse return error.RouteTooLong; │ │266 - return std.fmt.bufPrint(buffer, "{s}/{s}", .{ entry.forker, repo_identity.name }) catch error.RouteTooLong;│ │266 + return std.fmt.bufPrint(buffer, "{s}:{s}", .{ entry.forker, repo_identity.name }) catch error.RouteTooLong;│ │267 } │ │268 │ │269 pub fn commitsRoute(identity: []const u8, entry: PatchWithId) !?ui.RoutablePage { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │945 const target_branch = entry.record.event.target_branch; │ │946 │ │947 if (status_kind != .merged and entry.fork_exists) if (session.data.git_ssh_port) |port| { │ │948 - const url = try std.fmt.allocPrint(aa, "ssh://localhost:{d}/fork/{s}/patch:{s}", .{ port, self.identity, entry.id }); │ │948 + var buffer: [ui.RoutablePage.repo_identity_max_len]u8 = undefined; │ │949 + const url = try std.fmt.allocPrint(aa, "ssh://localhost:{d}/{s}+{s}", .{ port, try forkIdentity(&buffer, self.identity, entry), entry.id });│ │950 const push_command = try std.fmt.allocPrint(aa, "git push {s} HEAD:patch", .{url}); │ │950 - const clone_name = try cloneDirectoryName(aa, entry.record.event.title); │ │951 - const clone_command = if (clone_name.len == 0) │ │952 - try std.fmt.allocPrint(aa, "git clone {s}", .{url}) │ │953 - else │ │954 - try std.fmt.allocPrint(aa, "git clone {s} {s}", .{ url, clone_name }); │ │951 + const clone_command = try std.fmt.allocPrint(aa, "git clone {s}", .{url}); │ │952 const merge_command = try std.fmt.allocPrint(aa, "git fetch '{s}' refs/heads/patch && git merge FETCH_HEAD", .{url}); │ │953 const choices: [3]ui.widget.CopyableText.Choice = .{ │ │954 .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 996 errdefer copyable_text.deinit(allocator); │ │ 997 try box.children.put(allocator, copyable_text.getFocus().id, .{ .widget = .{ .copyable_text = copyable_text }, .rect = null, .min_size = null });│ │ 998 } │ │1002 - │ │1003 -fn cloneDirectoryName(allocator: std.mem.Allocator, title: []const u8) ![]const u8 { │ │1004 - var name: [64]u8 = undefined; │ │1005 - var len: usize = 0; │ │1006 - var pending: ?u8 = null; │ │ 999 │ │1008 - for (title) |char| { │ │1009 - if (std.ascii.isAlphanumeric(char)) { │ │1010 - const needed: usize = if (pending == null) 1 else 2; │ │1011 - if (len + needed > name.len) break; │ │1012 - if (pending) |value| { │ │1013 - name[len] = value; │ │1014 - len += 1; │ │1015 - } │ │1016 - name[len] = std.ascii.toLower(char); │ │1017 - len += 1; │ │1018 - pending = null; │ │1019 - } else if (char == ' ') { │ │1020 - if (len != 0) pending = '-'; │ │1021 - } else if (char == '.') { │ │1022 - if (len != 0 and pending != '-') pending = '.'; │ │1023 - } │ │1024 - } │ │1025 - if (len == 0) return ""; │ │1026 - return allocator.dupe(u8, name[0..len]); │ │1027 -} │ │1028 - │ │1000 // tabs switching between the patches page's views │ │1001 pub fn initHeader(allocator: std.mem.Allocator, session: *ui.Session, data: *const Self) !Header { │ │1002 var header = try Header.init(allocator, session, data.search); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯