From b81d63ea73277e356cc1e888e50fc65c2c48dcff Mon Sep 17 00:00:00 2001 From: "kenneth.skovhede@gmail.com" Date: Sat, 25 Sep 2010 12:02:14 +0000 Subject: [PATCH] Fixed a bug with async uploads that caused some files to no be uploaded. Fixed a protential race condition with warning messages and file counts (cosmetic only) when using async transfers. Spelling correction, Seperator -> Separator. Changed so a restore operation can also supply advanced options. Changed the format of timestamps in filenames to follow the Duplicity convention, which removes the need for --time-separator and --use-short-filenames. Moved the URL utility into Core, to avoid compilation errors with Monodevelop. Reorganized the runner to better support the LiveControls on all operations rather than only for backup/restore. Update issue #210 Status: Fixed I have now changed the time format to follow the Duplicity naming convention. This means that all filenames are now generated with the time set as "yyyyMMddTHHmmssZ". This format is more portable across all platforms, and easily sortable/readable. The drawback is that the Z indicates UTC time, so if one looks at the filenames, the times are not local. The motivation for this is to avoid trouble with daylight savings time offsets. There is full backwards compatibility as long as backups have not used more than one character for --time-separator (only possible via commandline). This new format means that the options --time-separator and --use-short-filenames are now deprecated and removed from the user interface. It is possible to access them from the advanced options page, along with the --use-old-filenames option. If anyone needs these options for some reason, let me know, otherwise they will be removed in a later version. git-svn-id: https://duplicati.googlecode.com/svn/trunk@523 59da171f-624f-0410-aa54-27559c288bec --- Duplicati/CommandLine/Program.cs | 12 - .../CommandLine/Strings/Program.Designer.cs | 9 - Duplicati/CommandLine/Strings/Program.resx | 3 - Duplicati/CommandLine/UnitTest.cs | 16 +- Duplicati/GUI/ApplicationSetup.cs | 2 +- Duplicati/GUI/Backup defaults.xml | 1 - .../2. Refactor for easier extensions.sql | 2 +- ...turekey.sql => 5. Remove signaturekey.sql} | 0 ...ve TimeSeparator and UseShortFilenames.sql | 9 + Duplicati/GUI/Database schema/Schema.sql | 2 +- Duplicati/GUI/Datamodel/Task.Extension.cs | 21 -- Duplicati/GUI/Duplicati.csproj | 32 +-- Duplicati/GUI/DuplicatiRunner.cs | 233 +++++++-------- Duplicati/GUI/DynamicSetupHelper.cs | 14 +- .../GUI/HelperControls/BackupFileList.cs | 4 +- .../HelperControls/BackupItems.Designer.cs | 1 + Duplicati/GUI/HelperControls/BackupItems.cs | 28 +- Duplicati/GUI/HelperControls/BackupItems.resx | 12 +- Duplicati/GUI/HelperControls/FilterDialog.cs | 6 +- Duplicati/GUI/HelperControls/FilterEditor.cs | 10 +- .../CommandLineOptionsGrid.Designer.cs | 2 +- .../Strings/CommandLineOptionsGrid.resx | 2 +- Duplicati/GUI/Program.cs | 16 +- Duplicati/GUI/TaskPackages.cs | 6 - .../Add backup/AdvancedOptions.Designer.cs | 9 - .../Add backup/AdvancedOptions.cs | 3 - .../Add backup/AdvancedOptions.resx | 41 +-- .../GeneratedFilenameOptions.Designer.cs | 94 ------ .../Add backup/GeneratedFilenameOptions.cs | 103 ------- .../Add backup/GeneratedFilenameOptions.resx | 272 ------------------ .../Wizard pages/Add backup/SelectFiles.cs | 16 +- .../Add backup/SettingOverrides.cs | 14 +- Duplicati/GUI/Wizard pages/FirstLaunch.cs | 7 + Duplicati/GUI/Wizard pages/MainPage.cs | 2 +- ...ner.cs => SelectBackupVersion.Designer.cs} | 4 +- ...SelectBackup.cs => SelectBackupVersion.cs} | 20 +- ...ctBackup.resx => SelectBackupVersion.resx} | 0 ...ner.cs => SelectBackupVersion.Designer.cs} | 8 +- ...ctBackup.resx => SelectBackupVersion.resx} | 0 .../GUI/Wizard pages/Restore/TargetFolder.cs | 2 +- Duplicati/GUI/Wizard pages/SelectBackend.cs | 17 +- .../GUI/Wizard pages/SelectBackup.Designer.cs | 52 ++-- Duplicati/GUI/Wizard pages/SelectBackup.cs | 31 +- Duplicati/GUI/Wizard pages/SelectBackup.resx | 62 +++- .../Strings/FirstLaunch.Designer.cs | 12 +- .../GUI/Wizard pages/Strings/FirstLaunch.resx | 4 + .../Strings/SelectBackup.Designer.cs | 2 +- .../GUI/Wizard pages/WizardSettingsWrapper.cs | 34 +-- .../Backend/CloudFiles/CloudFilesUI.cs | 2 +- ...uplicati.Library.Backend.CloudFiles.csproj | 3 - .../S3/Duplicati.Library.Backend.S3.csproj | 3 - Duplicati/Library/Backend/S3/S3UI.cs | 2 +- .../Compression/FileArchiveDirectory.cs | 4 +- .../Library/Compression/FileArchiveZip.cs | 10 +- .../Core/Duplicati.Library.Core.csproj | 1 + Duplicati/Library/Core/FilenameFilter.cs | 12 +- .../Core/Strings/FilenameFilter.Designer.cs | 6 +- .../Library/Core/Strings/FilenameFilter.resx | 2 +- Duplicati/Library/Core/TempFolder.cs | 2 +- Duplicati/Library/Core/Timeparser.cs | 4 +- .../{GUI => Library/Core}/UrlUtillity.cs | 22 +- Duplicati/Library/Core/Utility.cs | 25 +- Duplicati/Library/Encryption/SharpAESCrypt.cs | 12 +- Duplicati/Library/Main/BackendWrapper.cs | 32 ++- .../Library/Main/CommunicationStatistics.cs | 60 ++-- Duplicati/Library/Main/FilenameStrategy.cs | 91 ++++-- Duplicati/Library/Main/Interface.cs | 8 +- Duplicati/Library/Main/Options.cs | 48 ++-- Duplicati/Library/Main/RSyncDir.cs | 36 +-- .../Library/Main/Strings/Options.Designer.cs | 53 +++- Duplicati/Library/Main/Strings/Options.resx | 23 +- Duplicati/Library/Snapshots/LinuxSnapshot.cs | 8 +- Duplicati/Library/Snapshots/NoSnapshot.cs | 2 +- .../Library/Snapshots/WindowsSnapshot.cs | 10 +- 74 files changed, 735 insertions(+), 998 deletions(-) rename Duplicati/GUI/Database schema/{5.Remove signaturekey.sql => 5. Remove signaturekey.sql} (100%) create mode 100644 Duplicati/GUI/Database schema/6. Remove TimeSeparator and UseShortFilenames.sql delete mode 100644 Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs delete mode 100644 Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs delete mode 100644 Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx rename Duplicati/GUI/Wizard pages/Restore/{SelectBackup.Designer.cs => SelectBackupVersion.Designer.cs} (94%) rename Duplicati/GUI/Wizard pages/Restore/{SelectBackup.cs => SelectBackupVersion.cs} (73%) rename Duplicati/GUI/Wizard pages/Restore/{SelectBackup.resx => SelectBackupVersion.resx} (100%) rename Duplicati/GUI/Wizard pages/Restore/Strings/{SelectBackup.Designer.cs => SelectBackupVersion.Designer.cs} (92%) rename Duplicati/GUI/Wizard pages/Restore/Strings/{SelectBackup.resx => SelectBackupVersion.resx} (100%) rename Duplicati/{GUI => Library/Core}/UrlUtillity.cs (76%) diff --git a/Duplicati/CommandLine/Program.cs b/Duplicati/CommandLine/Program.cs index d11dd0850..344a553b3 100644 --- a/Duplicati/CommandLine/Program.cs +++ b/Duplicati/CommandLine/Program.cs @@ -116,18 +116,6 @@ namespace Duplicati.CommandLine if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("FTP_USERNAME"))) options["ftp-username"] = System.Environment.GetEnvironmentVariable("FTP_USERNAME"); - if (!Library.Core.Utility.IsClientLinux && (source.StartsWith("file://", StringComparison.InvariantCultureIgnoreCase) || target.StartsWith("file://", StringComparison.InvariantCultureIgnoreCase))) - { - string tmpShort; - options.TryGetValue("short-filenames", out tmpShort); - - if (!options.ContainsKey("time-separator") && !options.ContainsKey("time-seperator") && !Library.Core.Utility.ParseBool(tmpShort, false)) - { - Console.Error.WriteLine(Strings.Program.SettingDefaultTimeSeperatorWarning); - options["time-separator"] = "'"; - } - } - if (source.Trim().ToLower() == "list") Console.WriteLine(string.Join("\r\n", Duplicati.Library.Main.Interface.List(target, options))); else if (source.Trim().ToLower() == "list-current-files") diff --git a/Duplicati/CommandLine/Strings/Program.Designer.cs b/Duplicati/CommandLine/Strings/Program.Designer.cs index 9ab776c6a..70ef0e33b 100644 --- a/Duplicati/CommandLine/Strings/Program.Designer.cs +++ b/Duplicati/CommandLine/Strings/Program.Designer.cs @@ -201,15 +201,6 @@ namespace Duplicati.CommandLine.Strings { } } - /// - /// Looks up a localized string similar to WARNING: Duplicati uses the character : as the time seperator as that makes the filenames easier to read. However, that character is not supported on Windows filesystems. To work around this issue, Duplicati has adjusted the timeseperator char to '. Use the commandline option --time-separator=":" to prevent this from happening.. - /// - internal static string SettingDefaultTimeSeperatorWarning { - get { - return ResourceManager.GetString("SettingDefaultTimeSeperatorWarning", resourceCulture); - } - } - /// /// Looks up a localized string similar to Supported backends:. /// diff --git a/Duplicati/CommandLine/Strings/Program.resx b/Duplicati/CommandLine/Strings/Program.resx index 437fa19bb..65baa070e 100644 --- a/Duplicati/CommandLine/Strings/Program.resx +++ b/Duplicati/CommandLine/Strings/Program.resx @@ -163,9 +163,6 @@ New/Modified files - - WARNING: Duplicati uses the character : as the time seperator as that makes the filenames easier to read. However, that character is not supported on Windows filesystems. To work around this issue, Duplicati has adjusted the timeseperator char to '. Use the commandline option --time-separator=":" to prevent this from happening. - Supported backends: diff --git a/Duplicati/CommandLine/UnitTest.cs b/Duplicati/CommandLine/UnitTest.cs index fd76416b2..a97aee163 100644 --- a/Duplicati/CommandLine/UnitTest.cs +++ b/Duplicati/CommandLine/UnitTest.cs @@ -119,10 +119,6 @@ namespace Duplicati.CommandLine using(new Timer("Total unittest")) using(TempFolder tf = new TempFolder()) { - //Actually this is supposed to be the remote server's OS, not the client OS - if (System.Environment.OSVersion.Platform != PlatformID.Unix) - options["time-separator"] = "'"; - //The code below tests for a race condition in the ssh backend. /*string[] list = null; string[] prevList = null; @@ -186,7 +182,13 @@ namespace Duplicati.CommandLine List entries = Duplicati.Library.Main.Interface.ParseFileList(target, options); if (entries.Count != 1 || entries[0].Incrementals.Count != folders.Length - 1) - throw new Exception("Filename parsing problem, or corrupt storage"); + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Entry count: " + entries.Count.ToString()); + if (entries.Count == 1) + sb.Append(string.Format("Found {0} incrementals but there were {1} source folders", entries[0].Incrementals.Count, folders.Length)); + throw new Exception("Filename parsing problem, or corrupt storage: " + sb.ToString()); + } List t = new List(); t.Add(entries[0]); @@ -235,8 +237,8 @@ namespace Duplicati.CommandLine /// Another folder private static void VerifyDir(string f1, string f2) { - f1 = Utility.AppendDirSeperator(f1); - f2 = Utility.AppendDirSeperator(f2); + f1 = Utility.AppendDirSeparator(f1); + f2 = Utility.AppendDirSeparator(f2); List folders1 = Utility.EnumerateFolders(f1); List folders2 = Utility.EnumerateFolders(f2); diff --git a/Duplicati/GUI/ApplicationSetup.cs b/Duplicati/GUI/ApplicationSetup.cs index a9f5da663..9bdbb96cb 100644 --- a/Duplicati/GUI/ApplicationSetup.cs +++ b/Duplicati/GUI/ApplicationSetup.cs @@ -518,7 +518,7 @@ namespace Duplicati.GUI { Duplicati.License.LicenseEntry l = LicenseSections.SelectedItem as Duplicati.License.LicenseEntry; if (!string.IsNullOrEmpty(l.Url)) - UrlUtillity.OpenUrl(l.Url); + Duplicati.Library.Core.UrlUtillity.OpenUrl(l.Url); } } } diff --git a/Duplicati/GUI/Backup defaults.xml b/Duplicati/GUI/Backup defaults.xml index 4f1143afa..d6bca8f68 100644 --- a/Duplicati/GUI/Backup defaults.xml +++ b/Duplicati/GUI/Backup defaults.xml @@ -8,5 +8,4 @@ 13h e:.*\\Thumbs.db true - ' diff --git a/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql b/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql index 3bda651c7..01f595336 100644 --- a/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql +++ b/Duplicati/GUI/Database schema/2. Refactor for easier extensions.sql @@ -19,7 +19,7 @@ INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Async Transf INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Include Setup', [IncludeSetup] FROM Task; INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [ID], 'Ignore Timestamps', [IgnoreTimestamps] FROM Task; --- Move FileTimeSeperator into extensions +-- Move FileTimeSeparator into extensions INSERT INTO TaskExtension ([TaskID], [Name], [Value]) SELECT [TaskID], 'File Time Seperator', Value FROM BackendSetting WHERE [Name] = 'TimeSeparator'; DELETE FROM BackendSetting WHERE [Name] = 'TimeSeparator'; diff --git a/Duplicati/GUI/Database schema/5.Remove signaturekey.sql b/Duplicati/GUI/Database schema/5. Remove signaturekey.sql similarity index 100% rename from Duplicati/GUI/Database schema/5.Remove signaturekey.sql rename to Duplicati/GUI/Database schema/5. Remove signaturekey.sql diff --git a/Duplicati/GUI/Database schema/6. Remove TimeSeparator and UseShortFilenames.sql b/Duplicati/GUI/Database schema/6. Remove TimeSeparator and UseShortFilenames.sql new file mode 100644 index 000000000..b0de9c408 --- /dev/null +++ b/Duplicati/GUI/Database schema/6. Remove TimeSeparator and UseShortFilenames.sql @@ -0,0 +1,9 @@ +-- Remove unused options +DELETE FROM TaskExtension WHERE [Name] LIKE 'File Time Seperator'; +DELETE FROM TaskExtension WHERE [Name] LIKE 'Short Filenames'; + +-- Remove any empty filename prefixes which should be most common +DELETE FROM TaskExtension WHERE [Name] LIKE 'Filename Prefix' AND ([Value] LIKE '' OR [Value] IS NULL); + +-- Move any non-empty filename prefixes into the manual settings override +INSERT INTO TaskOverride ([TaskID], [Name], [Value]) SELECT [TaskID], 'filename-prefix', [Value] FROM TaskExtension WHERE [Name] LIKE 'Filename Prefix'; \ No newline at end of file diff --git a/Duplicati/GUI/Database schema/Schema.sql b/Duplicati/GUI/Database schema/Schema.sql index f8bbe1403..da09c0153 100644 --- a/Duplicati/GUI/Database schema/Schema.sql +++ b/Duplicati/GUI/Database schema/Schema.sql @@ -106,4 +106,4 @@ CREATE TABLE "EncryptionSetting" ( "Value" TEXT NULL ); -INSERT INTO "Version" ("Version") VALUES (5); \ No newline at end of file +INSERT INTO "Version" ("Version") VALUES (6); \ No newline at end of file diff --git a/Duplicati/GUI/Datamodel/Task.Extension.cs b/Duplicati/GUI/Datamodel/Task.Extension.cs index 32abbf8be..fbdaf12f0 100644 --- a/Duplicati/GUI/Datamodel/Task.Extension.cs +++ b/Duplicati/GUI/Datamodel/Task.Extension.cs @@ -189,9 +189,6 @@ namespace Duplicati.Datamodel private const string INCLUDE_SETUP = "Include Setup"; private const string IGNORE_TIMESTAMPS = "Ignore Timestamps"; private const string FILE_SIZE_LIMIT = "File Size Limit"; - private const string FILE_TIME_SEPERATOR = "File Time Seperator"; - private const string SHORT_FILENAMES = "Short Filenames"; - private const string FILENAME_PREFIX = "Filename Prefix"; private const string SELECTFILES_VERSION = "Select Files - Version"; private const string SELECTFILES_USESIMPLEMODE = "Select Files - Use Simple Mode"; @@ -270,24 +267,6 @@ namespace Duplicati.Datamodel set { m_owner.TaskExtensionsLookup[FILE_SIZE_LIMIT] = value; } } - public string FileTimeSeperator - { - get { return m_owner.TaskExtensionsLookup[FILE_TIME_SEPERATOR]; } - set { m_owner.TaskExtensionsLookup[FILE_TIME_SEPERATOR] = value; } - } - - public bool ShortFilenames - { - get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SHORT_FILENAMES], false); } - set { m_owner.TaskExtensionsLookup[SHORT_FILENAMES] = value.ToString(); } - } - - public string FilenamePrefix - { - get { return m_owner.TaskExtensionsLookup[FILENAME_PREFIX]; } - set { m_owner.TaskExtensionsLookup[FILENAME_PREFIX] = value; } - } - public int SelectFiles_Version { get { return string.IsNullOrEmpty(m_owner.TaskExtensionsLookup[SELECTFILES_VERSION]) ? 1 : int.Parse(m_owner.TaskExtensionsLookup[SELECTFILES_VERSION]); } diff --git a/Duplicati/GUI/Duplicati.csproj b/Duplicati/GUI/Duplicati.csproj index ff0173fc3..fbdaed0ae 100644 --- a/Duplicati/GUI/Duplicati.csproj +++ b/Duplicati/GUI/Duplicati.csproj @@ -307,7 +307,6 @@ ThrottleControl.cs - UserControl @@ -332,12 +331,6 @@ FinishedAdd.cs - - UserControl - - - GeneratedFilenameOptions.cs - UserControl @@ -499,21 +492,21 @@ FinishedRestore.cs - + UserControl - - SelectBackup.cs + + SelectBackupVersion.cs True True FinishedRestore.resx - + True True - SelectBackup.resx + SelectBackupVersion.resx True @@ -775,9 +768,9 @@ Designer FinishedRestore.cs - + Designer - SelectBackup.cs + SelectBackupVersion.cs Designer @@ -928,10 +921,6 @@ ThrottleControl.cs - - Designer - GeneratedFilenameOptions.cs - Designer SettingOverrides.cs @@ -1015,10 +1004,10 @@ ResXFileCodeGenerator FinishedRestore.Designer.cs - + Designer ResXFileCodeGenerator - SelectBackup.Designer.cs + SelectBackupVersion.Designer.cs Designer @@ -1132,7 +1121,8 @@ RawContainer.cs - + + diff --git a/Duplicati/GUI/DuplicatiRunner.cs b/Duplicati/GUI/DuplicatiRunner.cs index 9890d98cf..bbbd9b19a 100644 --- a/Duplicati/GUI/DuplicatiRunner.cs +++ b/Duplicati/GUI/DuplicatiRunner.cs @@ -63,169 +63,147 @@ namespace Duplicati.GUI try { - switch (task.TaskType) + //TODO: Its a bit dirty to set the options after creating the instance + using (Interface i = new Interface(destination, options)) { - case DuplicityTaskType.FullBackup: - case DuplicityTaskType.IncrementalBackup: - { - //Activate auto-cleanup - options["auto-cleanup"] = ""; - options["force"] = ""; - if (task.Schedule.Task.KeepFull > 0) - m_extraOperations++; - if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime)) - m_extraOperations++; + lock (m_lock) + m_currentBackupControlInterface = i; + SetupControlInterface(); + + i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress); - Library.Core.TempFolder tf = null; - try + switch (task.TaskType) + { + case DuplicityTaskType.FullBackup: + case DuplicityTaskType.IncrementalBackup: { - if (DuplicatiProgress != null) - DuplicatiProgress(DuplicatiOperation.Backup, RunnerState.Started, task.Schedule.Name, "", 0, -1); + //Activate auto-cleanup + options["auto-cleanup"] = ""; + options["force"] = ""; + if (task.Schedule.Task.KeepFull > 0) + m_extraOperations++; + if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime)) + m_extraOperations++; - if (task.Task.IncludeSetup) + Library.Core.TempFolder tf = null; + try { - //Make a copy of the current database - tf = new Duplicati.Library.Core.TempFolder(); - string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath)); + if (DuplicatiProgress != null) + DuplicatiProgress(DuplicatiOperation.Backup, RunnerState.Started, task.Schedule.Name, "", 0, -1); - System.IO.File.Copy(Program.DatabasePath, filename, true); - using (System.Data.IDbConnection con = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType)) + if (task.Task.IncludeSetup) { - con.ConnectionString = "Data Source=" + filename; - - //Open the database, handle any encryption issues automatically - Program.OpenDatabase(con); + //Make a copy of the current database + tf = new Duplicati.Library.Core.TempFolder(); + string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath)); - using (System.Data.IDbCommand cmd = con.CreateCommand()) + System.IO.File.Copy(Program.DatabasePath, filename, true); + using (System.Data.IDbConnection con = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType)) { - //Remove all log data to minimize the size of the database - cmd.CommandText = "DELETE FROM CommandQueue;"; - cmd.ExecuteNonQuery(); - cmd.CommandText = "DELETE FROM Log;"; - cmd.ExecuteNonQuery(); - cmd.CommandText = "DELETE FROM LogBlob;"; - cmd.ExecuteNonQuery(); + con.ConnectionString = "Data Source=" + filename; - //Free up unused space - cmd.CommandText = "VACUUM;"; + //Open the database, handle any encryption issues automatically + Program.OpenDatabase(con); + + using (System.Data.IDbCommand cmd = con.CreateCommand()) + { + //Remove all log data to minimize the size of the database + cmd.CommandText = "DELETE FROM CommandQueue;"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "DELETE FROM Log;"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "DELETE FROM LogBlob;"; + cmd.ExecuteNonQuery(); + + //Free up unused space + cmd.CommandText = "VACUUM;"; + } } + + options["signature-control-files"] = filename; } - options["signature-control-files"] = filename; + options["full-if-sourcefolder-changed"] = ""; + + List> filters = new List>(); + string[] sourceFolders = DynamicSetupHelper.GetSourceFolders(task.Task, new ApplicationSettings(task.Task.DataParent), filters); + + if (options.ContainsKey("filter")) + filters.AddRange(Library.Core.FilenameFilter.DecodeFilter(options["filter"])); + + options["filter"] = Library.Core.FilenameFilter.EncodeAsFilter(filters); + + results = i.Backup(sourceFolders); } - - options["full-if-sourcefolder-changed"] = ""; - - List> filters = new List>(); - string[] sourceFolders = DynamicSetupHelper.GetSourceFolders(task.Task, new ApplicationSettings(task.Task.DataParent), filters); - - if (options.ContainsKey("filter")) - filters.AddRange(Library.Core.FilenameFilter.DecodeFilter(options["filter"])); - - options["filter"] = Library.Core.FilenameFilter.EncodeAsFilter(filters); - - using (Interface i = new Interface(destination, options)) + finally { - try - { - lock (m_lock) - m_currentBackupControlInterface = i; - - SetupControlInterface(); + if (tf != null) + tf.Dispose(); - i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress); - results = i.Backup(sourceFolders); - } - finally - { - lock (m_lock) - m_currentBackupControlInterface = null; - } + if (DuplicatiProgress != null) + DuplicatiProgress(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1); } + break; } - finally + case DuplicityTaskType.ListBackups: + + List res = new List(); + foreach (ManifestEntry be in i.GetBackupSets()) { - if (tf != null) - tf.Dispose(); - - if (DuplicatiProgress != null) - DuplicatiProgress(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1); + res.Add(be.Time.ToString()); + foreach (ManifestEntry bei in be.Incrementals) + res.Add(bei.Time.ToString()); } + + (task as ListBackupsTask).Backups = res.ToArray(); break; - } - case DuplicityTaskType.ListBackups: + case DuplicityTaskType.ListBackupEntries: + (task as ListBackupEntriesTask).Backups = i.GetBackupSets(); + break; + case DuplicityTaskType.ListFiles: + (task as ListFilesTask).Files = i.ListCurrentFiles(); + break; + case DuplicityTaskType.ListSourceFolders: + (task as ListSourceFoldersTask).Files = new List(i.ListSourceFolders() ?? new string[0]); + break; + case DuplicityTaskType.ListActualFiles: + (task as ListActualFilesTask).Files = i.ListActualSignatureFiles(); + break; + case DuplicityTaskType.RemoveAllButNFull: + results = i.DeleteAllButNFull(); + break; + case DuplicityTaskType.RemoveOlderThan: + results = i.DeleteOlderThan(); + break; + case DuplicityTaskType.Restore: + options["file-to-restore"] = ((RestoreTask)task).SourceFiles; + if (options.ContainsKey("filter")) + options.Remove("filter"); - List res = new List(); - foreach (ManifestEntry be in Interface.ParseFileList(destination, options)) - { - res.Add(be.Time.ToString()); - foreach (ManifestEntry bei in be.Incrementals) - res.Add(bei.Time.ToString()); - } - - (task as ListBackupsTask).Backups = res.ToArray(); - break; - case DuplicityTaskType.ListBackupEntries: - (task as ListBackupEntriesTask).Backups = Interface.ParseFileList(destination, options); - break; - case DuplicityTaskType.ListFiles: - (task as ListFilesTask).Files = Interface.ListCurrentFiles(destination, options); - break; - case DuplicityTaskType.ListSourceFolders: - { - string[] tmp = Interface.ListSourceFolders(destination, options); - (task as ListSourceFoldersTask).Files = new List(tmp ?? new string[0]); - } - break; - case DuplicityTaskType.ListActualFiles: - (task as ListActualFilesTask).Files = Interface.ListActualSignatureFiles(destination, options); - break; - case DuplicityTaskType.RemoveAllButNFull: - results = Interface.DeleteAllButNFull(destination, options); - break; - case DuplicityTaskType.RemoveOlderThan: - results = Interface.DeleteOlderThan(destination, options); - break; - case DuplicityTaskType.Restore: - options["file-to-restore"] = ((RestoreTask)task).SourceFiles; - if (options.ContainsKey("filter")) - options.Remove("filter"); - - using (Interface i = new Interface(destination, options)) - { try { - lock (m_lock) - m_currentBackupControlInterface = i; - - SetupControlInterface(); - if (DuplicatiProgress != null) DuplicatiProgress(DuplicatiOperation.Restore, RunnerState.Started, task.Schedule.Name, "", 0, -1); - i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress); results = i.Restore(task.LocalPath.Split(System.IO.Path.PathSeparator)); } finally { - lock (m_lock) - m_currentBackupControlInterface = null; - if (DuplicatiProgress != null) DuplicatiProgress(DuplicatiOperation.Restore, RunnerState.Stopped, task.Schedule.Name, "", 100, -1); } - } - break; + break; - case DuplicityTaskType.RestoreSetup: - Interface.RestoreControlFiles(destination, task.LocalPath, options); - break; - default: - return; + case DuplicityTaskType.RestoreSetup: + i.RestoreControlFiles(task.LocalPath); + break; + default: + return; + } } } catch (Exception ex) { - //TODO: Extract ex.Message and save it in seperate field in the database + //TODO: Extract ex.Message and save it in separate field in the database if (ex is System.Threading.ThreadAbortException) { isAbortException = true; @@ -245,6 +223,11 @@ namespace Duplicati.GUI results += Environment.NewLine + "InnerError: " + ex.ToString(); //Don't localize } } + finally + { + lock (m_lock) + m_currentBackupControlInterface = null; + } try { diff --git a/Duplicati/GUI/DynamicSetupHelper.cs b/Duplicati/GUI/DynamicSetupHelper.cs index dc03d8929..891770cf9 100644 --- a/Duplicati/GUI/DynamicSetupHelper.cs +++ b/Duplicati/GUI/DynamicSetupHelper.cs @@ -88,8 +88,8 @@ namespace Duplicati.GUI private static string[] PrependFilterList(string[] sourceFolders, ApplicationSettings settings, List> filters) { string[] exFolders = new string[] { - Library.Core.Utility.AppendDirSeperator(System.Environment.ExpandEnvironmentVariables(settings.SignatureCachePath)), - Library.Core.Utility.AppendDirSeperator(System.Environment.ExpandEnvironmentVariables(settings.TempPath)) + Library.Core.Utility.AppendDirSeparator(System.Environment.ExpandEnvironmentVariables(settings.SignatureCachePath)), + Library.Core.Utility.AppendDirSeparator(System.Environment.ExpandEnvironmentVariables(settings.TempPath)) }; foreach (string i in sourceFolders) @@ -112,11 +112,11 @@ namespace Duplicati.GUI /// The source folder string private static string[] GetSourceFolders(bool includeDocuments, bool includeMusic, bool includeImages, bool includeDesktop, bool includeSettings, ApplicationSettings settings, List> filters) { - string myPictures = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)); - string myMusic = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)); - string desktop = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); - string appData = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); - string myDocuments = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); + string myPictures = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)); + string myMusic = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)); + string desktop = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); + string appData = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); + string myDocuments = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); List folders = new List(); List exfolders = new List(); diff --git a/Duplicati/GUI/HelperControls/BackupFileList.cs b/Duplicati/GUI/HelperControls/BackupFileList.cs index f7a77a2dd..9dcd061b3 100644 --- a/Duplicati/GUI/HelperControls/BackupFileList.cs +++ b/Duplicati/GUI/HelperControls/BackupFileList.cs @@ -331,7 +331,7 @@ namespace Duplicati.GUI.HelperControls if (t.Checked) { if (t.Tag != null && (bool)t.Tag == true) - files.Add(Library.Core.Utility.AppendDirSeperator(t.FullPath)); + files.Add(Library.Core.Utility.AppendDirSeparator(t.FullPath)); else files.Add(t.FullPath); } @@ -421,7 +421,7 @@ namespace Duplicati.GUI.HelperControls for (int index = 0; index < m_rootnodes.Length; index++) { - string target = string.IsNullOrEmpty(m_defaultTarget) ? "" : Library.Core.Utility.AppendDirSeperator(m_defaultTarget) + index.ToString(); + string target = string.IsNullOrEmpty(m_defaultTarget) ? "" : Library.Core.Utility.AppendDirSeparator(m_defaultTarget) + index.ToString(); m_rootnodes[index].Text = m_sourcefolders[index] + " => " + (!string.IsNullOrEmpty(m_targetfolders[index]) ? m_targetfolders[index] : target); m_rootnodes[index].ToolTipText = string.Format(Strings.BackupFileList.RootNodeTooltip, m_sourcefolders[index], string.IsNullOrEmpty(m_targetfolders[index]) ? target : m_targetfolders[index]); } diff --git a/Duplicati/GUI/HelperControls/BackupItems.Designer.cs b/Duplicati/GUI/HelperControls/BackupItems.Designer.cs index e10871986..a7dbddde4 100644 --- a/Duplicati/GUI/HelperControls/BackupItems.Designer.cs +++ b/Duplicati/GUI/HelperControls/BackupItems.Designer.cs @@ -82,6 +82,7 @@ namespace Duplicati.GUI.HelperControls // // backgroundWorker // + this.backgroundWorker.WorkerSupportsCancellation = true; this.backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_DoWork); this.backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker_RunWorkerCompleted); // diff --git a/Duplicati/GUI/HelperControls/BackupItems.cs b/Duplicati/GUI/HelperControls/BackupItems.cs index 141a94be9..d71f3fc2a 100644 --- a/Duplicati/GUI/HelperControls/BackupItems.cs +++ b/Duplicati/GUI/HelperControls/BackupItems.cs @@ -35,6 +35,8 @@ namespace Duplicati.GUI.HelperControls public event EventHandler LoadError; public event EventHandler ItemDoubleClicked; private Datamodel.Schedule m_schedule; + private object m_lock = new object(); + private DuplicatiRunner m_runner = null; public BackupItems() { @@ -72,8 +74,30 @@ namespace Duplicati.GUI.HelperControls private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { - DuplicatiRunner r = new DuplicatiRunner(); - e.Result = r.ListBackupEntries(m_schedule); + try + { + lock (m_lock) + m_runner = new DuplicatiRunner(); + e.Result = m_runner.ListBackupEntries(m_schedule); + } + finally + { + lock (m_lock) + m_runner = null; + } + } + + public void Abort() + { + try + { + lock (m_lock) + if (m_runner != null) + m_runner.Terminate(); + } + catch + { + } } private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) diff --git a/Duplicati/GUI/HelperControls/BackupItems.resx b/Duplicati/GUI/HelperControls/BackupItems.resx index 4126ccb68..9be3af26a 100644 --- a/Duplicati/GUI/HelperControls/BackupItems.resx +++ b/Duplicati/GUI/HelperControls/BackupItems.resx @@ -121,6 +121,12 @@ 17, 17 + + 160, 22 + + + View contents ... + 161, 26 @@ -130,12 +136,6 @@ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 160, 22 - - - View contents ... - Fill diff --git a/Duplicati/GUI/HelperControls/FilterDialog.cs b/Duplicati/GUI/HelperControls/FilterDialog.cs index a5b8bc3b4..365ca5742 100644 --- a/Duplicati/GUI/HelperControls/FilterDialog.cs +++ b/Duplicati/GUI/HelperControls/FilterDialog.cs @@ -88,9 +88,9 @@ namespace Duplicati.GUI.HelperControls { if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK) if (IsRegExp.Checked) - FilterText.Text = Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeperator(folderBrowserDialog.SelectedPath)); + FilterText.Text = Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath)); else - FilterText.Text = Duplicati.Library.Core.Utility.AppendDirSeperator(folderBrowserDialog.SelectedPath); + FilterText.Text = Duplicati.Library.Core.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath); } private void BrowseFileButton_Click(object sender, EventArgs e) @@ -104,7 +104,7 @@ namespace Duplicati.GUI.HelperControls private void HelpImage_Click(object sender, EventArgs e) { - UrlUtillity.OpenUrl("http://code.google.com/p/duplicati/wiki/FilterUsage"); + Duplicati.Library.Core.UrlUtillity.OpenUrl("http://code.google.com/p/duplicati/wiki/FilterUsage"); } private void HelpLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) diff --git a/Duplicati/GUI/HelperControls/FilterEditor.cs b/Duplicati/GUI/HelperControls/FilterEditor.cs index 0f57528b8..3027b2f8b 100644 --- a/Duplicati/GUI/HelperControls/FilterEditor.cs +++ b/Duplicati/GUI/HelperControls/FilterEditor.cs @@ -159,7 +159,7 @@ namespace Duplicati.GUI.HelperControls //Find the source folder that matches the path entered string basepath = null; foreach (string s in m_basepath) - if (filename.StartsWith(Library.Core.Utility.AppendDirSeperator(s), Library.Core.Utility.ClientFilenameStringComparision)) + if (filename.StartsWith(Library.Core.Utility.AppendDirSeparator(s), Library.Core.Utility.ClientFilenameStringComparision)) { basepath = s; break; @@ -178,7 +178,7 @@ namespace Duplicati.GUI.HelperControls while (folder.Length > basepath.Length) { folder = System.IO.Path.GetDirectoryName(folder); - parentFolders.Add(Duplicati.Library.Core.Utility.AppendDirSeperator(folder)); + parentFolders.Add(Duplicati.Library.Core.Utility.AppendDirSeparator(folder)); } //Work from the source towards the path @@ -388,7 +388,7 @@ namespace Duplicati.GUI.HelperControls /// The instance containing the event data. private void HelpButton_Click(object sender, EventArgs e) { - UrlUtillity.OpenUrl("http://code.google.com/p/duplicati/wiki/FilterUsage"); + Duplicati.Library.Core.UrlUtillity.OpenUrl("http://code.google.com/p/duplicati/wiki/FilterUsage"); } @@ -402,7 +402,7 @@ namespace Duplicati.GUI.HelperControls folderBrowserDialog.Description = Strings.FilterEditor.IncludeFolderBrowseTitle; if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK) { - listView.Items.Add(Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeperator(folderBrowserDialog.SelectedPath)), 0); + listView.Items.Add(Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath)), 0); FilenameTester_TextChanged(sender, e); } } @@ -417,7 +417,7 @@ namespace Duplicati.GUI.HelperControls folderBrowserDialog.Description = Strings.FilterEditor.ExcludeFolderBrowseTitle; if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK) { - listView.Items.Add(Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeperator(folderBrowserDialog.SelectedPath)), 1); + listView.Items.Add(Duplicati.Library.Core.FilenameFilter.ConvertGlobbingToRegExp(Duplicati.Library.Core.Utility.AppendDirSeparator(folderBrowserDialog.SelectedPath)), 1); FilenameTester_TextChanged(sender, e); } } diff --git a/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.Designer.cs b/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.Designer.cs index 8c3a15777..23d5231aa 100644 --- a/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.Designer.cs +++ b/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.Designer.cs @@ -63,7 +63,7 @@ namespace Duplicati.GUI.HelperControls.Strings { /// /// Looks up a localized string similar to Value type: {0}. ///{1}. - ///{2}.. + ///{2}. /// internal static string InfoLabelFormat { get { diff --git a/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.resx b/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.resx index 5f5b232c0..c88ce7cb0 100644 --- a/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.resx +++ b/Duplicati/GUI/HelperControls/Strings/CommandLineOptionsGrid.resx @@ -120,7 +120,7 @@ Value type: {0}. {1}. -{2}. +{2} This page is not supported on the current platform, this is a known issue. diff --git a/Duplicati/GUI/Program.cs b/Duplicati/GUI/Program.cs index 5adf985f2..66914017c 100644 --- a/Duplicati/GUI/Program.cs +++ b/Duplicati/GUI/Program.cs @@ -41,7 +41,7 @@ namespace Duplicati.GUI /// /// Gets the folder where Duplicati data is stored /// - public static string DATAFOLDER { get { return Library.Core.Utility.AppendDirSeperator(Environment.ExpandEnvironmentVariables("%" + DATAFOLDER_ENV_NAME + "%").TrimStart('"').TrimEnd('"')); } } + public static string DATAFOLDER { get { return Library.Core.Utility.AppendDirSeparator(Environment.ExpandEnvironmentVariables("%" + DATAFOLDER_ENV_NAME + "%").TrimStart('"').TrimEnd('"')); } } /// /// A flag indicating if database encryption is in use @@ -115,6 +115,8 @@ namespace Duplicati.GUI ); } + Library.Core.UrlUtillity.ErrorHandler = new Duplicati.Library.Core.UrlUtillity.ErrorHandlerDelegate(DisplayURLOpenError); + //If we are on windows we encrypt the database by default //We do not encrypt on Linux as most distros use a SQLite library without encryption support, //Linux users can use an encrypted home folder, or install a SQLite library with encryption support @@ -202,11 +204,10 @@ namespace Duplicati.GUI System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(DatabasePath)); #if DEBUG - //Default is to no use encryption for debugging - - Program.UseDatabaseEncryption = commandlineOptions.ContainsKey("unencrypted-database") ? Library.Core.Utility.ParseBool(commandlineOptions["unencrypted-database"], true) : true; + //Default is to not use encryption for debugging + Program.UseDatabaseEncryption = commandlineOptions.ContainsKey("unencrypted-database") ? !Library.Core.Utility.ParseBool(commandlineOptions["unencrypted-database"], true) : false; #else - Program.UseDatabaseEncryption = commandlineOptions.ContainsKey("unencrypted-database") ? Library.Core.Utility.ParseBool(commandlineOptions["unencrypted-database"], true) : false; + Program.UseDatabaseEncryption = commandlineOptions.ContainsKey("unencrypted-database") ? !Library.Core.Utility.ParseBool(commandlineOptions["unencrypted-database"], true) : true; #endif con.ConnectionString = "Data Source=" + DatabasePath; @@ -428,5 +429,10 @@ namespace Duplicati.GUI changePwdMethod.Invoke(con, new object[] { noEncryption ? null : password }); } } + + private static void DisplayURLOpenError(string message) + { + System.Windows.Forms.MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } } } \ No newline at end of file diff --git a/Duplicati/GUI/TaskPackages.cs b/Duplicati/GUI/TaskPackages.cs index a7fff94eb..97716592d 100644 --- a/Duplicati/GUI/TaskPackages.cs +++ b/Duplicati/GUI/TaskPackages.cs @@ -214,13 +214,7 @@ namespace Duplicati.GUI options["asynchronous-upload"] = ""; if (ext.IgnoreTimestamps) options["disable-filetime-check"] = ""; - if (!string.IsNullOrEmpty(ext.FileTimeSeperator)) - options["time-separator"] = ext.FileTimeSeperator; - if (!string.IsNullOrEmpty(ext.FilenamePrefix)) - options["backup-prefix"] = ext.FilenamePrefix; - if (ext.ShortFilenames) - options["short-filenames"] = ""; if (!string.IsNullOrEmpty(ext.FileSizeLimit)) options["skip-files-larger-than"] = ext.FileSizeLimit; } diff --git a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs index f4aaf7d4e..6ed9ebb16 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.Designer.cs @@ -34,7 +34,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup this.ThrottleOptions = new System.Windows.Forms.CheckBox(); this.EditFilters = new System.Windows.Forms.CheckBox(); this.IncludeDuplicatiSetup = new System.Windows.Forms.CheckBox(); - this.EditVolumeFilenames = new System.Windows.Forms.CheckBox(); this.EditOverrides = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // @@ -70,12 +69,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup this.IncludeDuplicatiSetup.Name = "IncludeDuplicatiSetup"; this.IncludeDuplicatiSetup.UseVisualStyleBackColor = true; // - // EditVolumeFilenames - // - resources.ApplyResources(this.EditVolumeFilenames, "EditVolumeFilenames"); - this.EditVolumeFilenames.Name = "EditVolumeFilenames"; - this.EditVolumeFilenames.UseVisualStyleBackColor = true; - // // EditOverrides // resources.ApplyResources(this.EditOverrides, "EditOverrides"); @@ -87,7 +80,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.EditOverrides); - this.Controls.Add(this.EditVolumeFilenames); this.Controls.Add(this.IncludeDuplicatiSetup); this.Controls.Add(this.EditFilters); this.Controls.Add(this.ThrottleOptions); @@ -106,7 +98,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup private System.Windows.Forms.CheckBox ThrottleOptions; private System.Windows.Forms.CheckBox EditFilters; private System.Windows.Forms.CheckBox IncludeDuplicatiSetup; - private System.Windows.Forms.CheckBox EditVolumeFilenames; private System.Windows.Forms.CheckBox EditOverrides; } } diff --git a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs index 48d5acca9..87b6777df 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.cs @@ -57,7 +57,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup m_settings["Advanced:Incremental"] = SelectCleanup.Checked; m_settings["Advanced:Throttle"] = ThrottleOptions.Checked; m_settings["Advanced:Filters"] = EditFilters.Checked; - m_settings["Advanced:Filenames"] = EditVolumeFilenames.Checked; m_settings["Advanced:Overrides"] = EditOverrides.Checked; if (args.Direction == PageChangedDirection.Back) @@ -75,8 +74,6 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup pages.Add(new Wizard_pages.Add_backup.ThrottleOptions()); if (EditFilters.Checked) pages.Add(new Wizard_pages.Add_backup.EditFilters()); - if (EditVolumeFilenames.Checked) - pages.Add(new Wizard_pages.Add_backup.GeneratedFilenameOptions()); if (EditOverrides.Checked) pages.Add(new Wizard_pages.Add_backup.SettingOverrides()); diff --git a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.resx b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.resx index c6575dbf3..619079b90 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.resx +++ b/Duplicati/GUI/Wizard pages/Add backup/AdvancedOptions.resx @@ -144,7 +144,7 @@ $this - 6 + 5 True @@ -171,7 +171,7 @@ $this - 5 + 4 True @@ -198,7 +198,7 @@ $this - 4 + 3 True @@ -225,7 +225,7 @@ $this - 3 + 2 True @@ -252,49 +252,22 @@ $this - 2 - - - True - - - 32, 136 - - - 369, 17 - - - 6 - - - Change the generated names for files stored on the backend (advanced) - - - EditVolumeFilenames - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - 1 True - 32, 168 + 32, 152 - 228, 17 + 205, 17 7 - Manually override settings (very advanced) + Manually override settings (advanced) EditOverrides diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs deleted file mode 100644 index e4fd7251d..000000000 --- a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.Designer.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace Duplicati.GUI.Wizard_pages.Add_backup -{ - partial class GeneratedFilenameOptions - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GeneratedFilenameOptions)); - this.label1 = new System.Windows.Forms.Label(); - this.FilePrefixEnabled = new System.Windows.Forms.CheckBox(); - this.UseShortFilenames = new System.Windows.Forms.CheckBox(); - this.FilePrefix = new System.Windows.Forms.TextBox(); - this.FileTimeSeperator = new System.Windows.Forms.ComboBox(); - this.SuspendLayout(); - // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // - // FilePrefixEnabled - // - resources.ApplyResources(this.FilePrefixEnabled, "FilePrefixEnabled"); - this.FilePrefixEnabled.Name = "FilePrefixEnabled"; - this.FilePrefixEnabled.UseVisualStyleBackColor = true; - this.FilePrefixEnabled.CheckedChanged += new System.EventHandler(this.FilePrefixEnabled_CheckedChanged); - // - // UseShortFilenames - // - resources.ApplyResources(this.UseShortFilenames, "UseShortFilenames"); - this.UseShortFilenames.Name = "UseShortFilenames"; - this.UseShortFilenames.UseVisualStyleBackColor = true; - // - // FilePrefix - // - resources.ApplyResources(this.FilePrefix, "FilePrefix"); - this.FilePrefix.Name = "FilePrefix"; - // - // FileTimeSeperator - // - resources.ApplyResources(this.FileTimeSeperator, "FileTimeSeperator"); - this.FileTimeSeperator.FormattingEnabled = true; - this.FileTimeSeperator.Items.AddRange(new object[] { - resources.GetString("FileTimeSeperator.Items"), - resources.GetString("FileTimeSeperator.Items1"), - resources.GetString("FileTimeSeperator.Items2")}); - this.FileTimeSeperator.Name = "FileTimeSeperator"; - // - // GeneratedFilenameOptions - // - this.Controls.Add(this.FileTimeSeperator); - this.Controls.Add(this.FilePrefix); - this.Controls.Add(this.UseShortFilenames); - this.Controls.Add(this.FilePrefixEnabled); - this.Controls.Add(this.label1); - this.Name = "GeneratedFilenameOptions"; - resources.ApplyResources(this, "$this"); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label label1; - private System.Windows.Forms.CheckBox FilePrefixEnabled; - private System.Windows.Forms.CheckBox UseShortFilenames; - private System.Windows.Forms.TextBox FilePrefix; - private System.Windows.Forms.ComboBox FileTimeSeperator; - } -} diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs deleted file mode 100644 index 997619c26..000000000 --- a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.cs +++ /dev/null @@ -1,103 +0,0 @@ -#region Disclaimer / License -// Copyright (C) 2010, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -// -#endregion -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Text; -using System.Windows.Forms; - -namespace Duplicati.GUI.Wizard_pages.Add_backup -{ - public partial class GeneratedFilenameOptions : System.Windows.Forms.Wizard.WizardControl - { - private WizardSettingsWrapper m_wrapper; - - public GeneratedFilenameOptions() - : base(Strings.GeneratedFilenameOptions.PageTitle, Strings.GeneratedFilenameOptions.PageDescription) - { - InitializeComponent(); - - base.PageEnter += new System.Windows.Forms.Wizard.PageChangeHandler(GeneratedFilenameOptions_PageEnter); - base.PageLeave += new System.Windows.Forms.Wizard.PageChangeHandler(GeneratedFilenameOptions_PageLeave); - } - - void GeneratedFilenameOptions_PageLeave(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) - { - if (args.Direction == System.Windows.Forms.Wizard.PageChangedDirection.Back) - return; - - string prefix = FilePrefixEnabled.Checked ? FilePrefix.Text : ""; - bool modified = - m_wrapper.FileTimeSeperator != FileTimeSeperator.Text || - m_wrapper.FilePrefix != prefix || - m_wrapper.ShortFilenames != UseShortFilenames.Checked; - - if (modified && m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Edit) - { - if (MessageBox.Show(this, Strings.GeneratedFilenameOptions.ModifyWillMakeBackupDisapearConfirmation, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning) != DialogResult.Yes) - { - args.Cancel = true; - return; - } - } - - m_wrapper.FileTimeSeperator = FileTimeSeperator.Text; - m_wrapper.FilePrefix = prefix; - m_wrapper.ShortFilenames = UseShortFilenames.Checked; - - WizardSettingsWrapper wrapper = new WizardSettingsWrapper(m_settings); - - if (wrapper.PrimayAction == WizardSettingsWrapper.MainAction.RestoreSetup) - args.NextPage = new RestoreSetup.FinishedRestoreSetup(); - else if (wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) - { - Datamodel.Schedule s = wrapper.DataConnection.GetObjectById(wrapper.ScheduleID); - wrapper.UpdateSchedule(s); - args.NextPage = new Restore.SelectBackup(); - } - else - { - //Don't set args.NextPage, it runs on a list - } - } - - void GeneratedFilenameOptions_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) - { - m_wrapper = new WizardSettingsWrapper(m_settings); - if (!m_valuesAutoLoaded) - { - FileTimeSeperator.Text = m_wrapper.FileTimeSeperator; - if (FileTimeSeperator.Text == "") - FileTimeSeperator.Text = ":"; - FilePrefixEnabled.Checked = !string.IsNullOrEmpty(m_wrapper.FilePrefix); - FilePrefix.Text = m_wrapper.FilePrefix; - UseShortFilenames.Checked = m_wrapper.ShortFilenames; - } - } - - private void FilePrefixEnabled_CheckedChanged(object sender, EventArgs e) - { - FilePrefix.Enabled = FilePrefixEnabled.Checked; - } - } -} - diff --git a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx b/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx deleted file mode 100644 index 700c0ac3b..000000000 --- a/Duplicati/GUI/Wizard pages/Add backup/GeneratedFilenameOptions.resx +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - True - - - - 40, 24 - - - 92, 13 - - - 0 - - - File time seperator - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 - - - True - - - 24, 56 - - - 133, 17 - - - 1 - - - Change filename prefix - - - FilePrefixEnabled - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - - True - - - 24, 88 - - - 118, 17 - - - 2 - - - Use short filenames - - - UseShortFilenames - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - False - - - 168, 56 - - - 128, 20 - - - 3 - - - FilePrefix - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - Courier New, 8.25pt - - - ' - - - : - - - _ - - - 168, 24 - - - 56, 22 - - - 4 - - - FileTimeSeperator - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - True - - - 506, 242 - - - GeneratedFilenameOptions - - - System.Windows.Forms.Wizard.WizardControl, System.Windows.Forms.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ae51c3db610c5381 - - \ No newline at end of file diff --git a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs index 613b7dc6b..b16f34de2 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SelectFiles.cs @@ -55,11 +55,11 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup InitializeComponent(); m_sizes = new Dictionary(Library.Core.Utility.IsFSCaseSensitive ? StringComparer.CurrentCulture : StringComparer.CurrentCultureIgnoreCase ); - m_myPictures = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)); - m_myMusic = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)); - m_desktop = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); - m_appData = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); - m_myDocuments = Library.Core.Utility.AppendDirSeperator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); + m_myPictures = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)); + m_myMusic = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)); + m_desktop = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); + m_appData = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); + m_myDocuments = Library.Core.Utility.AppendDirSeparator(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); FolderTooltip.SetToolTip(IncludeDocuments, m_myDocuments); FolderTooltip.SetToolTip(IncludeMusic, m_myMusic); @@ -101,7 +101,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup { string path = entry.SelectedPath.Trim(); if (!string.IsNullOrEmpty(path)) - folders.Add(Library.Core.Utility.AppendDirSeperator(path)); + folders.Add(Library.Core.Utility.AppendDirSeparator(path)); } folders.Reverse(); @@ -138,7 +138,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup { string path = entry.SelectedPath.Trim(); if (!string.IsNullOrEmpty(path)) - folders.Add(Library.Core.Utility.AppendDirSeperator(path)); + folders.Add(Library.Core.Utility.AppendDirSeparator(path)); } for (int i = 0; i < folders.Count; i++) @@ -204,7 +204,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup //Upgrade from the previous design with one source folder and multiple filters MessageBox.Show(this, Strings.SelectFiles.UpgradeWarning, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); - string p = Library.Core.Utility.AppendDirSeperator(m_wrapper.SourcePath); + string p = Library.Core.Utility.AppendDirSeparator(m_wrapper.SourcePath); List> filters = Library.Core.FilenameFilter.DecodeFilter(m_wrapper.EncodedFilters); //See what folders are included with the current setup diff --git a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs index 20548abc7..a82280711 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs @@ -49,7 +49,19 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup if (!OptionGrid.Unsupported) m_wrapper.Overrides = OptionGrid.GetConfiguration(); - //Don't set args.NextPage, it runs on a list + if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) + { + m_wrapper.UpdateSchedule(m_wrapper.DataConnection.GetObjectById(m_wrapper.ScheduleID)); + args.NextPage = new Restore.SelectBackupVersion(); + } + else if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.RestoreSetup) + { + args.NextPage = new RestoreSetup.FinishedRestoreSetup(); + } + else + { + //Don't set args.NextPage, it runs on a list + } } void SettingOverrides_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) diff --git a/Duplicati/GUI/Wizard pages/FirstLaunch.cs b/Duplicati/GUI/Wizard pages/FirstLaunch.cs index 88ca000e5..78b2cb6c5 100644 --- a/Duplicati/GUI/Wizard pages/FirstLaunch.cs +++ b/Duplicati/GUI/Wizard pages/FirstLaunch.cs @@ -58,7 +58,14 @@ namespace Duplicati.GUI.Wizard_pages } else if (RestoreSetup.Checked) { + DialogResult res = MessageBox.Show(this, Strings.FirstLaunch.ShowAdvancedQuestion, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); + if (res == DialogResult.Cancel) + { + args.Cancel = true; + return; + } wrapper.SetupDefaults(); + wrapper.ShowAdvancedRestoreOptions = res == DialogResult.Yes; args.NextPage = new Add_backup.PasswordSettings(); wrapper.DataConnection = Program.DataConnection; wrapper.PrimayAction = WizardSettingsWrapper.MainAction.RestoreSetup; diff --git a/Duplicati/GUI/Wizard pages/MainPage.cs b/Duplicati/GUI/Wizard pages/MainPage.cs index 430b43d9e..98277f966 100644 --- a/Duplicati/GUI/Wizard pages/MainPage.cs +++ b/Duplicati/GUI/Wizard pages/MainPage.cs @@ -140,7 +140,7 @@ namespace Duplicati.GUI.Wizard_pages private void donate_clicked(object sender, EventArgs e) { - Duplicati.GUI.UrlUtillity.OpenUrl("https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal%40hexad%2edk&item_name=Duplicati%20Donation&no_shipping=2&no_note=1&tax=0¤cy_code=EUR&lc=DK&bn=PP%2dDonationsBF&charset=UTF%2d8"); + Duplicati.Library.Core.UrlUtillity.OpenUrl("https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal%40hexad%2edk&item_name=Duplicati%20Donation&no_shipping=2&no_note=1&tax=0¤cy_code=EUR&lc=DK&bn=PP%2dDonationsBF&charset=UTF%2d8"); } private void donate_link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) diff --git a/Duplicati/GUI/Wizard pages/Restore/SelectBackup.Designer.cs b/Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.Designer.cs similarity index 94% rename from Duplicati/GUI/Wizard pages/Restore/SelectBackup.Designer.cs rename to Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.Designer.cs index 4979609f1..c47341c48 100644 --- a/Duplicati/GUI/Wizard pages/Restore/SelectBackup.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.Designer.cs @@ -1,6 +1,6 @@ namespace Duplicati.GUI.Wizard_pages.Restore { - partial class SelectBackup + partial class SelectBackupVersion { /// /// Required designer variable. @@ -28,7 +28,7 @@ namespace Duplicati.GUI.Wizard_pages.Restore /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectBackup)); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectBackupVersion)); this.BackupList = new Duplicati.GUI.HelperControls.BackupItems(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); diff --git a/Duplicati/GUI/Wizard pages/Restore/SelectBackup.cs b/Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.cs similarity index 73% rename from Duplicati/GUI/Wizard pages/Restore/SelectBackup.cs rename to Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.cs index 8e4fe2cd6..47c31b003 100644 --- a/Duplicati/GUI/Wizard pages/Restore/SelectBackup.cs +++ b/Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.cs @@ -30,28 +30,31 @@ using Duplicati.Library.Core; namespace Duplicati.GUI.Wizard_pages.Restore { - public partial class SelectBackup : WizardControl + public partial class SelectBackupVersion : WizardControl { WizardSettingsWrapper m_wrapper; DateTime m_selectedDate = new DateTime(); - public SelectBackup() - : base(Strings.SelectBackup.PageTitle, Strings.SelectBackup.PageDescription) + public SelectBackupVersion() + : base(Strings.SelectBackupVersion.PageTitle, Strings.SelectBackupVersion.PageDescription) { InitializeComponent(); - base.PageEnter += new PageChangeHandler(SelectBackup_PageEnter); - base.PageLeave += new PageChangeHandler(SelectBackup_PageLeave); + base.PageEnter += new PageChangeHandler(SelectBackupVersion_PageEnter); + base.PageLeave += new PageChangeHandler(SelectBackupVersion_PageLeave); } - void SelectBackup_PageLeave(object sender, PageChangedArgs args) + void SelectBackupVersion_PageLeave(object sender, PageChangedArgs args) { if (args.Direction == PageChangedDirection.Back) + { + BackupList.Abort(); return; + } if (BackupList.SelectedItem.Ticks == 0) { - MessageBox.Show(this, Strings.SelectBackup.NoBackupSelectedError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); + MessageBox.Show(this, Strings.SelectBackupVersion.NoBackupSelectedError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); args.Cancel = true; return; } @@ -63,9 +66,10 @@ namespace Duplicati.GUI.Wizard_pages.Restore args.NextPage = new TargetFolder(); } - void SelectBackup_PageEnter(object sender, PageChangedArgs args) + void SelectBackupVersion_PageEnter(object sender, PageChangedArgs args) { m_wrapper = new WizardSettingsWrapper(m_settings); + m_wrapper.UpdateSchedule(m_wrapper.DataConnection.GetObjectById(m_wrapper.ScheduleID)); BackupList.Setup(m_wrapper.DataConnection.GetObjectById(m_wrapper.ScheduleID)); } diff --git a/Duplicati/GUI/Wizard pages/Restore/SelectBackup.resx b/Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.resx similarity index 100% rename from Duplicati/GUI/Wizard pages/Restore/SelectBackup.resx rename to Duplicati/GUI/Wizard pages/Restore/SelectBackupVersion.resx diff --git a/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackup.Designer.cs b/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackupVersion.Designer.cs similarity index 92% rename from Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackup.Designer.cs rename to Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackupVersion.Designer.cs index 690aa0938..52135a6a8 100644 --- a/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackup.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackupVersion.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3082 +// Runtime Version:2.0.50727.4952 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -22,14 +22,14 @@ namespace Duplicati.GUI.Wizard_pages.Restore.Strings { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class SelectBackup { + internal class SelectBackupVersion { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal SelectBackup() { + internal SelectBackupVersion() { } /// @@ -39,7 +39,7 @@ namespace Duplicati.GUI.Wizard_pages.Restore.Strings { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Duplicati.GUI.Wizard_pages.Restore.Strings.SelectBackup", typeof(SelectBackup).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Duplicati.GUI.Wizard_pages.Restore.Strings.SelectBackupVersion", typeof(SelectBackupVersion).Assembly); resourceMan = temp; } return resourceMan; diff --git a/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackup.resx b/Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackupVersion.resx similarity index 100% rename from Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackup.resx rename to Duplicati/GUI/Wizard pages/Restore/Strings/SelectBackupVersion.resx diff --git a/Duplicati/GUI/Wizard pages/Restore/TargetFolder.cs b/Duplicati/GUI/Wizard pages/Restore/TargetFolder.cs index e1788664a..7194bd7f4 100644 --- a/Duplicati/GUI/Wizard pages/Restore/TargetFolder.cs +++ b/Duplicati/GUI/Wizard pages/Restore/TargetFolder.cs @@ -70,7 +70,7 @@ namespace Duplicati.GUI.Wizard_pages.Restore args.Cancel = true; return; } - targetpaths[i] = Library.Core.Utility.AppendDirSeperator(TargetPath.Text) + i.ToString(); + targetpaths[i] = Library.Core.Utility.AppendDirSeparator(TargetPath.Text) + i.ToString(); } } else diff --git a/Duplicati/GUI/Wizard pages/SelectBackend.cs b/Duplicati/GUI/Wizard pages/SelectBackend.cs index 9db6f1b24..226b63850 100644 --- a/Duplicati/GUI/Wizard pages/SelectBackend.cs +++ b/Duplicati/GUI/Wizard pages/SelectBackend.cs @@ -89,9 +89,20 @@ namespace Duplicati.GUI.Wizard_pages m_wrapper.Backend = selectedBackend.ProtocolKey; - //Setup page to go to after the backend GUI - if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.RestoreSetup || m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) - args.NextPage = new Add_backup.GeneratedFilenameOptions(); + if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) + { + if (m_wrapper.ShowAdvancedRestoreOptions) + args.NextPage = new Add_backup.SettingOverrides(); + else + args.NextPage = new Restore.SelectBackupVersion(); + } + else if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.RestoreSetup) + { + if (m_wrapper.ShowAdvancedRestoreOptions) + args.NextPage = new Add_backup.SettingOverrides(); + else + args.NextPage = new RestoreSetup.FinishedRestoreSetup(); + } else args.NextPage = new Add_backup.AdvancedOptions(); diff --git a/Duplicati/GUI/Wizard pages/SelectBackup.Designer.cs b/Duplicati/GUI/Wizard pages/SelectBackup.Designer.cs index ceb0346fe..1e640d45d 100644 --- a/Duplicati/GUI/Wizard pages/SelectBackup.Designer.cs +++ b/Duplicati/GUI/Wizard pages/SelectBackup.Designer.cs @@ -31,14 +31,17 @@ namespace Duplicati.GUI.Wizard_pages System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectBackup)); this.topLabel = new System.Windows.Forms.Label(); this.panel1 = new System.Windows.Forms.Panel(); + this.BackupList = new Duplicati.GUI.HelperControls.BackupTreeView(); this.ExpanderPanel = new System.Windows.Forms.Panel(); this.RestoreOptions = new System.Windows.Forms.Panel(); - this.RestoreExisting = new System.Windows.Forms.RadioButton(); this.DirectRestore = new System.Windows.Forms.Wizard.DoubleClickRadioButton(); - this.BackupList = new Duplicati.GUI.HelperControls.BackupTreeView(); + this.RestoreExisting = new System.Windows.Forms.RadioButton(); + this.ShowAdvanced = new System.Windows.Forms.CheckBox(); + this.ShowAdvancedPanel = new System.Windows.Forms.Panel(); this.panel1.SuspendLayout(); this.ExpanderPanel.SuspendLayout(); this.RestoreOptions.SuspendLayout(); + this.ShowAdvancedPanel.SuspendLayout(); this.SuspendLayout(); // // topLabel @@ -53,9 +56,19 @@ namespace Duplicati.GUI.Wizard_pages resources.ApplyResources(this.panel1, "panel1"); this.panel1.Name = "panel1"; // + // BackupList + // + resources.ApplyResources(this.BackupList, "BackupList"); + this.BackupList.Name = "BackupList"; + this.BackupList.SelectedBackup = null; + this.BackupList.SelectedFolder = ""; + this.BackupList.SelectedBackupChanged += new System.EventHandler(this.BackupList_SelectedBackupChanged); + this.BackupList.TreeDoubleClicked += new System.EventHandler(this.BackupList_TreeDoubleClicked); + // // ExpanderPanel // this.ExpanderPanel.Controls.Add(this.panel1); + this.ExpanderPanel.Controls.Add(this.ShowAdvancedPanel); this.ExpanderPanel.Controls.Add(this.RestoreOptions); resources.ApplyResources(this.ExpanderPanel, "ExpanderPanel"); this.ExpanderPanel.Name = "ExpanderPanel"; @@ -67,13 +80,6 @@ namespace Duplicati.GUI.Wizard_pages resources.ApplyResources(this.RestoreOptions, "RestoreOptions"); this.RestoreOptions.Name = "RestoreOptions"; // - // RestoreExisting - // - resources.ApplyResources(this.RestoreExisting, "RestoreExisting"); - this.RestoreExisting.Name = "RestoreExisting"; - this.RestoreExisting.TabStop = true; - this.RestoreExisting.UseVisualStyleBackColor = true; - // // DirectRestore // resources.ApplyResources(this.DirectRestore, "DirectRestore"); @@ -82,14 +88,24 @@ namespace Duplicati.GUI.Wizard_pages this.DirectRestore.UseVisualStyleBackColor = true; this.DirectRestore.DoubleClick += new System.EventHandler(this.DirectRestore_DoubleClick); // - // BackupList + // RestoreExisting // - resources.ApplyResources(this.BackupList, "BackupList"); - this.BackupList.Name = "BackupList"; - this.BackupList.SelectedBackup = null; - this.BackupList.SelectedFolder = ""; - this.BackupList.SelectedBackupChanged += new System.EventHandler(this.BackupList_SelectedBackupChanged); - this.BackupList.TreeDoubleClicked += new System.EventHandler(this.BackupList_TreeDoubleClicked); + resources.ApplyResources(this.RestoreExisting, "RestoreExisting"); + this.RestoreExisting.Name = "RestoreExisting"; + this.RestoreExisting.TabStop = true; + this.RestoreExisting.UseVisualStyleBackColor = true; + // + // ShowAdvanced + // + resources.ApplyResources(this.ShowAdvanced, "ShowAdvanced"); + this.ShowAdvanced.Name = "ShowAdvanced"; + this.ShowAdvanced.UseVisualStyleBackColor = true; + // + // ShowAdvancedPanel + // + this.ShowAdvancedPanel.Controls.Add(this.ShowAdvanced); + resources.ApplyResources(this.ShowAdvancedPanel, "ShowAdvancedPanel"); + this.ShowAdvancedPanel.Name = "ShowAdvancedPanel"; // // SelectBackup // @@ -102,6 +118,8 @@ namespace Duplicati.GUI.Wizard_pages this.ExpanderPanel.ResumeLayout(false); this.RestoreOptions.ResumeLayout(false); this.RestoreOptions.PerformLayout(); + this.ShowAdvancedPanel.ResumeLayout(false); + this.ShowAdvancedPanel.PerformLayout(); this.ResumeLayout(false); } @@ -115,5 +133,7 @@ namespace Duplicati.GUI.Wizard_pages private System.Windows.Forms.Panel RestoreOptions; private System.Windows.Forms.RadioButton RestoreExisting; private System.Windows.Forms.Wizard.DoubleClickRadioButton DirectRestore; + private System.Windows.Forms.CheckBox ShowAdvanced; + private System.Windows.Forms.Panel ShowAdvancedPanel; } } diff --git a/Duplicati/GUI/Wizard pages/SelectBackup.cs b/Duplicati/GUI/Wizard pages/SelectBackup.cs index b1dc5da83..160b438b7 100644 --- a/Duplicati/GUI/Wizard pages/SelectBackup.cs +++ b/Duplicati/GUI/Wizard pages/SelectBackup.cs @@ -33,6 +33,7 @@ namespace Duplicati.GUI.Wizard_pages public partial class SelectBackup : WizardControl { private WizardSettingsWrapper m_wrapper; + private bool m_skipFirstEvent = false; public SelectBackup() : base ("", "") @@ -52,17 +53,23 @@ namespace Duplicati.GUI.Wizard_pages if (m_wrapper.ScheduleID > 0) BackupList.SelectedBackup = m_wrapper.DataConnection.GetObjectById(m_wrapper.ScheduleID); - if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) + if (!m_valuesAutoLoaded) { - topLabel.Visible = false; - RestoreOptions.Visible = true; + if (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore) + { + topLabel.Visible = false; + RestoreOptions.Visible = true; + } + else + { + topLabel.Visible = true; + RestoreOptions.Visible = false; + ShowAdvancedPanel.Visible = false; + topLabel.Text = this.Title; + } } else - { - topLabel.Visible = true; - RestoreOptions.Visible = false; - topLabel.Text = this.Title; - } + m_skipFirstEvent = true; } void SelectBackup_PageLeave(object sender, PageChangedArgs args) @@ -105,10 +112,11 @@ namespace Duplicati.GUI.Wizard_pages args.NextPage = new Delete_backup.DeleteFinished(); break; case WizardSettingsWrapper.MainAction.Restore: + m_wrapper.ShowAdvancedRestoreOptions = ShowAdvanced.Checked; if (DirectRestore.Checked) args.NextPage = new Add_backup.PasswordSettings(); else - args.NextPage = new Restore.SelectBackup(); + args.NextPage = m_wrapper.ShowAdvancedRestoreOptions ? (IWizardControl)new Add_backup.SettingOverrides() : (IWizardControl)new Restore.SelectBackupVersion(); break; case WizardSettingsWrapper.MainAction.RunNow: args.NextPage = new RunNow.RunNowFinished(); @@ -172,7 +180,10 @@ namespace Duplicati.GUI.Wizard_pages private void BackupList_SelectedBackupChanged(object sender, EventArgs e) { - RestoreExisting.Checked = true; + if (m_skipFirstEvent) + m_skipFirstEvent = false; + else + RestoreExisting.Checked = true; } private void DirectRestore_DoubleClick(object sender, EventArgs e) diff --git a/Duplicati/GUI/Wizard pages/SelectBackup.resx b/Duplicati/GUI/Wizard pages/SelectBackup.resx index 0863b62a1..69d34cc7d 100644 --- a/Duplicati/GUI/Wizard pages/SelectBackup.resx +++ b/Duplicati/GUI/Wizard pages/SelectBackup.resx @@ -163,7 +163,7 @@ 0, 17 - 432, 127 + 432, 111 0 @@ -187,7 +187,7 @@ 0, 56 - 432, 144 + 432, 128 2 @@ -204,6 +204,60 @@ 0 + + True + + + NoControl + + + 8, 4 + + + 141, 17 + + + 4 + + + Show advanced options + + + ShowAdvanced + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ShowAdvancedPanel + + + 0 + + + Bottom + + + 0, 184 + + + 432, 24 + + + 4 + + + ShowAdvancedPanel + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ExpanderPanel + + + 1 + True @@ -286,13 +340,13 @@ ExpanderPanel - 1 + 2 32, 8 - 432, 200 + 432, 208 3 diff --git a/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.Designer.cs b/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.Designer.cs index 675360737..e3a7698fa 100644 --- a/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3082 +// Runtime Version:2.0.50727.4952 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -86,5 +86,15 @@ namespace Duplicati.GUI.Wizard_pages.Strings { return ResourceManager.GetString("PageTitle", resourceCulture); } } + + /// + /// Looks up a localized string similar to Do you need to modify advanced settings? + ///(Most users do not need this). + /// + internal static string ShowAdvancedQuestion { + get { + return ResourceManager.GetString("ShowAdvancedQuestion", resourceCulture); + } + } } } diff --git a/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.resx b/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.resx index 0778ae864..76e6a3b81 100644 --- a/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.resx +++ b/Duplicati/GUI/Wizard pages/Strings/FirstLaunch.resx @@ -126,4 +126,8 @@ Welcome to Duplicati + + Do you need to modify advanced settings? +(Most users do not need this) + \ No newline at end of file diff --git a/Duplicati/GUI/Wizard pages/Strings/SelectBackup.Designer.cs b/Duplicati/GUI/Wizard pages/Strings/SelectBackup.Designer.cs index e20a035dd..c83e23f3d 100644 --- a/Duplicati/GUI/Wizard pages/Strings/SelectBackup.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Strings/SelectBackup.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3082 +// Runtime Version:2.0.50727.4952 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs index 98d35e453..61ad73c7d 100644 --- a/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs +++ b/Duplicati/GUI/Wizard pages/WizardSettingsWrapper.cs @@ -143,10 +143,6 @@ namespace Duplicati.GUI.Wizard_pages this.IgnoreFileTimestamps = schedule.Task.Extensions.IgnoreTimestamps; this.FileSizeLimit = schedule.Task.Extensions.FileSizeLimit; - this.FilePrefix = schedule.Task.Extensions.FilenamePrefix; - this.FileTimeSeperator = schedule.Task.Extensions.FileTimeSeperator; - this.ShortFilenames = schedule.Task.Extensions.ShortFilenames; - //Handle the "Select Files" portion this.SelectFilesUI.Version = schedule.Task.Extensions.SelectFiles_Version; this.SelectFilesUI.UseSimpleMode = schedule.Task.Extensions.SelectFiles_UseSimpleMode; @@ -211,10 +207,6 @@ namespace Duplicati.GUI.Wizard_pages schedule.Task.Extensions.IgnoreTimestamps = this.IgnoreFileTimestamps; schedule.Task.Extensions.FileSizeLimit = this.FileSizeLimit; - schedule.Task.Extensions.FilenamePrefix = this.FilePrefix; - schedule.Task.Extensions.FileTimeSeperator = this.FileTimeSeperator; - schedule.Task.Extensions.ShortFilenames = this.ShortFilenames; - schedule.Task.Extensions.SelectFiles_Version = this.SelectFilesUI.Version; schedule.Task.Extensions.SelectFiles_UseSimpleMode = this.SelectFilesUI.UseSimpleMode; schedule.Task.Extensions.SelectFiles_IncludeDocuments = this.SelectFilesUI.IncludeDocuments; @@ -628,30 +620,12 @@ namespace Duplicati.GUI.Wizard_pages } /// - /// A prefix to the volume filename + /// True if advanced restore options should be displayed /// - public string FilePrefix + public bool ShowAdvancedRestoreOptions { - get { return GetItem("FilePrefix", ""); } - set { SetItem("FilePrefix", value); } - } - - /// - /// The character used to seperate time digits in the filename - /// - public string FileTimeSeperator - { - get { return GetItem("FileTimeSeperator", ":"); } - set { SetItem("FileTimeSeperator", value); } - } - - /// - /// True if the filenames generated should be short - /// - public bool ShortFilenames - { - get { return GetItem("ShortFilenames", false); } - set { SetItem("ShortFilenames", value); } + get { return GetItem("ShowAdvancedRestoreOptions", false); } + set { SetItem("ShowAdvancedRestoreOptions", value); } } /// diff --git a/Duplicati/Library/Backend/CloudFiles/CloudFilesUI.cs b/Duplicati/Library/Backend/CloudFiles/CloudFilesUI.cs index 9c2b9bced..0b900f031 100644 --- a/Duplicati/Library/Backend/CloudFiles/CloudFilesUI.cs +++ b/Duplicati/Library/Backend/CloudFiles/CloudFilesUI.cs @@ -127,7 +127,7 @@ namespace Duplicati.Library.Backend private void SignUpLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { - Duplicati.GUI.UrlUtillity.OpenUrl(LOGIN_PAGE); + Duplicati.Library.Core.UrlUtillity.OpenUrl(LOGIN_PAGE); } private void TestConnection_Click(object sender, EventArgs e) diff --git a/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj b/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj index e5cebe909..4650c835d 100644 --- a/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj +++ b/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj @@ -60,9 +60,6 @@ - - UrlUtillity.cs - UserControl diff --git a/Duplicati/Library/Backend/S3/Duplicati.Library.Backend.S3.csproj b/Duplicati/Library/Backend/S3/Duplicati.Library.Backend.S3.csproj index db5b93a14..aa0d914e3 100644 --- a/Duplicati/Library/Backend/S3/Duplicati.Library.Backend.S3.csproj +++ b/Duplicati/Library/Backend/S3/Duplicati.Library.Backend.S3.csproj @@ -66,9 +66,6 @@ - - UrlUtillity.cs - diff --git a/Duplicati/Library/Backend/S3/S3UI.cs b/Duplicati/Library/Backend/S3/S3UI.cs index 120bea2ff..f6a87d53d 100644 --- a/Duplicati/Library/Backend/S3/S3UI.cs +++ b/Duplicati/Library/Backend/S3/S3UI.cs @@ -321,7 +321,7 @@ namespace Duplicati.Library.Backend private void SignUpLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { - Duplicati.GUI.UrlUtillity.OpenUrl(LOGIN_PAGE); + Duplicati.Library.Core.UrlUtillity.OpenUrl(LOGIN_PAGE); } private void TestConnection_Click(object sender, EventArgs e) diff --git a/Duplicati/Library/Compression/FileArchiveDirectory.cs b/Duplicati/Library/Compression/FileArchiveDirectory.cs index 54983e2a6..8dbf89d51 100644 --- a/Duplicati/Library/Compression/FileArchiveDirectory.cs +++ b/Duplicati/Library/Compression/FileArchiveDirectory.cs @@ -38,7 +38,7 @@ namespace Duplicati.Library.Compression /// The folder to base the archive on public FileArchiveDirectory(string basefolder) { - m_folder = Core.Utility.AppendDirSeperator(basefolder); + m_folder = Core.Utility.AppendDirSeparator(basefolder); } #region IFileArchive Members @@ -83,7 +83,7 @@ namespace Duplicati.Library.Compression } /// - /// Lists all entries in the archive, folders are suffixed with System.IO.Path.DirectorySeperator + /// Lists all entries in the archive, folders are suffixed with System.IO.Path.DirectorySeparator /// /// An optional prefix that is used to filter the list /// A filtered list of entries diff --git a/Duplicati/Library/Compression/FileArchiveZip.cs b/Duplicati/Library/Compression/FileArchiveZip.cs index 6c0798c4d..ab4a0f7cc 100644 --- a/Duplicati/Library/Compression/FileArchiveZip.cs +++ b/Duplicati/Library/Compression/FileArchiveZip.cs @@ -83,7 +83,7 @@ namespace Duplicati.Library.Compression /// /// Converts a zip file path to the format used by the local filesystem. - /// Internally all files are stored in the archive use / as directory seperator. + /// Internally all files are stored in the archive use / as directory separator. /// /// The path to convert in internal format /// The path in filesystem format @@ -97,7 +97,7 @@ namespace Duplicati.Library.Compression /// /// Converts a file system path to the internal format. - /// Internally all files are stored in the archive use / as directory seperator. + /// Internally all files are stored in the archive use / as directory separator. /// /// The path to convert in filesystem format /// The path in the internal format @@ -177,7 +177,7 @@ namespace Duplicati.Library.Compression if (prefix == null || name.StartsWith(prefix)) { if (ze.IsDirectory) - results.Add(Core.Utility.AppendDirSeperator(name)); + results.Add(Core.Utility.AppendDirSeparator(name)); } } @@ -203,7 +203,7 @@ namespace Duplicati.Library.Compression if (prefix == null || name.StartsWith(prefix)) { if (ze.IsDirectory) - results.Add(Core.Utility.AppendDirSeperator(name)); + results.Add(Core.Utility.AppendDirSeparator(name)); else results.Add(name); } @@ -304,7 +304,7 @@ namespace Duplicati.Library.Compression { ICSharpCode.SharpZipLib.Zip.ZipEntry ze = m_zip.GetEntry(PathFromFilesystem(file)); - if (ze == null) //Grrr... The zip library has a pretty relaxed take on seperators + if (ze == null) //Grrr... The zip library has a pretty relaxed take on separators ze = m_zip.GetEntry(PathToFilesystem(file)); return ze; diff --git a/Duplicati/Library/Core/Duplicati.Library.Core.csproj b/Duplicati/Library/Core/Duplicati.Library.Core.csproj index 4f7196e69..860b9e401 100644 --- a/Duplicati/Library/Core/Duplicati.Library.Core.csproj +++ b/Duplicati/Library/Core/Duplicati.Library.Core.csproj @@ -105,6 +105,7 @@ + diff --git a/Duplicati/Library/Core/FilenameFilter.cs b/Duplicati/Library/Core/FilenameFilter.cs index 6ff121808..9ef49ec36 100644 --- a/Duplicati/Library/Core/FilenameFilter.cs +++ b/Duplicati/Library/Core/FilenameFilter.cs @@ -59,8 +59,8 @@ namespace Duplicati.Library.Core //It is annoying to use backslashes on windows, because they are also escape //controls, so \t has to be \\t and on the command line it must be \\\\t, so we - //accept the unix style dir seperator "/" - cmd = cmd.Replace("/", ConvertGlobbingToRegExp(System.IO.Path.DirectorySeparatorChar.ToString())); + //accept the unix style dir separator "/" + cmd = cmd.Replace("/", ConvertGlobbingToRegExp(Core.Utility.DirectorySeparatorString)); lst.Add(new KeyValuePair(include, cmd)); if (remove) @@ -88,7 +88,7 @@ namespace Duplicati.Library.Core sb.Append(System.IO.Path.PathSeparator.ToString()); sb.Append(x.Key ? "i:" : "e:"); if (x.Value.Contains(System.IO.Path.PathSeparator.ToString())) - throw new Exception(string.Format(Strings.FilenameFilter.FilterContainsPathSeperator, System.IO.Path.PathSeparator)); + throw new Exception(string.Format(Strings.FilenameFilter.FilterContainsPathSeparator, System.IO.Path.PathSeparator)); sb.Append(x.Value); } return sb.ToString(); @@ -112,7 +112,7 @@ namespace Duplicati.Library.Core x = filter.IndexOf(System.IO.Path.PathSeparator, x); //HACK: Detection of linux special case - //TODO: Reconsider using the ":" character, as that is the PathSeperator on linux + //TODO: Reconsider using the ":" character, as that is the PathSeparator on linux if (System.IO.Path.PathSeparator == ':' && x == 1) x = filter.IndexOf(System.IO.Path.PathSeparator, x + 1); @@ -236,7 +236,7 @@ namespace Duplicati.Library.Core public bool ShouldInclude(string basepath, string filename, out IFilenameFilter match) { match = null; - basepath = Core.Utility.AppendDirSeperator(basepath); + basepath = Core.Utility.AppendDirSeparator(basepath); if (!filename.StartsWith(basepath, Core.Utility.ClientFilenameStringComparision)) return false; @@ -258,7 +258,7 @@ namespace Duplicati.Library.Core public List FilterList(string basepath, IEnumerable filenames) { - basepath = Core.Utility.AppendDirSeperator(basepath); + basepath = Core.Utility.AppendDirSeparator(basepath); List included = new List(); foreach (string s in filenames) diff --git a/Duplicati/Library/Core/Strings/FilenameFilter.Designer.cs b/Duplicati/Library/Core/Strings/FilenameFilter.Designer.cs index 348c2cb88..1e946b64a 100644 --- a/Duplicati/Library/Core/Strings/FilenameFilter.Designer.cs +++ b/Duplicati/Library/Core/Strings/FilenameFilter.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.3082 +// Runtime Version:2.0.50727.4952 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -63,9 +63,9 @@ namespace Duplicati.Library.Core.Strings { /// /// Looks up a localized string similar to Filter contains: {0}. /// - internal static string FilterContainsPathSeperator { + internal static string FilterContainsPathSeparator { get { - return ResourceManager.GetString("FilterContainsPathSeperator", resourceCulture); + return ResourceManager.GetString("FilterContainsPathSeparator", resourceCulture); } } } diff --git a/Duplicati/Library/Core/Strings/FilenameFilter.resx b/Duplicati/Library/Core/Strings/FilenameFilter.resx index 5ca91180c..be41d61ca 100644 --- a/Duplicati/Library/Core/Strings/FilenameFilter.resx +++ b/Duplicati/Library/Core/Strings/FilenameFilter.resx @@ -117,7 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Filter contains: {0} \ No newline at end of file diff --git a/Duplicati/Library/Core/TempFolder.cs b/Duplicati/Library/Core/TempFolder.cs index 3a59c2aff..8f7838fc3 100644 --- a/Duplicati/Library/Core/TempFolder.cs +++ b/Duplicati/Library/Core/TempFolder.cs @@ -39,7 +39,7 @@ namespace Duplicati.Library.Core public TempFolder(string folder) { m_protect = false; - m_folder = Core.Utility.AppendDirSeperator(folder); + m_folder = Core.Utility.AppendDirSeparator(folder); System.IO.Directory.CreateDirectory(m_folder); } diff --git a/Duplicati/Library/Core/Timeparser.cs b/Duplicati/Library/Core/Timeparser.cs index 4c8c19024..ec824cb19 100644 --- a/Duplicati/Library/Core/Timeparser.cs +++ b/Duplicati/Library/Core/Timeparser.cs @@ -62,12 +62,12 @@ namespace Duplicati.Library.Core if (DateTime.TryParse(datestring, System.Globalization.CultureInfo.CurrentUICulture, System.Globalization.DateTimeStyles.None, out t)) return t; - char[] seperators = new char[] { 's', 'm', 'h', 'D', 'W', 'M', 'Y' }; + char[] separators = new char[] { 's', 'm', 'h', 'D', 'W', 'M', 'Y' }; int index = 0; int previndex = 0; - while ((index = datestring.IndexOfAny(seperators, previndex)) > 0) + while ((index = datestring.IndexOfAny(separators, previndex)) > 0) { string partial = datestring.Substring(previndex, index - previndex).Trim(); int factor; diff --git a/Duplicati/GUI/UrlUtillity.cs b/Duplicati/Library/Core/UrlUtillity.cs similarity index 76% rename from Duplicati/GUI/UrlUtillity.cs rename to Duplicati/Library/Core/UrlUtillity.cs index df43a2dd5..5ddd18a51 100644 --- a/Duplicati/GUI/UrlUtillity.cs +++ b/Duplicati/Library/Core/UrlUtillity.cs @@ -20,16 +20,31 @@ using System; using System.Collections.Generic; using System.Text; -using System.Windows.Forms; -namespace Duplicati.GUI +namespace Duplicati.Library.Core { public static class UrlUtillity { + /// + /// The file path to the system browser selected + /// public static string SystemBrowser = null; + + /// + /// A delegate for handing error messages + /// + /// The message to display the error for + public delegate void ErrorHandlerDelegate(string errormessage); + + /// + /// The errorhandler callback method + /// + public static ErrorHandlerDelegate ErrorHandler; + /// /// Opens the given URL in a browser /// + /// The url to open, must start with http:// or https:// public static void OpenUrl(string url) { try @@ -68,7 +83,8 @@ namespace Duplicati.GUI } catch { - MessageBox.Show(string.Format("Unable to open a browser window, please manually visit: \r\n{0}", url), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + if (ErrorHandler != null) + ErrorHandler(string.Format("Unable to open a browser window, please manually visit: \r\n{0}", url)); } } diff --git a/Duplicati/Library/Core/Utility.cs b/Duplicati/Library/Core/Utility.cs index 38734b79e..f1da52295 100644 --- a/Duplicati/Library/Core/Utility.cs +++ b/Duplicati/Library/Core/Utility.cs @@ -125,11 +125,11 @@ namespace Duplicati.Library.Core while (lst.Count > 0) { - string f = AppendDirSeperator(lst.Dequeue()); + string f = AppendDirSeparator(lst.Dequeue()); try { foreach (string s in folderList(f)) - if (filter == null || filter.ShouldInclude(rootpath, AppendDirSeperator(s))) + if (filter == null || filter.ShouldInclude(rootpath, AppendDirSeparator(s))) lst.Enqueue(s); callback(rootpath, f, EnumeratedFileStatus.Folder); @@ -237,7 +237,7 @@ namespace Duplicati.Library.Core /// The search is recursive. /// /// The folder to look in. - /// A list of the full filenames and foldernames. Foldernames ends with the directoryseperator char + /// A list of the full filenames and foldernames. Foldernames ends with the directoryseparator char public static List EnumerateFileSystemEntries(string basepath) { return EnumerateFileSystemEntries(basepath, null); @@ -249,7 +249,7 @@ namespace Duplicati.Library.Core /// /// The folder to look in. /// An optional filter to apply to the filenames - /// A list of the full filenames and foldernames. Foldernames ends with the directoryseperator char + /// A list of the full filenames and foldernames. Foldernames ends with the directoryseparator char public static List EnumerateFileSystemEntries(string basepath, FilenameFilter filter) { PathCollector c = new PathCollector(true, true); @@ -272,15 +272,20 @@ namespace Duplicati.Library.Core } /// - /// Appends the appropriate directory seperator to paths, depending on OS. - /// Does not append the seperator if the path already ends with it. + /// A cached instance of the directory separator as a string + /// + public static readonly string DirectorySeparatorString = System.IO.Path.DirectorySeparatorChar.ToString(); + + /// + /// Appends the appropriate directory separator to paths, depending on OS. + /// Does not append the separator if the path already ends with it. /// /// The path to append to - /// The path with the directory seperator appended - public static string AppendDirSeperator(string path) + /// The path with the directory separator appended + public static string AppendDirSeparator(string path) { - if (!path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString())) - return path += System.IO.Path.DirectorySeparatorChar; + if (!path.EndsWith(DirectorySeparatorString)) + return path += DirectorySeparatorString; else return path; } diff --git a/Duplicati/Library/Encryption/SharpAESCrypt.cs b/Duplicati/Library/Encryption/SharpAESCrypt.cs index 10bb4e598..02337afce 100644 --- a/Duplicati/Library/Encryption/SharpAESCrypt.cs +++ b/Duplicati/Library/Encryption/SharpAESCrypt.cs @@ -155,7 +155,7 @@ namespace SharpAESCrypt /// /// An exception message that indicates that an extension had an invalid format /// - public static string InvalidExtensionData = "Invalid extension data, seperator (0x00) not found"; + public static string InvalidExtensionData = "Invalid extension data, separator (0x00) not found"; /// /// An exception message that indicates that the format was accepted, but the password was not verified /// @@ -356,13 +356,13 @@ namespace SharpAESCrypt if (extensionLength != 0) { byte[] data = RepeatRead(m_stream, extensionLength); - int seperatorIndex = Array.IndexOf(data, 0); - if (seperatorIndex < 0) + int separatorIndex = Array.IndexOf(data, 0); + if (separatorIndex < 0) throw new InvalidDataException(Strings.InvalidExtensionData); - string key = System.Text.Encoding.UTF8.GetString(data, 0, seperatorIndex); - byte[] value = new byte[data.Length - seperatorIndex - 1]; - Array.Copy(data, seperatorIndex + 1, value, 0, value.Length); + string key = System.Text.Encoding.UTF8.GetString(data, 0, separatorIndex); + byte[] value = new byte[data.Length - separatorIndex - 1]; + Array.Copy(data, separatorIndex + 1, value, 0, value.Length); m_extensions.Add(new KeyValuePair(key, value)); } diff --git a/Duplicati/Library/Main/BackendWrapper.cs b/Duplicati/Library/Main/BackendWrapper.cs index 0c3dfa628..33d948154 100644 --- a/Duplicati/Library/Main/BackendWrapper.cs +++ b/Duplicati/Library/Main/BackendWrapper.cs @@ -95,7 +95,7 @@ namespace Duplicati.Library.Main /// The cache filename strategy used /// /// A cache filename strategy object - public static FilenameStrategy CreateCacheFilenameStrategy() { return new FilenameStrategy("dpl", "_", true); } + public static FilenameStrategy CreateCacheFilenameStrategy() { return new FilenameStrategy("dpl"); } /// /// The filename strategy used to generate and parse filenames @@ -442,7 +442,7 @@ namespace Duplicati.Library.Main m_statistics.LogWarning(string.Format(Strings.BackendWrapper.EmptyManifestWarning, me.Filename), null); foreach (ManifestEntry me2 in me.Incrementals) - if (me.Volumes.Count == 0) + if (me2.Volumes.Count == 0) m_statistics.LogWarning(string.Format(Strings.BackendWrapper.EmptyManifestWarning, me.Filename), null); } } @@ -648,7 +648,7 @@ namespace Duplicati.Library.Main { try { - m_statistics.NumberOfRemoteCalls++; + m_statistics.AddNumberOfRemoteCalls(1); return m_backend.List(); } catch (System.Threading.ThreadAbortException) @@ -678,7 +678,7 @@ namespace Duplicati.Library.Main { try { - m_statistics.NumberOfRemoteCalls++; + m_statistics.AddNumberOfRemoteCalls(1); m_backend.Delete(remote.Filename); lastEx = null; } @@ -742,7 +742,7 @@ namespace Duplicati.Library.Main else tempfile = new Duplicati.Library.Core.TempFile(filename); - m_statistics.NumberOfRemoteCalls++; + m_statistics.AddNumberOfRemoteCalls(1); if (m_backend is Duplicati.Library.Interface.IStreamingBackend && !m_options.DisableStreamingTransfers) { using (System.IO.FileStream fs = System.IO.File.Open(tempfile, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None)) @@ -830,7 +830,7 @@ namespace Duplicati.Library.Main else throw new Exception(string.Format(Strings.BackendWrapper.FileDownloadError, lastEx.Message), lastEx); - m_statistics.NumberOfBytesDownloaded += new System.IO.FileInfo(filename).Length; + m_statistics.AddBytesDownloaded(new System.IO.FileInfo(filename).Length); } private void PutInternal(BackupEntryBase remote, string filename) @@ -861,7 +861,7 @@ namespace Duplicati.Library.Main { try { - m_statistics.NumberOfRemoteCalls++; + m_statistics.AddNumberOfRemoteCalls(1); if (m_backend is Library.Interface.IStreamingBackend && !m_options.DisableStreamingTransfers) { #if DEBUG_THROTTLE @@ -929,7 +929,7 @@ namespace Duplicati.Library.Main if (!success) throw new Exception(string.Format(Strings.BackendWrapper.FileUploadError, lastEx == null ? "" : lastEx.Message), lastEx); - m_statistics.NumberOfBytesUploaded += new System.IO.FileInfo(filename).Length; + m_statistics.AddBytesUploaded(new System.IO.FileInfo(filename).Length); } finally { @@ -1125,20 +1125,30 @@ namespace Duplicati.Library.Main m_asyncTerminate = true; work = new List>(); - if (m_pendingOperations.Count > 1) + + if (m_pendingOperations.Count > 0) { while (m_pendingOperations.Count != 0) work.Add(m_pendingOperations.Dequeue()); - //The top entry is being completed by the thread + //The top entry is probably being completed by the thread m_pendingOperations.Enqueue(work[0]); - work.RemoveAt(0); } } + //Make sure the worker is awake to see the terminate message + m_asyncItemReady.Set(); + //When the thread completes, disable asynchronous transfers and return the unfinished work if (m_workerThread == null || !m_workerThread.IsAlive) { + if (m_workerException != null) + throw m_workerException; + + //If the thread did indeed complete the entry, remove it from the pending list + if (m_pendingOperations.Count == 0 && work.Count > 0) + work.RemoveAt(0); + m_async = false; return work; } diff --git a/Duplicati/Library/Main/CommunicationStatistics.cs b/Duplicati/Library/Main/CommunicationStatistics.cs index 97e8eab20..834b3af49 100644 --- a/Duplicati/Library/Main/CommunicationStatistics.cs +++ b/Duplicati/Library/Main/CommunicationStatistics.cs @@ -25,6 +25,7 @@ namespace Duplicati.Library.Main { public class CommunicationStatistics { + private object m_lock = new object(); private bool m_verboseErrors = false; private long m_numberOfBytesUploaded; private long m_numberOfRemoteCalls; @@ -45,31 +46,49 @@ namespace Duplicati.Library.Main public long NumberOfBytesUploaded { get { return m_numberOfBytesUploaded; } - set { m_numberOfBytesUploaded = value; } } public long NumberOfBytesDownloaded { get { return m_numberOfBytesDownloaded; } - set { m_numberOfBytesDownloaded = value; } } public long NumberOfRemoteCalls { get { return m_numberOfRemoteCalls; } - set { m_numberOfRemoteCalls = value; } + } + + public void AddBytesUploaded(long value) + { + lock (m_lock) + m_numberOfBytesUploaded += value; + } + + public void AddBytesDownloaded(long value) + { + lock (m_lock) + m_numberOfBytesDownloaded += value; + } + + public void AddNumberOfRemoteCalls(long value) + { + lock (m_lock) + m_numberOfRemoteCalls += value; } public void LogError(string errorMessage, Exception ex) { - m_numberOfErrors++; - m_errorMessages.AppendLine(errorMessage); - if (m_verboseErrors) - while (ex != null) - { - m_errorMessages.AppendLine(ex.ToString()); - ex = ex.InnerException; - } + lock (m_lock) + { + m_numberOfErrors++; + m_errorMessages.AppendLine(errorMessage); + if (m_verboseErrors) + while (ex != null) + { + m_errorMessages.AppendLine(ex.ToString()); + ex = ex.InnerException; + } + } } public override string ToString() @@ -101,14 +120,17 @@ namespace Duplicati.Library.Main public void LogWarning(string warningMessage, Exception ex) { - m_numberOfWarnings++; - m_warningMessages.AppendLine(warningMessage); - if (m_verboseErrors) - while (ex != null) - { - m_warningMessages.AppendLine(ex.ToString()); - ex = ex.InnerException; - } + lock (m_lock) + { + m_numberOfWarnings++; + m_warningMessages.AppendLine(warningMessage); + if (m_verboseErrors) + while (ex != null) + { + m_warningMessages.AppendLine(ex.ToString()); + ex = ex.InnerException; + } + } } } } diff --git a/Duplicati/Library/Main/FilenameStrategy.cs b/Duplicati/Library/Main/FilenameStrategy.cs index 9a7929094..1c4a4f1d3 100644 --- a/Duplicati/Library/Main/FilenameStrategy.cs +++ b/Duplicati/Library/Main/FilenameStrategy.cs @@ -33,7 +33,7 @@ namespace Duplicati.Library.Main //In Duplicati 1.0 there is only one manifest file, and it is called manifest or M in short mode //Issue# 58 introduced a backup manifest. Since 1.0 does not verify the manifest version number, - // the name manifest/M is not used, as that prevents 1.0 clients from reading the manifests and volumes. + // the name manifest/M is not used, which prevents 1.0 clients from reading the manifests and volumes. //The new names are manifestA and manifestB (A/B in short mode). //Future versions of Duplicati always verify the version number to avoid reading/writing data to a format // that is not supported. @@ -60,10 +60,15 @@ namespace Duplicati.Library.Main private const string VOLUME = "vol"; + //Note: Actually the K should be Z which is more correct as it is forced to be Z, but Z as a format specifier is fairly undocumented + private const string TIMESTAMP_FORMAT = "yyyyMMdd'T'HHmmssK"; + + private bool m_useOldFilenames; private bool m_useShortFilenames; - private string m_timeSeperator; + private string m_timeSeparator; private string m_prefix; + private Regex m_oldFilenameRegExp; private Regex m_filenameRegExp; private Regex m_shortRegExp; @@ -73,11 +78,17 @@ namespace Duplicati.Library.Main /// private Dictionary m_timeStringCache; - public FilenameStrategy(string prefix, string timeSeperator, bool useShortNames) + public FilenameStrategy(string prefix) + : this(prefix, null, false, false) + { + } + + public FilenameStrategy(string prefix, string timeSeparator, bool useShortNames, bool oldFilenames) { m_prefix = prefix; - m_timeSeperator = timeSeperator; + m_timeSeparator = timeSeparator; m_useShortFilenames = useShortNames; + m_useOldFilenames = oldFilenames; m_shortRegExp = new Regex( string.Format(@"(?{0})\-(?({1}|{2}|{3}|{4}|{5}))(?({6}|{7}))(?