Browse Source

Allow "edit" transforms, fix rm transforms and path matching

default_compile_flags
vector-of-bool 4 years ago
parent
commit
d1bf1aafcd
2 changed files with 139 additions and 8 deletions
  1. +119
    -4
      src/dds/util/fs_transform.cpp
  2. +20
    -4
      src/dds/util/fs_transform.hpp

+ 119
- 4
src/dds/util/fs_transform.cpp View File

@@ -85,6 +85,9 @@ dds::fs_transformation dds::fs_transformation::from_json(const json5::data& data
};
};

struct fs_transformation::edit pending_edit;
fs_transformation::one_edit pending_edit_item;

walk(data,
require_obj{"Each transform must be a JSON object"},
mapping{
@@ -115,6 +118,66 @@ dds::fs_transformation dds::fs_transformation::from_json(const json5::data& data
require_str{"'content' must be a string"},
put_into(ret.write->content)},
}},
if_key{
"edit",
require_obj{"'edit' should be a JSON object"},
prep_optional(ret.edit),
mapping{
required_key{"path",
"'path' is required",
require_str{"'path' should be a string path"},
put_into(ret.edit->path, str_to_path)},
required_key{
"edits",
"An 'edits' array is required",
require_array{"'edits' should be an array"},
for_each{
require_obj{"Each edit should be a JSON object"},
[&](auto&&) {
ret.edit->edits.emplace_back();
return walk.pass;
},
[&](auto&& dat) {
return mapping{
required_key{
"kind",
"Edit 'kind' is required",
require_str{"'kind' should be a string"},
[&](std::string s) {
auto& ed = ret.edit->edits.back();
if (s == "delete") {
ed.kind = ed.delete_;
} else if (s == "insert") {
ed.kind = ed.insert;
} else {
return walk.reject("Invalid edit kind");
}
return walk.accept;
},
},
required_key{
"line",
"Edit 'line' number is required",
require_type<double>{"'line' should be an integer"},
[&](double d) {
ret.edit->edits.back().line = int(d);
return walk.accept;
},
},
if_key{
"content",
require_str{"'content' should be a string"},
[&](std::string s) {
ret.edit->edits.back().content = s;
return walk.accept;
},
},
}(dat);
},
},
},
},
},
});

return ret;
@@ -224,7 +287,8 @@ void do_remove(const struct fs_transformation::remove& oper, path_ref root) {
if (child.is_directory()) {
continue;
}
if (!oper.only_matching.empty() && !matches_any(child, oper.only_matching)) {
auto relpath = child.path().lexically_proximate(from);
if (!oper.only_matching.empty() && !matches_any(relpath, oper.only_matching)) {
continue;
}
fs::remove_all(child);
@@ -244,12 +308,36 @@ void do_write(const struct fs_transformation::write& oper, path_ref root) {
root.string());
}

std::cout << "Write content: " << oper.content;

auto of = dds::open(dest, std::ios::binary | std::ios::out);
of << oper.content;
}

void do_edit(path_ref filepath, const fs_transformation::one_edit& edit) {
auto file = open(filepath, std::ios::in | std::ios::binary);
file.exceptions(std::ios::badbit);
std::string lines;
std::string line;
int line_n = 1;
for (; std::getline(file, line, '\n'); ++line_n) {
if (line_n != edit.line) {
lines += line + "\n";
continue;
}
switch (edit.kind) {
case edit.delete_:
// Just delete the line. Ignore it.
continue;
case edit.insert:
// Insert some new content
lines += edit.content + "\n";
lines += line + "\n";
continue;
}
}
file = open(filepath, std::ios::out | std::ios::binary);
file << lines;
}

} // namespace

void dds::fs_transformation::apply_to(dds::path_ref root_) const {
@@ -266,6 +354,19 @@ void dds::fs_transformation::apply_to(dds::path_ref root_) const {
if (write) {
do_write(*write, root);
}
if (edit) {
auto fpath = root / edit->path;
if (!parent_dir_of(root, fpath)) {
throw_external_error<errc::invalid_repo_transform>(
"Filesystem transformation wants to edit a file outside of the root. Attempted to "
"modify [{}]. Writing is restricted to [{}].",
fpath.string(),
root.string());
}
for (auto&& ed : edit->edits) {
do_edit(fpath, ed);
}
}
}

namespace {
@@ -315,7 +416,7 @@ std::string fs_transformation::as_json() const noexcept {
for (auto&& gl : remove->only_matching) {
if_arr.push_back(gl.string());
}
rm["only-matching"] = rm;
rm["only-matching"] = if_arr;
}
obj["remove"] = rm;
}
@@ -325,6 +426,20 @@ std::string fs_transformation::as_json() const noexcept {
wr["content"] = write->content;
obj["write"] = wr;
}
if (edit) {
auto ed = nlohmann::json::object();
ed["path"] = edit->path.string();
auto edits = nlohmann::json::array();
for (auto&& one : edit->edits) {
auto one_ed = nlohmann::json::object();
one_ed["kind"] = one.kind == one.delete_ ? "delete" : "insert";
one_ed["line"] = one.line;
one_ed["content"] = one.content;
edits.push_back(std::move(one_ed));
}
ed["edits"] = edits;
obj["edit"] = ed;
}

return to_string(obj);
}

+ 20
- 4
src/dds/util/fs_transform.hpp View File

@@ -34,10 +34,26 @@ struct fs_transformation {
std::string content;
};

std::optional<struct copy> copy;
std::optional<struct move> move;
std::optional<remove> remove;
std::optional<struct write> write;
struct one_edit {
int line = 0;
std::string content;
enum kind_t {
delete_,
insert,
} kind
= delete_;
};

struct edit {
fs::path path;
std::vector<one_edit> edits;
};

std::optional<struct copy> copy;
std::optional<struct move> move;
std::optional<struct remove> remove;
std::optional<struct write> write;
std::optional<struct edit> edit;

void apply_to(path_ref root) const;


Loading…
Cancel
Save