2020-09-12 20:38:55 +03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
2023-06-24 17:33:04 +12:00
|
|
|
* Copyright (c) 2023, Shannon Booth <shannon.ml.booth@gmail.com>
|
2020-09-12 20:38:55 +03:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-09-12 20:38:55 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "Hunks.h"
|
2021-01-15 21:46:23 +01:00
|
|
|
#include <AK/Debug.h>
|
2020-09-12 20:38:55 +03:00
|
|
|
|
|
|
|
|
namespace Diff {
|
2023-06-24 12:44:22 +12:00
|
|
|
|
2023-06-24 13:13:50 +12:00
|
|
|
ErrorOr<Vector<Hunk>> parse_hunks(StringView diff)
|
2020-09-12 20:38:55 +03:00
|
|
|
{
|
2023-06-24 13:13:50 +12:00
|
|
|
Vector<StringView> diff_lines = diff.split_view('\n');
|
2020-09-12 20:38:55 +03:00
|
|
|
if (diff_lines.is_empty())
|
2023-06-24 12:44:22 +12:00
|
|
|
return Vector<Hunk> {};
|
2020-09-12 20:38:55 +03:00
|
|
|
|
|
|
|
|
Vector<Hunk> hunks;
|
|
|
|
|
|
|
|
|
|
size_t line_index = 0;
|
|
|
|
|
HunkLocation current_location {};
|
|
|
|
|
|
|
|
|
|
// Skip to first hunk
|
|
|
|
|
while (diff_lines[line_index][0] != '@') {
|
|
|
|
|
++line_index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (line_index < diff_lines.size()) {
|
|
|
|
|
if (diff_lines[line_index][0] == '@') {
|
|
|
|
|
current_location = parse_hunk_location(diff_lines[line_index]);
|
|
|
|
|
++line_index;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2023-06-24 17:33:04 +12:00
|
|
|
|
2020-09-12 20:38:55 +03:00
|
|
|
Hunk hunk {};
|
2023-06-24 17:33:04 +12:00
|
|
|
hunk.location = current_location;
|
2020-09-12 20:38:55 +03:00
|
|
|
|
2023-06-24 17:33:04 +12:00
|
|
|
while (line_index < diff_lines.size()) {
|
|
|
|
|
auto const& line = diff_lines[line_index];
|
|
|
|
|
|
|
|
|
|
char const operation = line[0];
|
|
|
|
|
if (operation != ' ' && operation != '+' && operation != '-')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
auto const content = line.substring_view(1, line.length() - 1);
|
|
|
|
|
|
|
|
|
|
TRY(hunk.lines.try_append(Line { Line::operation_from_symbol(operation), TRY(String::from_utf8(content)) }));
|
2020-09-12 20:38:55 +03:00
|
|
|
|
|
|
|
|
++line_index;
|
|
|
|
|
}
|
2023-06-24 12:44:22 +12:00
|
|
|
TRY(hunks.try_append(hunk));
|
2020-09-12 20:38:55 +03:00
|
|
|
}
|
|
|
|
|
|
2021-01-23 23:59:27 +01:00
|
|
|
if constexpr (HUNKS_DEBUG) {
|
2022-04-01 20:58:27 +03:00
|
|
|
for (auto const& hunk : hunks) {
|
2023-06-24 17:33:04 +12:00
|
|
|
dbgln("{}", hunk.location);
|
|
|
|
|
for (auto const& line : hunk.lines)
|
|
|
|
|
dbgln("{}", line);
|
2020-09-12 20:38:55 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hunks;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 12:40:15 +12:00
|
|
|
HunkLocation parse_hunk_location(StringView location_line)
|
2020-09-12 20:38:55 +03:00
|
|
|
{
|
|
|
|
|
size_t char_index = 0;
|
2023-06-24 12:40:15 +12:00
|
|
|
auto parse_start_and_length_pair = [](StringView raw) {
|
2023-06-24 17:33:04 +12:00
|
|
|
auto maybe_index_of_separator = raw.find(',');
|
|
|
|
|
|
|
|
|
|
size_t start = 0;
|
|
|
|
|
size_t length = 0;
|
|
|
|
|
if (maybe_index_of_separator.has_value()) {
|
|
|
|
|
auto index_of_separator = maybe_index_of_separator.value();
|
|
|
|
|
start = raw.substring_view(0, index_of_separator).to_uint().value();
|
|
|
|
|
length = raw.substring_view(index_of_separator + 1, raw.length() - index_of_separator - 1).to_uint().value();
|
|
|
|
|
} else {
|
|
|
|
|
length = 1;
|
|
|
|
|
start = raw.to_uint().value();
|
|
|
|
|
}
|
2021-12-30 16:41:29 +00:00
|
|
|
|
2023-06-24 17:33:04 +12:00
|
|
|
return Range { start, length };
|
2020-09-12 20:38:55 +03:00
|
|
|
};
|
|
|
|
|
while (char_index < location_line.length() && location_line[char_index++] != '-') {
|
|
|
|
|
}
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(char_index < location_line.length());
|
2020-09-12 20:38:55 +03:00
|
|
|
|
|
|
|
|
size_t original_location_start_index = char_index;
|
|
|
|
|
|
|
|
|
|
while (char_index < location_line.length() && location_line[char_index++] != ' ') {
|
|
|
|
|
}
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(char_index < location_line.length() && location_line[char_index] == '+');
|
2020-09-12 20:38:55 +03:00
|
|
|
size_t original_location_end_index = char_index - 2;
|
|
|
|
|
|
|
|
|
|
size_t target_location_start_index = char_index + 1;
|
|
|
|
|
|
|
|
|
|
char_index += 1;
|
|
|
|
|
while (char_index < location_line.length() && location_line[char_index++] != ' ') {
|
|
|
|
|
}
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(char_index < location_line.length());
|
2020-09-12 20:38:55 +03:00
|
|
|
|
|
|
|
|
size_t target_location_end_index = char_index - 2;
|
|
|
|
|
|
2023-06-24 17:33:04 +12:00
|
|
|
auto old_range = parse_start_and_length_pair(location_line.substring_view(original_location_start_index, original_location_end_index - original_location_start_index + 1));
|
|
|
|
|
auto new_range = parse_start_and_length_pair(location_line.substring_view(target_location_start_index, target_location_end_index - target_location_start_index + 1));
|
|
|
|
|
return { old_range, new_range };
|
2020-09-12 20:38:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|