From 4cfc7a563b0a043bb2930a999c6d8b5613107a20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Thu, 22 Apr 2021 18:03:47 +0200
Subject: [PATCH] Julia: do not overwrite Static/Dynamic files if contents has
 not changed

Ref. DynareJulia/Dynare.jl#1
---
 src/DataTree.cc     | 24 +++++++++++++++++++++++-
 src/DataTree.hh     |  7 ++++++-
 src/DynamicModel.cc | 12 +++---------
 src/StaticModel.cc  | 13 +++----------
 4 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/src/DataTree.cc b/src/DataTree.cc
index 1906212a..0eea7962 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -21,7 +21,8 @@
 #include <cassert>
 #include <iostream>
 #include <regex>
-
+#include <algorithm>
+#include <iterator>
 #include <filesystem>
 
 #include "DataTree.hh"
@@ -946,3 +947,24 @@ DataTree::packageDir(const string &package)
   filesystem::create_directories(dirname);
   return dirname;
 }
+
+void
+DataTree::writeToFileIfModified(stringstream &new_contents, const string &filename)
+{
+  ifstream old_file{filename, ios::in | ios::binary};
+  if (old_file.is_open()
+      && equal(istreambuf_iterator<char>{old_file}, istreambuf_iterator<char>{},
+               istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{}))
+    return;
+  old_file.close();
+
+  ofstream new_file{filename, ios::out | ios::binary};
+  if (!new_file.is_open())
+    {
+      cerr << "Error: Can't open file " << filename << " for writing" << endl;
+      exit(EXIT_FAILURE);
+    }
+  copy(istreambuf_iterator<char>{new_contents}, istreambuf_iterator<char>{},
+       ostreambuf_iterator<char>{new_file});
+  new_file.close();
+}
diff --git a/src/DataTree.hh b/src/DataTree.hh
index 4a82c379..ef91555f 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2020 Dynare Team
+ * Copyright © 2003-2021 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -105,6 +105,11 @@ protected:
     inside +objective subdir). */
   static string packageDir(const string &package);
 
+  /* Writes the contents of “new_contents” to the file “filename”. However, if
+     the file already exists and would not be modified by this operation, then do
+     nothing. */
+  static void writeToFileIfModified(stringstream &new_contents, const string &filename);
+
 private:
   constexpr static int constants_precision{16};
 
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 13b4edfd..f4bddc54 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -2125,14 +2125,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
     }
   else
     {
-      string filename = basename + "Dynamic.jl";
-      ofstream output;
-      output.open(filename, ios::out | ios::binary);
-      if (!output.is_open())
-        {
-          cerr << "Error: Can't open file " << filename << " for writing" << endl;
-          exit(EXIT_FAILURE);
-        }
+      stringstream output;
 
       output << "module " << basename << "Dynamic" << endl
              << "#" << endl
@@ -2330,7 +2323,8 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput,
              << "    return nothing" << endl
              << "end" << endl
              << "end" << endl;
-      output.close();
+
+      writeToFileIfModified(output, basename + "Dynamic.jl");
     }
 }
 
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 41ede9ca..a3ae89c5 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -1469,15 +1469,7 @@ StaticModel::writeStaticModel(const string &basename,
     }
   else
     {
-      string filename = basename + "Static.jl";
-      ofstream output;
-      output.open(filename, ios::out | ios::binary);
-      if (!output.is_open())
-        {
-          cerr << "Error: Can't open file " << filename << " for writing" << endl;
-          exit(EXIT_FAILURE);
-        }
-
+      stringstream output;
       output << "module " << basename << "Static" << endl
              << "#" << endl
              << "# NB: this file was automatically generated by Dynare" << endl
@@ -1675,7 +1667,8 @@ StaticModel::writeStaticModel(const string &basename,
              << "    return nothing" << endl
              << "end" << endl << endl
              << "end" << endl;
-      output.close();
+
+      writeToFileIfModified(output, basename + "Static.jl");
     }
 }
 
-- 
GitLab