JAL-3141 Backup files being created with default suffix up to 10 backups. Configurabl...
authorBen Soares <bsoares@dundee.ac.uk>
Fri, 19 Oct 2018 16:26:27 +0000 (17:26 +0100)
committerBen Soares <bsoares@dundee.ac.uk>
Fri, 19 Oct 2018 16:26:27 +0000 (17:26 +0100)
src/jalview/bin/Cache.java
src/jalview/io/JalviewFileChooser.java

index 83bc810..aa156bf 100755 (executable)
@@ -600,6 +600,24 @@ public class Cache
     return def;
   }
 
+  public static int getDefault(String property, int def)
+  {
+    String string = getProperty(property);
+    if (string != null)
+    {
+      try
+      {
+        def = Integer.parseInt(string);
+      } catch (NumberFormatException e)
+      {
+        System.out.println("Error parsing int property '" + property
+                + "' with value '" + string + "'");
+      }
+    }
+
+    return def;
+  }
+
   /**
    * These methods are used when checking if the saved preference is different
    * to the default setting
index 7a21c16..983800b 100755 (executable)
@@ -33,6 +33,7 @@ import java.awt.HeadlessException;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -350,6 +351,97 @@ public class JalviewFileChooser extends JFileChooser
       {
         ret = JalviewFileChooser.CANCEL_OPTION;
       }
+
+      rollBackupFiles(ourselectedFile);
+
+    }
+
+    return ret;
+  }
+
+  // attempts to roll backup files for this file (before overwriting). Returns
+  // true if it rolled all the files, false otherwise.
+  private static boolean rollBackupFiles(File file)
+  {
+
+    if (!file.exists())
+    {
+      // nothing to do
+      return true;
+    }
+
+    // split filename up to insert suffix template in the right place. template
+    // and backupMax can be set in .jalview_properties
+    String backupSuffixTemplate = jalview.bin.Cache
+            .getDefault("BACKUP_SUFFIX", "-bak-%n");
+    int backupMax = jalview.bin.Cache.getDefault("BACKUP_MAX", 10);
+    String dir = "";
+    try
+    {
+      File dirFile = file.getParentFile();
+      dir = dirFile.getCanonicalPath();
+    } catch (Exception e)
+    {
+      System.out.println(
+              "Could not get canonical path for file '" + file + "'");
+      return false;
+    }
+    String filename = file.getName();
+    String basename = filename;
+    String extension = "";
+    int dotchar = filename.lastIndexOf('.');
+    // don't split of filenames with the last '.' at the very beginning or
+    // very end of the filename
+    if ((dotchar > 0) && (dotchar < filename.length() - 1))
+    {
+      basename = filename.substring(0, dotchar);
+      extension = filename.substring(dotchar); // NOTE this includes the '.'
+    }
+
+    boolean ret = true;
+    if (backupMax >= 1)
+    {
+      // Create/move backups up one
+      String numString = null;
+      File lastfile = null;
+      for (int n = backupMax; n > 0; n--)
+      {
+        numString = String.format("%02d", n);
+        String backupSuffix = backupSuffixTemplate.replaceAll("%n",
+                numString);
+        String backupfilename = dir + File.separatorChar + basename
+                + backupSuffix + extension;
+        File backupfile_n = new File(backupfilename);
+
+        if (! backupfile_n.exists()) {
+          lastfile = backupfile_n;
+          continue;
+        }
+        
+        if (n == backupMax-1)
+        { // Move the max backup to /tmp instead of deleting (Just In
+          // Case)
+          String tmpfile = "tmp-" + backupfilename;
+          try
+          {
+            File tmpFile = File.createTempFile(tmpfile, ".tmp");
+            ret = ret && backupfile_n.renameTo(tmpFile);
+          } catch (IOException e)
+          {
+            System.out.println(
+                    "Could not create temp file '" + tmpfile + ".tmp'");
+          }
+        }
+        else
+        {
+          ret = ret && backupfile_n.renameTo(lastfile);
+        }
+
+        lastfile = backupfile_n;
+      }
+      
+      // now actually backup the important file!
+      ret = ret && file.renameTo(lastfile);
     }
 
     return ret;