From 58f07d2021d239bb23cbf56afee24e2924ba58e1 Mon Sep 17 00:00:00 2001
From: Paul Licameli <paul.licameli@audacityteam.org>
Date: Tue, 24 Oct 2017 14:46:32 -0400
Subject: [PATCH] Flush .aup before writing .au; no redundant out-of-space
 messages

---
 src/Project.cpp       | 28 +++++++++++++++++++++-------
 src/xml/XMLWriter.cpp | 13 ++++++++++++-
 src/xml/XMLWriter.h   |  8 ++++++++
 3 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/src/Project.cpp b/src/Project.cpp
index ec8c38f905..a1a1dd9966 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 dd1904c024..a969b0b791 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 e8262d7b00..11cb791cb2 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;
 
-- 
GitLab