diff --git a/backuphelper.cpp b/backuphelper.cpp index d8c7172..feac001 100644 --- a/backuphelper.cpp +++ b/backuphelper.cpp @@ -33,20 +33,6 @@ namespace TagParser { namespace BackupHelper { -/*! - * \brief Returns the directory used to store backup files. - * - * Setting this value allows creation of backup files in a custom location - * instead of the directory of the file being modified. - * - * \todo Add this as member variable to MediaFileInfo to avoid global. - */ -string &backupDirectory() -{ - static string backupDir; - return backupDir; -} - /*! * \brief Restores the original file from the specified backup file. * \param originalPath Specifies the path to the original file. @@ -111,6 +97,8 @@ static bool isRelative(const std::string &path) /*! * \brief Creates a backup file for the specified file. + * \param backupDir Specifies the directory to store backup files. If empty, the directory of the file + * to be backuped is used. * \param originalPath Specifies the path of the file to be backuped. * \param backupPath Contains the path of the created backup file when this function returns. * \param originalStream Specifies a std::fstream for the original file. @@ -132,10 +120,10 @@ static bool isRelative(const std::string &path) * \throws Throws std::ios_base::failure on failure. * \todo Implement callback for progress updates (copy). */ -void createBackupFile(const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, NativeFileStream &backupStream) +void createBackupFile(const std::string &backupDir, const std::string &originalPath, std::string &backupPath, NativeFileStream &originalStream, + NativeFileStream &backupStream) { // determine dirs - const auto &backupDir(backupDirectory()); const auto backupDirRelative(isRelative(backupDir)); const auto originalDir(backupDirRelative ? BasicFileInfo::containingDirectory(originalPath) : string()); diff --git a/backuphelper.h b/backuphelper.h index 9142c1b..1e26e5b 100644 --- a/backuphelper.h +++ b/backuphelper.h @@ -12,11 +12,10 @@ class Diagnostics; namespace BackupHelper { -TAG_PARSER_EXPORT std::string &backupDirectory(); TAG_PARSER_EXPORT void restoreOriginalFileFromBackupFile(const std::string &originalPath, const std::string &backupPath, IoUtilities::NativeFileStream &originalStream, IoUtilities::NativeFileStream &backupStream); -TAG_PARSER_EXPORT void createBackupFile(const std::string &originalPath, std::string &backupPath, IoUtilities::NativeFileStream &originalStream, - IoUtilities::NativeFileStream &backupStream); +TAG_PARSER_EXPORT void createBackupFile(const std::string &backupDir, const std::string &originalPath, std::string &backupPath, + IoUtilities::NativeFileStream &originalStream, IoUtilities::NativeFileStream &backupStream); TAG_PARSER_EXPORT void handleFailureAfterFileModified(MediaFileInfo &mediaFileInfo, const std::string &backupPath, IoUtilities::NativeFileStream &outputStream, IoUtilities::NativeFileStream &backupStream, Diagnostics &diag, const std::string &context = "making file"); diff --git a/matroska/matroskacontainer.cpp b/matroska/matroskacontainer.cpp index 800d4d4..e532652 100644 --- a/matroska/matroskacontainer.cpp +++ b/matroska/matroskacontainer.cpp @@ -1497,7 +1497,7 @@ void MatroskaContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFee if (fileInfo().saveFilePath().empty()) { // move current file to temp dir and reopen it as backupStream, recreate original file try { - BackupHelper::createBackupFile(fileInfo().path(), backupPath, outputStream, backupStream); + BackupHelper::createBackupFile(fileInfo().backupDirectory(), fileInfo().path(), backupPath, outputStream, backupStream); // recreate original file, define buffer variables outputStream.open(fileInfo().path(), ios_base::out | ios_base::binary | ios_base::trunc); } catch (...) { diff --git a/mediafileinfo.cpp b/mediafileinfo.cpp index 0e7c117..58818bc 100644 --- a/mediafileinfo.cpp +++ b/mediafileinfo.cpp @@ -1608,7 +1608,7 @@ void MediaFileInfo::makeMp3File(Diagnostics &diag, AbortableProgressFeedback &pr if (m_saveFilePath.empty()) { // move current file to temp dir and reopen it as backupStream, recreate original file try { - BackupHelper::createBackupFile(path(), backupPath, outputStream, backupStream); + BackupHelper::createBackupFile(backupDirectory(), path(), backupPath, outputStream, backupStream); // recreate original file, define buffer variables outputStream.open(path(), ios_base::out | ios_base::binary | ios_base::trunc); } catch (...) { diff --git a/mediafileinfo.h b/mediafileinfo.h index 26a5896..c6736b2 100644 --- a/mediafileinfo.h +++ b/mediafileinfo.h @@ -120,6 +120,8 @@ public: void clearParsingResults(); // methods to get, set object behaviour + const std::string &backupDirectory() const; + void setBackupDirectory(const std::string &backupDirectory); const std::string &saveFilePath() const; void setSaveFilePath(const std::string &saveFilePath); const std::string writingApplication() const; @@ -176,6 +178,7 @@ private: ParsingStatus m_attachmentsParsingStatus; // fields specifying object behaviour + std::string m_backupDirectory; std::string m_saveFilePath; std::string m_writingApplication; size_t m_minPadding; @@ -339,6 +342,25 @@ inline const std::vector> &MediaFileInfo::id3v2Tags() return m_id3v2Tags; } +/*! + * \brief Returns the directory used to store backup files. + * \remarks If empty, backup files will be stored in the same directory of the file being modified. + * \sa setBackupDirectory() + */ +inline const std::string &MediaFileInfo::backupDirectory() const +{ + return m_backupDirectory; +} + +/*! + * \brief Sets the directory used to store backup files. + * \remarks If empty, backup files will be stored in the same directory of the file being modified. + */ +inline void MediaFileInfo::setBackupDirectory(const std::string &backupDirectory) +{ + m_backupDirectory = backupDirectory; +} + /*! * \brief Returns the "save file path" which has been set using setSaveFilePath(). * \sa setSaveFilePath() diff --git a/mp4/mp4container.cpp b/mp4/mp4container.cpp index 7120570..b5d968d 100644 --- a/mp4/mp4container.cpp +++ b/mp4/mp4container.cpp @@ -517,7 +517,7 @@ calculatePadding: if (fileInfo().saveFilePath().empty()) { // move current file to temp dir and reopen it as backupStream, recreate original file try { - BackupHelper::createBackupFile(fileInfo().path(), backupPath, outputStream, backupStream); + BackupHelper::createBackupFile(fileInfo().backupDirectory(), fileInfo().path(), backupPath, outputStream, backupStream); // recreate original file, define buffer variables outputStream.open(fileInfo().path(), ios_base::out | ios_base::binary | ios_base::trunc); } catch (...) { diff --git a/ogg/oggcontainer.cpp b/ogg/oggcontainer.cpp index d15f431..700baf5 100644 --- a/ogg/oggcontainer.cpp +++ b/ogg/oggcontainer.cpp @@ -376,7 +376,7 @@ void OggContainer::internalMakeFile(Diagnostics &diag, AbortableProgressFeedback if (fileInfo().saveFilePath().empty()) { // move current file to temp dir and reopen it as backupStream, recreate original file try { - BackupHelper::createBackupFile(fileInfo().path(), backupPath, fileInfo().stream(), backupStream); + BackupHelper::createBackupFile(fileInfo().backupDirectory(), fileInfo().path(), backupPath, fileInfo().stream(), backupStream); // recreate original file, define buffer variables fileInfo().stream().open(fileInfo().path(), ios_base::out | ios_base::binary | ios_base::trunc); } catch (...) { diff --git a/tests/utils.cpp b/tests/utils.cpp index ae996c2..777bfb5 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -300,19 +300,16 @@ void UtilitiesTests::testBackupFile() { using namespace BackupHelper; - // ensure backup directory is empty, so backups will be created in the same directory - // as the original file - backupDirectory().clear(); - // setup testfile MediaFileInfo file(workingCopyPath("unsupported.bin")); + file.setBackupDirectory(string()); // ensure backup directory is empty, so backups will be created in the same directory as the original file const auto workingDir(file.containingDirectory()); file.open(); // create backup file string backupPath1, backupPath2; NativeFileStream backupStream1, backupStream2; - createBackupFile(file.path(), backupPath1, file.stream(), backupStream1); + createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1); CPPUNIT_ASSERT_EQUAL(workingDir + "/unsupported.bin.bak", backupPath1); // recreate original file (like the 'make' methods would do to apply changes) @@ -320,7 +317,7 @@ void UtilitiesTests::testBackupFile() file.stream() << "test1" << endl; // create a 2nd backup which should not override the first one - createBackupFile(file.path(), backupPath2, file.stream(), backupStream2); + createBackupFile(string(), file.path(), backupPath2, file.stream(), backupStream2); CPPUNIT_ASSERT_EQUAL(workingDir + "/unsupported.bin.1.bak", backupPath2); // get rid of 2nd backup, recreate original file @@ -330,9 +327,8 @@ void UtilitiesTests::testBackupFile() file.stream() << "test2" << endl; // create backup under another location - backupDirectory() = "bak"; try { - createBackupFile(file.path(), backupPath2, file.stream(), backupStream2); + createBackupFile("bak", file.path(), backupPath2, file.stream(), backupStream2); CPPUNIT_FAIL("renaming failed because backup dir does not exist"); } catch (...) { const char *what = catchIoFailure(); @@ -340,13 +336,13 @@ void UtilitiesTests::testBackupFile() } backupStream2.clear(); workingCopyPathMode("bak/unsupported.bin", WorkingCopyMode::NoCopy); - createBackupFile(file.path(), backupPath2, file.stream(), backupStream2); + createBackupFile("bak", file.path(), backupPath2, file.stream(), backupStream2); CPPUNIT_ASSERT_EQUAL(workingDir + "/bak/unsupported.bin", backupPath2); // get rid of 2nd backup (again) backupStream2.close(); CPPUNIT_ASSERT_EQUAL(0, remove(backupPath2.data())); - CPPUNIT_ASSERT_EQUAL(0, remove(argsToString(workingDir % '/' + backupDirectory()).data())); + CPPUNIT_ASSERT_EQUAL(0, remove((workingDir + "/bak").data())); // should be able to use backup stream, eg. seek to the end backupStream1.seekg(0, ios_base::end); @@ -361,11 +357,8 @@ void UtilitiesTests::testBackupFile() CPPUNIT_ASSERT_EQUAL(0x34_st, static_cast(file.stream().get())); file.close(); - // reset backup dir again - backupDirectory().clear(); - // restore after user aborted - createBackupFile(file.path(), backupPath1, file.stream(), backupStream1); + createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1); try { throw OperationAbortedException(); } catch (...) { @@ -379,7 +372,7 @@ void UtilitiesTests::testBackupFile() } // restore after error - createBackupFile(file.path(), backupPath1, file.stream(), backupStream1); + createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1); try { throw Failure(); } catch (...) { @@ -391,7 +384,7 @@ void UtilitiesTests::testBackupFile() } // restore after io failure - createBackupFile(file.path(), backupPath1, file.stream(), backupStream1); + createBackupFile(string(), file.path(), backupPath1, file.stream(), backupStream1); try { throwIoFailure("simulated IO failure"); } catch (...) {