1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

patch+LibDiff: Implement 'strip' of filenames when parsing patch

Implement the patch '-p' / '--strip' option, which strips the given
number of leading components from filenames parsed in the patch header.
If not given this option defaults to the basename of that path.
This commit is contained in:
Shannon Booth 2023-07-14 12:07:00 +12:00 committed by Andrew Kaster
parent 87e2b8e343
commit 81df0278b1
4 changed files with 80 additions and 5 deletions

View file

@ -7,6 +7,7 @@
#include "Hunks.h"
#include <AK/Debug.h>
#include <AK/LexicalPath.h>
namespace Diff {
@ -57,19 +58,48 @@ bool Parser::consume_line_number(size_t& number)
return true;
}
ErrorOr<Header> Parser::parse_header()
ErrorOr<String> Parser::parse_file_line(Optional<size_t> const& strip_count)
{
// FIXME: handle parsing timestamps as well.
auto path = consume_line();
// No strip count given. Default to basename of file.
if (!strip_count.has_value())
return String::from_deprecated_string(LexicalPath::basename(path));
// NOTE: We cannot use LexicalPath::parts as we want to strip the non-canonicalized path.
auto const& parts = path.split_view('/');
// More components to strip than the filename has. Just pretend it is missing.
if (strip_count.value() >= parts.size())
return String();
// Remove given number of leading components from the path.
size_t components = parts.size() - strip_count.value();
StringBuilder stripped_path;
for (size_t i = parts.size() - components; i < parts.size(); ++i) {
TRY(stripped_path.try_append(parts[i]));
if (i != parts.size() - 1)
TRY(stripped_path.try_append("/"sv));
}
return stripped_path.to_string();
}
ErrorOr<Header> Parser::parse_header(Optional<size_t> const& strip_count)
{
Header header;
while (!is_eof()) {
if (consume_specific("+++ ")) {
header.new_file_path = TRY(String::from_utf8(consume_line()));
header.new_file_path = TRY(parse_file_line(strip_count));
continue;
}
if (consume_specific("--- ")) {
header.old_file_path = TRY(String::from_utf8(consume_line()));
header.old_file_path = TRY(parse_file_line(strip_count));
continue;
}