Changed the way the autoupdater probes for potential paths, such that it does not attempt to use ProgramFiles, even if it is write-able.
Added some better choices for storing update data on OSX.
This commit is contained in:
@@ -40,9 +40,10 @@ namespace Duplicati.Library.AutoUpdater
|
||||
|
||||
public static readonly string INSTALLDIR;
|
||||
|
||||
private static readonly string INSTALLED_BASE_DIR = string.IsNullOrWhiteSpace(System.Environment.GetEnvironmentVariable(string.Format(INSTALLDIR_ENVNAME_TEMPLATE, APPNAME))) ?
|
||||
System.IO.Path.GetDirectoryName( Duplicati.Library.Utility.Utility.getEntryAssembly().Location)
|
||||
: System.Environment.GetEnvironmentVariable(string.Format(INSTALLDIR_ENVNAME_TEMPLATE, APPNAME));
|
||||
private static readonly string INSTALLED_BASE_DIR =
|
||||
string.IsNullOrWhiteSpace(System.Environment.GetEnvironmentVariable(string.Format(BASEINSTALLDIR_ENVNAME_TEMPLATE, APPNAME)))
|
||||
? System.IO.Path.GetDirectoryName(Duplicati.Library.Utility.Utility.getEntryAssembly().Location)
|
||||
: Library.Utility.Utility.ExpandEnvironmentVariables(System.Environment.GetEnvironmentVariable(string.Format(BASEINSTALLDIR_ENVNAME_TEMPLATE, APPNAME)));
|
||||
|
||||
private static readonly bool DISABLE_UPDATE_DOMAIN = !string.IsNullOrWhiteSpace(System.Environment.GetEnvironmentVariable(string.Format(SKIPUPDATE_ENVNAME_TEMPLATE, APPNAME)));
|
||||
|
||||
@@ -57,7 +58,8 @@ namespace Duplicati.Library.AutoUpdater
|
||||
public static event Action<Exception> OnError;
|
||||
|
||||
private const string DATETIME_FORMAT = "yyyymmddhhMMss";
|
||||
private const string INSTALLDIR_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_INSTALL_ROOT";
|
||||
private const string BASEINSTALLDIR_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_INSTALL_ROOT";
|
||||
private const string UPDATEINSTALLDIR_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_UPDATE_ROOT";
|
||||
internal const string SKIPUPDATE_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_SKIP_UPDATE";
|
||||
private const string RUN_UPDATED_FOLDER_PATH = "AUTOUPDATER_LOAD_UPDATE";
|
||||
private const string SLEEP_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_SLEEP";
|
||||
@@ -80,26 +82,104 @@ namespace Duplicati.Library.AutoUpdater
|
||||
|
||||
static UpdaterManager()
|
||||
{
|
||||
string installdir = null;
|
||||
var attempts = new string[] {
|
||||
System.IO.Path.Combine(InstalledBaseDir, "updates"),
|
||||
// Update folder strategy is a bit complicated,
|
||||
// because it depends on the actual system,
|
||||
// and because it tries to find a good spot
|
||||
// by probing for locations
|
||||
|
||||
// Not defined on Non-Windows
|
||||
string.IsNullOrWhiteSpace(System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles))
|
||||
? null : System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), APPNAME, "updates"),
|
||||
// The "overrides" paths are checked,
|
||||
// to see if they exist and are writeable.
|
||||
// The first existing and writeable path
|
||||
// for "overrides" is chosen
|
||||
|
||||
System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), APPNAME, "updates"),
|
||||
System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), APPNAME, "updates"),
|
||||
};
|
||||
// If override was not found, the "legacypaths"
|
||||
// are checked in the same way to see if
|
||||
// we have previously used such a folder
|
||||
// and if that folder has contents,
|
||||
// which indicates that it has been used.
|
||||
|
||||
foreach(var p in attempts)
|
||||
if (!string.IsNullOrWhiteSpace(p) && TestDirectoryIsWriteable(p))
|
||||
{
|
||||
installdir = p;
|
||||
break;
|
||||
}
|
||||
// Finally we check the "attempts",
|
||||
// which are suitable candidates
|
||||
// for storing the updates on each
|
||||
// operating system
|
||||
|
||||
if (string.IsNullOrWhiteSpace(System.Environment.GetEnvironmentVariable(string.Format(UPDATEINSTALLDIR_ENVNAME_TEMPLATE, APPNAME))))
|
||||
{
|
||||
string installdir = null;
|
||||
var programfiles = System.Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
|
||||
// The user can override updates by having a local updates folder
|
||||
var overrides = new List<string>(new string [] {
|
||||
System.IO.Path.Combine(InstalledBaseDir, "updates"),
|
||||
});
|
||||
|
||||
if (Library.Utility.Utility.IsClientWindows)
|
||||
{
|
||||
overrides.Add(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), APPNAME, "updates"));
|
||||
overrides.Add(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), APPNAME, "updates"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Library.Utility.Utility.IsClientOSX)
|
||||
overrides.Add(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library", "Application Support", APPNAME, "updates"));
|
||||
|
||||
overrides.Add(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), APPNAME, "updates"));
|
||||
}
|
||||
|
||||
// Previous locations that we don't want to use,
|
||||
// but we keep them active to avoid breaking the update syste
|
||||
var legacypaths = new List<string>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(programfiles))
|
||||
legacypaths.Add(System.IO.Path.Combine(programfiles, APPNAME, "updates"));
|
||||
if (Library.Utility.Utility.IsClientLinux)
|
||||
legacypaths.Add(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), APPNAME, "updates"));
|
||||
|
||||
// The real attempts that we probe for
|
||||
var attempts = new List<string>();
|
||||
|
||||
// We do not want to install anything in the basedir, if the application is installed in "ProgramFiles"
|
||||
if (!string.IsNullOrWhiteSpace(programfiles) && !InstalledBaseDir.StartsWith(Library.Utility.Utility.AppendDirSeparator(programfiles)))
|
||||
attempts.Add(System.IO.Path.Combine(InstalledBaseDir, "updates"));
|
||||
|
||||
if (Library.Utility.Utility.IsClientOSX)
|
||||
attempts.Add(System.IO.Path.Combine("/", "Library", "Application Support", APPNAME, "updates"));
|
||||
else
|
||||
attempts.Add(System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), APPNAME, "updates"));
|
||||
|
||||
attempts.AddRange(overrides.Skip(1));
|
||||
|
||||
// Check if the override folder exists, and choose that
|
||||
foreach (var p in overrides)
|
||||
if (!string.IsNullOrWhiteSpace(p) && System.IO.Directory.Exists(p) && TestDirectoryIsWriteable(p))
|
||||
{
|
||||
installdir = p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(installdir))
|
||||
foreach (var p in legacypaths)
|
||||
if (!string.IsNullOrWhiteSpace(p) && System.IO.Directory.Exists(p) && System.IO.Directory.EnumerateFiles(p, "*", System.IO.SearchOption.TopDirectoryOnly).Count() > 0 && TestDirectoryIsWriteable(p))
|
||||
{
|
||||
installdir = p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(installdir))
|
||||
foreach (var p in attempts)
|
||||
if (!string.IsNullOrWhiteSpace(p) && TestDirectoryIsWriteable(p))
|
||||
{
|
||||
installdir = p;
|
||||
break;
|
||||
}
|
||||
|
||||
INSTALLDIR = installdir;
|
||||
INSTALLDIR = installdir;
|
||||
}
|
||||
else
|
||||
{
|
||||
INSTALLDIR = Library.Utility.Utility.ExpandEnvironmentVariables(System.Environment.GetEnvironmentVariable(string.Format(UPDATEINSTALLDIR_ENVNAME_TEMPLATE, APPNAME)));
|
||||
}
|
||||
|
||||
|
||||
if (INSTALLDIR != null)
|
||||
{
|
||||
@@ -963,7 +1043,7 @@ namespace Duplicati.Library.AutoUpdater
|
||||
}
|
||||
}
|
||||
|
||||
Environment.SetEnvironmentVariable(string.Format(INSTALLDIR_ENVNAME_TEMPLATE, APPNAME), InstalledBaseDir);
|
||||
Environment.SetEnvironmentVariable(string.Format(BASEINSTALLDIR_ENVNAME_TEMPLATE, APPNAME), InstalledBaseDir);
|
||||
|
||||
var folder = best.Key;
|
||||
|
||||
|
||||
@@ -751,6 +751,17 @@ namespace Duplicati.Library.Utility
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if the client is Windows based
|
||||
/// </summary>
|
||||
public static bool IsClientWindows
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IsClientLinux;
|
||||
}
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Returns a value indicating if the filesystem, is case sensitive
|
||||
/// </value>
|
||||
|
||||
Reference in New Issue
Block a user