5#include <c++utilities/conversion/stringbuilder.h>
6#include <c++utilities/conversion/stringconversion.h>
27namespace BackupHelper {
48 const std::string &originalPath,
const std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream)
51 originalStream.exceptions(ios_base::goodbit);
52 backupStream.exceptions(ios_base::goodbit);
53 originalStream.close();
55 originalStream.clear();
59 originalStream.exceptions(ios_base::badbit | ios_base::failbit);
60 backupStream.exceptions(ios_base::badbit | ios_base::failbit);
65 auto ec = std::error_code();
66 if (!std::filesystem::exists(backupPathForOpen, ec) && !ec) {
67 throw std::ios_base::failure(
"Backup/temporary file has not been created.");
71 std::filesystem::remove(originalPath, ec);
73 throw std::ios_base::failure(
"Unable to remove original file: " + ec.message());
75 std::filesystem::rename(backupPathForOpen, originalPathForOpen, ec);
78 std::filesystem::copy_file(backupPathForOpen, originalPathForOpen, ec);
81 throw std::ios_base::failure(
"Unable to restore original file from backup file \"" % backupPath %
"\" after failure: " + ec.message());
110void createBackupFile(
const std::string &backupDir,
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream,
111 NativeFileStream &backupStream)
114 const auto backupDirRelative = std::filesystem::path(backupDir).is_relative();
118 auto ec = std::error_code();
119 for (
unsigned int i = 0;; ++i) {
120 if (backupDir.empty()) {
122 backupPath = originalPath %
'.' % i +
".bak";
124 backupPath = originalPath +
".bak";
130 if (backupDirRelative) {
131 backupPath = originalDir %
'/' % backupDir %
'/' % fileName %
'.' % i + ext;
133 backupPath = backupDir %
'/' % fileName %
'.' % i + ext;
136 if (backupDirRelative) {
137 backupPath = originalDir %
'/' % backupDir %
'/' + fileName;
139 backupPath = backupDir %
'/' + fileName;
151 if (originalStream.is_open()) {
152 originalStream.close();
157 std::filesystem::rename(originalPath, backupPathForOpen, ec);
160 std::filesystem::copy_file(originalPath, backupPathForOpen, ec);
163 throw std::ios_base::failure(
164 argsToString(
"Unable to create backup file \"", backupPathForOpen,
"\" of \"", originalPath,
"\" before rewriting it: " + ec.message()));
170 if (originalStream.is_open()) {
171 originalStream.close();
174 if (backupStream.is_open()) {
175 backupStream.close();
178 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
180 }
catch (
const std::ios_base::failure &failure) {
184 }
catch (
const std::ios_base::failure &) {
185 throw std::ios_base::failure(
"Unable to restore original file from backup file \"" % backupPath %
"\" after failure: " + failure.what());
187 throw std::ios_base::failure(argsToString(
"Unable to open backup file: ", failure.what()));
198 CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
200 auto ec = std::error_code();
202 originalPath = canonicalPath.string();
204 throw std::ios_base::failure(
"Unable to canonicalize path of original file before rewriting it: " + ec.message());
206 createBackupFile(backupDir, originalPath, backupPath, originalStream, backupStream);
229 NativeFileStream &backupStream,
Diagnostics &diag,
const std::string &context)
240 CppUtilities::NativeFileStream &outputStream, CppUtilities::NativeFileStream &backupStream,
Diagnostics &diag,
const std::string &context)
251 if (!backupPath.empty()) {
253 diag.emplace_back(
DiagLevel::Information,
"Rewriting the file to apply changed tag information has been aborted.", context);
256 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
257 }
catch (
const std::ios_base::failure &failure) {
258 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
266 if (!backupPath.empty()) {
268 diag.emplace_back(
DiagLevel::Critical,
"Rewriting the file to apply changed tag information failed.", context);
271 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
272 }
catch (
const std::ios_base::failure &failure) {
273 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
280 }
catch (
const std::ios_base::failure &) {
281 if (!backupPath.empty()) {
283 diag.emplace_back(
DiagLevel::Critical,
"An IO error occurred when rewriting the file to apply changed tag information.", context);
286 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
287 }
catch (
const std::ios_base::failure &failure) {
288 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
291 diag.emplace_back(
DiagLevel::Critical,
"An IO error occurred when applying tag information.", context);
virtual void reset()
Discards all parsing results.
std::string containingDirectory() const
Returns the path of the directory containing the current file.
static std::string fileName(std::string_view path, bool cutExtension=false)
Returns the file name of the given file.
const std::string & path() const
Returns the path of the current file.
static std::string_view pathForOpen(std::string_view url)
Returns removes the "file:/" prefix from url to be able to pass it to functions like open(),...
std::string extension() const
Returns the extension of the current file.
The Diagnostics class is a container for DiagMessage.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
The exception that is thrown when an operation has been stopped and thus not successfully completed b...
TAG_PARSER_EXPORT void createBackupFile(const std::string &backupDir, const std::string &originalPath, std::string &backupPath, CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
TAG_PARSER_EXPORT void handleFailureAfterFileModifiedCanonical(MediaFileInfo &fileInfo, const std::string &originalPath, const std::string &backupPath, CppUtilities::NativeFileStream &outputStream, CppUtilities::NativeFileStream &backupStream, Diagnostics &diag, const std::string &context="making file")
Handles a failure/abort which occurred after the file has been modified.
TAG_PARSER_EXPORT void restoreOriginalFileFromBackupFile(const std::string &originalPath, const std::string &backupPath, CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
TAG_PARSER_EXPORT void createBackupFileCanonical(const std::string &backupDir, std::string &originalPath, std::string &backupPath, CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
Creates a backup file like createBackupFile() but canonicalizes originalPath before doing the backup.
TAG_PARSER_EXPORT void handleFailureAfterFileModified(MediaFileInfo &fileInfo, const std::string &backupPath, CppUtilities::NativeFileStream &outputStream, CppUtilities::NativeFileStream &backupStream, Diagnostics &diag, const std::string &context="making file")
Contains all classes and functions of the TagInfo library.