╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭───────────────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
78 } 79 }, 80 } 81 } 82 return try list.toOwnedSlice(aa); 83 } 84 85 // join the chunks back into one document. `resolutions` holds the final text 86 // of each conflict chunk in order; an empty resolution drops the hunk's lines. 87 pub fn assemble( 88 allocator: std.mem.Allocator, 89 chunk_list: []const Chunk, 90 resolutions: []const []const u8, 91 ) ![]u8 { 92 var out: std.ArrayList(u8) = .empty; 93 errdefer out.deinit(allocator); 94 var resolution_index: usize = 0; 95 for (chunk_list) |chunk| { 96 const piece: ?[]const u8 = switch (chunk) { 97 .same => |text| text, 98 .auto => |auto| auto.text, 99 .conflict => blk: { 100 const resolution = resolutions[resolution_index]; 101 resolution_index += 1; 102 break :blk if (resolution.len > 0) resolution else null; 103 }, 104 }; 105 if (piece) |text| { 106 if (out.items.len > 0) try out.append(allocator, '\n'); 107 try out.appendSlice(allocator, text); 108 } 109 } 110 return try out.toOwnedSlice(allocator); 111 } 112 113 // a range's lines joined with newlines, or null when it spans no lines 114 fn joinRange( 115 aa: std.mem.Allocator, 116 iter: *LineIterator, 117 range_maybe: ?df.Diff3Iterator(repo_kind, repo_opts).Range, 118 ) !?[]const u8 { 119 const range = range_maybe orelse return null; 120 if (range.end <= range.begin) return null; 121 var out: std.ArrayList(u8) = .empty; 122 for (range.begin..range.end) |line_num| { 123 // buffer-backed lines are borrowed, so no free is needed 124 const line = try iter.get(line_num); 125 if (line_num > range.begin) try out.append(aa, '\n'); 126 try out.appendSlice(aa, line); 127 } 128 return try out.toOwnedSlice(aa); 129 } 130 131 fn textEqual(a: ?[]const u8, b: ?[]const u8) bool { 132 const a_text = a orelse return b == null; 133 const b_text = b orelse return false; 134 return std.mem.eql(u8, a_text, b_text); 135 } 136