Skip to content

Commit fa11efd

Browse files
committed
citnames: output writing is an atomic operation
1 parent b8b46fa commit fa11efd

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

source/citnames/source/Citnames.cc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ namespace {
9494
return fs::exists(path, error_code);
9595
}
9696

97+
bool rename_file(const fs::path &from, const fs::path &to) {
98+
std::error_code error_code;
99+
fs::rename(from, to, error_code);
100+
return error_code.value() == 0;
101+
}
102+
97103
rust::Result<cs::Arguments> into_arguments(const flags::Arguments &args) {
98104
auto input = args.as_string(cmd::citnames::FLAG_INPUT);
99105
auto output = args.as_string(cmd::citnames::FLAG_OUTPUT);
@@ -199,7 +205,7 @@ namespace cs {
199205
spdlog::debug("compilation entries created. [size: {}]", new_entries_count);
200206
// read back the current content and extend with the new elements.
201207
return (arguments_.append)
202-
? output.from_json(arguments_.output.c_str(), entries)
208+
? output.from_json(arguments_.output, entries)
203209
.template map<size_t>([&new_entries_count](auto old_entries_count) {
204210
spdlog::debug("compilation entries have read. [size: {}]", old_entries_count);
205211
return new_entries_count + old_entries_count;
@@ -209,7 +215,12 @@ namespace cs {
209215
.and_then<size_t>([this, &output, &entries](const size_t & size) {
210216
// write the entries into the output file.
211217
spdlog::debug("compilation entries to output. [size: {}]", size);
212-
return output.to_json(arguments_.output.c_str(), entries);
218+
219+
const fs::path temporary_file(arguments_.output.string() + ".tmp");
220+
auto result = output.to_json(temporary_file, entries);
221+
return rename_file(temporary_file, arguments_.output)
222+
? result
223+
: rust::Err(std::runtime_error(fmt::format("Failed to rename file: {}", arguments_.output)));
213224
})
214225
.map<int>([](auto size) {
215226
// just map to success exit code if it was successful.

0 commit comments

Comments
 (0)