diff --git a/src/Project.cpp b/src/Project.cpp index ec8c38f905ab33d01fbc15da94072e3494563a34..a1a1dd996606f5d673efaf9b1789b4608f11d48e 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -3873,15 +3873,24 @@ bool AudacityProject::Save(bool overwrite /* = true */ , // Write the .aup now, before DirManager::SetProject, // because it's easier to clean up the effects of successful write of .aup // followed by failed SetProject, than the other way about. - // And that cleanup is done by the destructor of saveFile, if Commit() is + // And that cleanup is done by the destructor of saveFile, if PostCommit() is // not done. // (SetProject, when it fails, cleans itself up.) XMLFileWriter saveFile{ mFileName, _("Error Saving Project") }; success = GuardedCall< bool >( [&] { - WriteXMLHeader(saveFile); - WriteXML(saveFile, bWantSaveCompressed); - return true; - } ); + WriteXMLHeader(saveFile); + WriteXML(saveFile, bWantSaveCompressed); + // Flushes files, forcing space exhaustion errors before trying + // SetProject(): + saveFile.PreCommit(); + return true; + }, + MakeSimpleGuard(false), + // Suppress the usual error dialog for failed write, + // which is redundant here: + [](void*){} + ); + if (!success) return false; @@ -3920,9 +3929,14 @@ bool AudacityProject::Save(bool overwrite /* = true */ , // Commit the writing of the .aup only now, after we know that the _data // folder also saved with no problems. + // Error recovery in case this fails might not be correct -- there is no + // provision to undo the effects of SetProject -- but it is very unlikely + // that this will happen: only renaming and removing of files happens, + // not writes that might exhaust space. So DO give a second dialog in + // case the unusual happens. success = success && GuardedCall< bool >( [&] { - saveFile.Commit(); - return true; + saveFile.PostCommit(); + return true; } ); if (!success) diff --git a/src/xml/XMLWriter.cpp b/src/xml/XMLWriter.cpp index dd1904c024ca1fdfb8b884656f0a0aa40f0533a4..a969b0b7919a6ecd108635ebb3650b6ed9d20b64 100644 --- a/src/xml/XMLWriter.cpp +++ b/src/xml/XMLWriter.cpp @@ -313,14 +313,25 @@ XMLFileWriter::~XMLFileWriter() void XMLFileWriter::Commit() // may throw +{ + PreCommit(); + PostCommit(); +} + +void XMLFileWriter::PreCommit() +// may throw { while (mTagstack.GetCount()) { EndTag(mTagstack[0]); } - auto tempPath = GetName(); CloseWithoutEndingTags(); +} +void XMLFileWriter::PostCommit() +// may throw +{ + auto tempPath = GetName(); if (mKeepBackup) { if (! mBackupFile.Close() || ! wxRenameFile( mOutputPath, mBackupName ) ) diff --git a/src/xml/XMLWriter.h b/src/xml/XMLWriter.h index e8262d7b00182f2b460d5fb80442e17f343b20b6..11cb791cb2645a0f03ea2cab95e2b422771ae008 100644 --- a/src/xml/XMLWriter.h +++ b/src/xml/XMLWriter.h @@ -86,8 +86,16 @@ class AUDACITY_DLL_API XMLFileWriter final : private wxFFile, public XMLWriter { /// Close all tags and then close the file. /// Might throw. If not, then create /// or modify the file at the output path. + /// Composed of two steps, PreCommit() and PostCommit() void Commit(); + /// Does the part of Commit that might fail because of exhaustion of space + void PreCommit(); + + /// Does other parts of Commit that are not likely to fail for exhaustion + /// of space, but might for other reasons + void PostCommit(); + /// Write to file. Might throw. void Write(const wxString &data) override;