5#include <c++utilities/conversion/stringbuilder.h>
6#include <c++utilities/conversion/stringconversion.h>
7#include <c++utilities/io/path.h>
49 const std::string &originalPath,
const std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream)
52 originalStream.exceptions(ios_base::goodbit);
53 backupStream.exceptions(ios_base::goodbit);
54 originalStream.close();
56 originalStream.clear();
60 originalStream.exceptions(ios_base::badbit | ios_base::failbit);
61 backupStream.exceptions(ios_base::badbit | ios_base::failbit);
66 auto ec = std::error_code();
67 if (!std::filesystem::exists(backupPathForOpen, ec) && !ec) {
68 throw std::ios_base::failure(
"Backup/temporary file has not been created.");
72 std::filesystem::remove(originalPathForOpen, ec);
74 throw std::ios_base::failure(
"Unable to remove original file: " + ec.message());
76 std::filesystem::rename(backupPathForOpen, originalPathForOpen, ec);
79 std::filesystem::copy_file(backupPathForOpen, originalPathForOpen, ec);
82 throw std::ios_base::failure(
"Unable to restore original file from backup file \"" % backupPath %
"\" after failure: " + ec.message());
111void createBackupFile(
const std::string &backupDir,
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream,
112 NativeFileStream &backupStream)
115 const auto backupDirRelative = std::filesystem::path(makeNativePath(backupDir)).is_relative();
119 auto ec = std::error_code();
120 for (
unsigned int i = 0;; ++i) {
121 if (backupDir.empty()) {
123 backupPath = originalPath %
'.' % i +
".bak";
125 backupPath = originalPath +
".bak";
131 if (backupDirRelative) {
132 backupPath = originalDir %
'/' % backupDir %
'/' % fileName %
'.' % i + ext;
134 backupPath = backupDir %
'/' % fileName %
'.' % i + ext;
137 if (backupDirRelative) {
138 backupPath = originalDir %
'/' % backupDir %
'/' + fileName;
140 backupPath = backupDir %
'/' + fileName;
152 if (originalStream.is_open()) {
153 originalStream.close();
157 const auto u8originalPath = std::filesystem::path(makeNativePath(originalPath));
159 std::filesystem::rename(u8originalPath, backupPathForOpen, ec);
162 std::filesystem::copy_file(u8originalPath, backupPathForOpen, ec);
165 throw std::ios_base::failure(argsToString(
"Unable to create backup file \"",
BasicFileInfo::pathForOpen(backupPath),
"\" of \"", originalPath,
166 "\" before rewriting it: " + ec.message()));
172 if (originalStream.is_open()) {
173 originalStream.close();
176 if (backupStream.is_open()) {
177 backupStream.close();
180 backupStream.exceptions(ios_base::failbit | ios_base::badbit);
182 }
catch (
const std::ios_base::failure &failure) {
186 }
catch (
const std::ios_base::failure &) {
187 throw std::ios_base::failure(
"Unable to restore original file from backup file \"" % backupPath %
"\" after failure: " + failure.what());
189 throw std::ios_base::failure(argsToString(
"Unable to open backup file: ", failure.what()));
111void createBackupFile(
const std::string &backupDir,
const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, {
…}
200 CppUtilities::NativeFileStream &originalStream, CppUtilities::NativeFileStream &backupStream)
202 auto ec = std::error_code();
203 if (
const auto canonicalPath = std::filesystem::canonical(makeNativePath(
BasicFileInfo::pathForOpen(originalPath)), ec); !ec) {
204 originalPath = canonicalPath.string();
206 throw std::ios_base::failure(
"Unable to canonicalize path of original file before rewriting it: " + ec.message());
208 createBackupFile(backupDir, originalPath, backupPath, originalStream, backupStream);
231 NativeFileStream &backupStream,
Diagnostics &diag,
const std::string &context)
242 CppUtilities::NativeFileStream &outputStream, CppUtilities::NativeFileStream &backupStream,
Diagnostics &diag,
const std::string &context)
253 if (!backupPath.empty()) {
255 diag.emplace_back(
DiagLevel::Information,
"Rewriting the file to apply changed tag information has been aborted.", context);
258 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
259 }
catch (
const std::ios_base::failure &failure) {
260 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
268 if (!backupPath.empty()) {
270 diag.emplace_back(
DiagLevel::Critical,
"Rewriting the file to apply changed tag information failed.", context);
273 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
274 }
catch (
const std::ios_base::failure &failure) {
275 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
282 }
catch (
const std::ios_base::failure &) {
283 if (!backupPath.empty()) {
285 diag.emplace_back(
DiagLevel::Critical,
"An IO error occurred when rewriting the file to apply changed tag information.", context);
288 diag.emplace_back(
DiagLevel::Warning,
"The original file has been restored.", context);
289 }
catch (
const std::ios_base::failure &failure) {
290 diag.emplace_back(
DiagLevel::Critical, argsToString(
"The original file could not be restored: ", failure.what()), context);
293 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.
static std::string extension(std::string_view path)
Returns the extension 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(),...
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...
Helps to create and restore backup files when rewriting files to apply changed tag information.
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.