diff --git a/Duplicati/CommandLine/Duplicati.CommandLine.csproj b/Duplicati/CommandLine/Duplicati.CommandLine.csproj
index d975d891b..09615be3d 100644
--- a/Duplicati/CommandLine/Duplicati.CommandLine.csproj
+++ b/Duplicati/CommandLine/Duplicati.CommandLine.csproj
@@ -157,6 +157,10 @@
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}
Duplicati.Library.Backend.OneDrive
+
+ {B68F2214-951F-4F78-8488-66E1ED3F50BF}
+ Duplicati.Library.Localization
+
diff --git a/Duplicati/CommandLine/Program.cs b/Duplicati/CommandLine/Program.cs
index fe66826fb..68a42aad4 100644
--- a/Duplicati/CommandLine/Program.cs
+++ b/Duplicati/CommandLine/Program.cs
@@ -21,6 +21,7 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
+using Duplicati.Library.Localization.Short;
namespace Duplicati.CommandLine
{
@@ -230,10 +231,36 @@ namespace Duplicati.CommandLine
Console.WriteLine(string.Format("Failed to delete temp file: {0}", path));
});
-
+ var autoupdate = Library.Utility.Utility.ParseBoolOption(options, "auto-update");
+ options.Remove("auto-update");
+
if (knownCommands.ContainsKey(command))
{
- return knownCommands[command](cargs, options, filter);
+ var res = knownCommands[command](cargs, options, filter);
+
+ if (autoupdate)
+ {
+ var update = Library.AutoUpdater.UpdaterManager.LastUpdateCheckVersion;
+ if (update == null)
+ update = Library.AutoUpdater.UpdaterManager.CheckForUpdate();
+
+ if (update != null && update.Version != Library.AutoUpdater.UpdaterManager.SelfVersion.Version)
+ {
+ Console.WriteLine("Found update \"{0}\", downloading ...", update.Displayname);
+ long lastpg = 0;
+ Library.AutoUpdater.UpdaterManager.DownloadAndUnpackUpdate(update, f => {
+ var npg = (long)(f*100);
+ if (Math.Abs(npg - lastpg) >= 5 || (npg == 100 && lastpg != 100))
+ {
+ lastpg = npg;
+ Console.WriteLine("Downloading {0}% ...", npg);
+ }
+ });
+ Console.WriteLine("Update \"{0}\" ({1}) installed, using on next launch", update.Displayname, update.Version);
+ }
+ }
+
+ return res;
}
else
{
@@ -281,6 +308,7 @@ namespace Duplicati.CommandLine
new Library.Interface.CommandLineArgument("exclude", Library.Interface.CommandLineArgument.ArgumentType.String, Strings.Program.ExcludeShort, Strings.Program.ExcludeLong),
new Library.Interface.CommandLineArgument("control-files", Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.ControlFilesOptionShort, Strings.Program.ControlFilesOptionLong, "false"),
new Library.Interface.CommandLineArgument("quiet-console", Library.Interface.CommandLineArgument.ArgumentType.Boolean, Strings.Program.QuietConsoleOptionShort, Strings.Program.QuietConsoleOptionLong, "false"),
+ new Library.Interface.CommandLineArgument("auto-update", Library.Interface.CommandLineArgument.ArgumentType.Boolean, LC.L("Toggle automatic updates"), LC.L("Set this option if you prefer to have the commandline version automatically update"), "false"),
});
}
}
diff --git a/Duplicati/Library/AutoUpdater/AutoUpdateSettings.cs b/Duplicati/Library/AutoUpdater/AutoUpdateSettings.cs
index da4d4c202..19f05f95e 100644
--- a/Duplicati/Library/AutoUpdater/AutoUpdateSettings.cs
+++ b/Duplicati/Library/AutoUpdater/AutoUpdateSettings.cs
@@ -29,8 +29,7 @@ namespace Duplicati.Library.AutoUpdater
private const string UPDATE_README = "AutoUpdateFolderReadme.txt";
private const string UPDATE_INSTALL_FILE = "AutoUpdateInstallIDTemplate.txt";
- private const string UPDATEURL_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_URLS";
-
+ internal const string UPDATEURL_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_URLS";
static AutoUpdateSettings()
{
diff --git a/Duplicati/Library/AutoUpdater/Duplicati.Library.AutoUpdater.csproj b/Duplicati/Library/AutoUpdater/Duplicati.Library.AutoUpdater.csproj
index 120717548..04c6ff09b 100644
--- a/Duplicati/Library/AutoUpdater/Duplicati.Library.AutoUpdater.csproj
+++ b/Duplicati/Library/AutoUpdater/Duplicati.Library.AutoUpdater.csproj
@@ -6,11 +6,12 @@
8.0.30703
2.0
{7E119745-1F62-43F0-936C-F312A1912C0B}
- Library
+ Exe
Duplicati.Library.AutoUpdater
Duplicati.Library.AutoUpdater
true
..\..\GUI\Duplicati.GUI.TrayIcon\Duplicati.snk
+ Duplicati.Library.AutoUpdater.Program
true
@@ -43,6 +44,7 @@
+
diff --git a/Duplicati/Library/AutoUpdater/Program.cs b/Duplicati/Library/AutoUpdater/Program.cs
new file mode 100644
index 000000000..91101c48d
--- /dev/null
+++ b/Duplicati/Library/AutoUpdater/Program.cs
@@ -0,0 +1,123 @@
+// Copyright (C) 2014, Kenneth Skovhede
+
+// http://www.hexad.dk, opensource@hexad.dk
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace Duplicati.Library.AutoUpdater
+{
+ public static class Program
+ {
+ public static int Main(string[] args)
+ {
+ return Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent(typeof(Program).GetMethod("RealMain"), args, AutoUpdateStrategy.Never);
+ }
+
+ public static int RealMain(string[] _args)
+ {
+ var args = new List(_args);
+ Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args);
+
+ if (args.Count == 0)
+ {
+ WriteUsage();
+ return 100;
+ }
+ else if (args.Count != 1)
+ {
+ Console.WriteLine("Invalid number of arguments, got {0}:{1}{1}{2}{1}{1}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
+ return 100;
+ }
+
+ var cmd = args[0].ToLowerInvariant().Trim();
+ switch (cmd)
+ {
+ case "help":
+ WriteUsage();
+ return 0;
+ case "list":
+ {
+ var versions = UpdaterManager.FindInstalledVersions();
+ var selfdir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+ if (string.Equals(Library.Utility.Utility.AppendDirSeparator(selfdir), Library.Utility.Utility.AppendDirSeparator(UpdaterManager.InstalledBaseDir)))
+ versions = versions.Union(new KeyValuePair[] { new KeyValuePair(selfdir, UpdaterManager.SelfVersion) });
+ Console.WriteLine(string.Join(Environment.NewLine, versions.Select(x => string.Format(" {0} {1} ({2})", (x.Value.Version == UpdaterManager.SelfVersion.Version ? "*" : "-"), x.Value.Displayname, x.Value.Version))));
+ return 0;
+ }
+ case "check":
+ {
+ var update = UpdaterManager.CheckForUpdate();
+ if (update == null)
+ Console.WriteLine("No updates found");
+ else if (update.Version == UpdaterManager.SelfVersion.Version)
+ Console.WriteLine("You are running the latest version: {0}", update.Displayname);
+ else
+ Console.WriteLine("New version is available: {0}", update.Displayname);
+
+ return 0;
+ }
+ case "install":
+ {
+ var update = UpdaterManager.CheckForUpdate();
+ if (update == null || update.Version == UpdaterManager.SelfVersion.Version)
+ {
+ Console.WriteLine("You are running the latest version: {0} ({1})", UpdaterManager.SelfVersion.Displayname, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
+ return 0;
+ }
+ Console.WriteLine("Downloading update \"{0}\" ...", update.Displayname);
+
+ long lastpg = 0;
+ UpdaterManager.DownloadAndUnpackUpdate(update, f => {
+ var npg = (long)(f*100);
+ if (Math.Abs(npg - lastpg) >= 5 || (npg == 100 && lastpg != 100))
+ {
+ lastpg = npg;
+ Console.WriteLine("Downloading {0}% ...", npg);
+ }
+ });
+
+ Console.WriteLine("New version \"{0}\" installed!", update.Displayname);
+ return 0;
+ }
+ default:
+ Console.WriteLine("Unknown command: \"{0}\"", args[0]);
+ Console.WriteLine();
+ Console.WriteLine("Try the command \"{0}\" instead", "help");
+ return 100;
+ }
+ }
+
+ private static void WriteUsage()
+ {
+ Console.WriteLine("Usage:{0}\t{1}{2} [LIST|CHECK|INSTALL|HELP]", Environment.NewLine, Duplicati.Library.Utility.Utility.IsMono ? "mono " : "", System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location));
+ Console.WriteLine();
+ Console.WriteLine("Environment variables:");
+ Console.WriteLine();
+ Console.WriteLine("{0} - Disables updates completely", string.Format(UpdaterManager.SKIPUPDATE_ENVNAME_TEMPLATE, AutoUpdateSettings.AppName));
+ Console.WriteLine("{0} - Choose how to handle updates, valid settings: {1}", string.Format(UpdaterManager.UPDATE_STRATEGY_ENVNAME_TEMPLATE, AutoUpdateSettings.AppName), string.Join(", ", Enum.GetNames(typeof(AutoUpdateStrategy))));
+ Console.WriteLine("{0} - Use alternate updates urls", string.Format(AutoUpdateSettings.UPDATEURL_ENVNAME_TEMPLATE, AutoUpdateSettings.AppName));
+ Console.WriteLine();
+ Console.WriteLine("Updates are downloaded from: {0}", string.Join(";", AutoUpdateSettings.URLs));
+ Console.WriteLine("Updates are installed in: {0}", UpdaterManager.INSTALLDIR);
+ Console.WriteLine("The base install dir is: {0}", UpdaterManager.InstalledBaseDir);
+ Console.WriteLine("This version is \"{0}\" ({1}) and is installed in: {2}", UpdaterManager.SelfVersion.Displayname, System.Reflection.Assembly.GetExecutingAssembly().GetName().Version, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
+ Console.WriteLine();
+ }
+ }
+}
+
diff --git a/Duplicati/Library/AutoUpdater/UpdaterManager.cs b/Duplicati/Library/AutoUpdater/UpdaterManager.cs
index aed65f43c..d78ed24d8 100644
--- a/Duplicati/Library/AutoUpdater/UpdaterManager.cs
+++ b/Duplicati/Library/AutoUpdater/UpdaterManager.cs
@@ -38,7 +38,7 @@ namespace Duplicati.Library.AutoUpdater
private static readonly string[] MANIFEST_URLS = AutoUpdateSettings.URLs;
private static readonly string APPNAME = AutoUpdateSettings.AppName;
- private static readonly string INSTALLDIR;
+ internal 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(System.Reflection.Assembly.GetEntryAssembly().Location)
@@ -50,16 +50,16 @@ namespace Duplicati.Library.AutoUpdater
private static KeyValuePair? m_hasUpdateInstalled;
- private static readonly UpdateInfo SelfVersion;
+ public static readonly UpdateInfo SelfVersion;
public static event Action OnError;
private const string DATETIME_FORMAT = "yyyymmddhhMMss";
private const string INSTALLDIR_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_INSTALL_ROOT";
- private const string SKIPUPDATE_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_SKIP_UPDATE";
+ 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";
- private const string UPDATE_STRATEGY_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_POLICY";
+ internal const string UPDATE_STRATEGY_ENVNAME_TEMPLATE = "AUTOUPDATER_{0}_POLICY";
private const string UPDATE_MANIFEST_FILENAME = "autoupdate.manifest";
private const string README_FILE = "README.txt";
private const string INSTALL_FILE = "installation.txt";
@@ -71,6 +71,11 @@ namespace Duplicati.Library.AutoUpdater
/// The original directory that this application was installed into
public static string InstalledBaseDir { get { return INSTALLED_BASE_DIR; } }
+ ///
+ /// Gets the last version found from an update
+ ///
+ public static UpdateInfo LastUpdateCheckVersion { get; private set; }
+
static UpdaterManager()
{
string installdir = null;
@@ -197,7 +202,7 @@ namespace Duplicati.Library.AutoUpdater
using(var tmpfile = new Library.Utility.TempFile())
{
System.Net.WebClient wc = new System.Net.WebClient();
- wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, string.Format("{0} v{1}", APPNAME, SelfVersion.Version));
+ wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, string.Format("{0} v{1}{2}", APPNAME, SelfVersion.Version, string.IsNullOrWhiteSpace(InstallID) ? "" : " -" + InstallID));
wc.Headers.Add("X-Install-ID", InstallID);
wc.DownloadFile(url, tmpfile);
@@ -214,6 +219,7 @@ namespace Duplicati.Library.AutoUpdater
if (string.Equals(SelfVersion.ReleaseType, "Debug", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(update.ReleaseType, SelfVersion.ReleaseType, StringComparison.CurrentCultureIgnoreCase))
return null;
+ LastUpdateCheckVersion = update;
return update;
}
}
@@ -856,7 +862,7 @@ namespace Duplicati.Library.AutoUpdater
}
}
- public static int RunFromMostRecent(System.Reflection.MethodInfo method, string[] cmdargs, AutoUpdateStrategy defaultstrategy = AutoUpdateStrategy.InstallDuring)
+ public static int RunFromMostRecent(System.Reflection.MethodInfo method, string[] cmdargs, AutoUpdateStrategy defaultstrategy = AutoUpdateStrategy.CheckDuring)
{
// If the update is disabled, go straight in
if (DISABLE_UPDATE_DOMAIN)
diff --git a/Duplicati/Server/Duplicati.Server.csproj b/Duplicati/Server/Duplicati.Server.csproj
index a9e8ed29d..4040104a0 100644
--- a/Duplicati/Server/Duplicati.Server.csproj
+++ b/Duplicati/Server/Duplicati.Server.csproj
@@ -226,10 +226,6 @@
{2C838169-B187-4B09-8768-1C24C2521C8D}
Duplicati.Library.SQLiteHelper
-
- {7E119745-1F62-43F0-936C-F312A1912C0B}
- Duplicati.Library.AutoUpdater
-
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}
Duplicati.Library.Backend.OneDrive
@@ -242,6 +238,10 @@
{B68F2214-951F-4F78-8488-66E1ED3F50BF}
Duplicati.Library.Localization
+
+ {7E119745-1F62-43F0-936C-F312A1912C0B}
+ Duplicati.Library.AutoUpdater
+
diff --git a/Duplicati/Service/Duplicati.Service/Duplicati.Service.csproj b/Duplicati/Service/Duplicati.Service/Duplicati.Service.csproj
index 9b0e827d2..c56de1d68 100644
--- a/Duplicati/Service/Duplicati.Service/Duplicati.Service.csproj
+++ b/Duplicati/Service/Duplicati.Service/Duplicati.Service.csproj
@@ -42,5 +42,9 @@
{19E661D2-C5DA-4F35-B3EE-7586E5734B5F}
Duplicati.Server
+
+ {7E119745-1F62-43F0-936C-F312A1912C0B}
+ Duplicati.Library.AutoUpdater
+
\ No newline at end of file