diff --git a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.Designer.cs b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.Designer.cs index 952f240b7..44c6a0c44 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.Designer.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.Designer.cs @@ -22,23 +22,24 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup #region Component Designer generated code - /// - /// Required method for Designer support - do not modify + /// + /// 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(FinishedAdd)); - this.label1 = new System.Windows.Forms.Label(); this.Summary = new System.Windows.Forms.TextBox(); this.RunNow = new System.Windows.Forms.CheckBox(); + this.Tabs = new System.Windows.Forms.TabControl(); + this.TabSummary = new System.Windows.Forms.TabPage(); + this.TabCommandLine = new System.Windows.Forms.TabPage(); + this.CommandLine = new System.Windows.Forms.TextBox(); + this.Tabs.SuspendLayout(); + this.TabSummary.SuspendLayout(); + this.TabCommandLine.SuspendLayout(); this.SuspendLayout(); // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // // Summary // resources.ApplyResources(this.Summary, "Summary"); @@ -51,14 +52,45 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup this.RunNow.Name = "RunNow"; this.RunNow.UseVisualStyleBackColor = true; // + // Tabs + // + this.Tabs.Controls.Add(this.TabSummary); + this.Tabs.Controls.Add(this.TabCommandLine); + resources.ApplyResources(this.Tabs, "Tabs"); + this.Tabs.Name = "Tabs"; + this.Tabs.SelectedIndex = 0; + this.Tabs.SelectedIndexChanged += new System.EventHandler(this.Tabs_SelectedIndexChanged); + // + // TabSummary + // + this.TabSummary.Controls.Add(this.Summary); + resources.ApplyResources(this.TabSummary, "TabSummary"); + this.TabSummary.Name = "TabSummary"; + // + // TabCommandLine + // + this.TabCommandLine.Controls.Add(this.CommandLine); + resources.ApplyResources(this.TabCommandLine, "TabCommandLine"); + this.TabCommandLine.Name = "TabCommandLine"; + // + // CommandLine + // + resources.ApplyResources(this.CommandLine, "CommandLine"); + this.CommandLine.Name = "CommandLine"; + this.CommandLine.ReadOnly = true; + // // FinishedAdd // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.Tabs); this.Controls.Add(this.RunNow); - this.Controls.Add(this.Summary); - this.Controls.Add(this.label1); this.Name = "FinishedAdd"; + this.Tabs.ResumeLayout(false); + this.TabSummary.ResumeLayout(false); + this.TabSummary.PerformLayout(); + this.TabCommandLine.ResumeLayout(false); + this.TabCommandLine.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -66,8 +98,11 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup #endregion - private System.Windows.Forms.Label label1; public System.Windows.Forms.TextBox Summary; public System.Windows.Forms.CheckBox RunNow; + private System.Windows.Forms.TabControl Tabs; + private System.Windows.Forms.TabPage TabSummary; + private System.Windows.Forms.TabPage TabCommandLine; + public System.Windows.Forms.TextBox CommandLine; } } diff --git a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.cs b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.cs index 287966528..52552de73 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.cs @@ -26,6 +26,7 @@ using System.Text; using System.Windows.Forms; using System.Windows.Forms.Wizard; using Duplicati.Datamodel; +using Duplicati.Server; namespace Duplicati.GUI.Wizard_pages.Add_backup { @@ -115,6 +116,9 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup Summary.Text = sb.ToString(); args.TreatAsLast = true; + + CommandLine.Text = ""; + Tabs.SelectedTab = TabSummary; } public override string HelpText @@ -138,5 +142,141 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup return Strings.FinishedAdd.PageTitleModify; } } + + private string QuoteIfRequired(string input) + { + if (Library.Utility.Utility.IsClientLinux) + { + input = input.Replace("\\", "\\\\") + .Replace("$", "\\$") + .Replace("*", "\\*") + .Replace("?", "\\?") + .Replace("`", "\\`"); + } + + if (input.IndexOfAny(new char[] { ' ', '|', '&' }) >= 0) + { + if (!Library.Utility.Utility.IsClientLinux && input.EndsWith("\\")) + input += "\\"; + return '"' + input + '"'; + } + return input; + } + + private void Tabs_SelectedIndexChanged(object sender, EventArgs e) + { + // The CommandLine box is filled only on demand. + + if (Tabs.SelectedTab == TabCommandLine && CommandLine.TextLength == 0) + { + // Getting all options for the task + System.Data.LightDatamodel.IDataFetcherWithRelations con = new System.Data.LightDatamodel.DataFetcherNested(Program.DataConnection); + Schedule schedule = con.Add(); + m_wrapper.UpdateSchedule(schedule); + Dictionary options = new Dictionary(); + String target = new IncrementalBackupTask(schedule).GetConfiguration(options); + + List defaults = SettingOverrides.GetModuleOptions(m_wrapper, null); + defaults.AddRange(new Library.Main.Options(new Dictionary()).SupportedCommands); + + String source = schedule.Task.SourcePath; + if (source == "") + { + // We need to extract the paths of the "easy" folders + string[] sourceFolders = DynamicSetupHelper.GetSourceFolders(schedule.Task, new ApplicationSettings(schedule.Task.DataParent), new List>()); + source = String.Join(System.IO.Path.PathSeparator.ToString(), sourceFolders); + } + + // We have everything needed to build the Command line + System.Text.StringBuilder sb = new StringBuilder(); + sb.AppendLine("Command-line equivalent of this task:"); + sb.AppendLine(); + sb.Append(QuoteIfRequired(Application.ExecutablePath.Substring(0, Application.ExecutablePath.Length - 4) + ".CommandLine.exe")); + + // Filters are handled differently + options.Remove("filter"); + + //Remove all default values + foreach (Library.Interface.ICommandLineArgument arg in defaults) + { + string defvalue = arg.DefaultValue == null ? "" : arg.DefaultValue; + + if (options.ContainsKey(arg.Name) && (defvalue) == (options[arg.Name] == null ? "" : options[arg.Name])) + options.Remove(arg.Name); + + if (arg.Aliases != null) + foreach(string a in arg.Aliases) + if (options.ContainsKey(a) && (arg.DefaultValue ?? "") == (options[a] == null ? "" : options[a])) + options.Remove(a); + } + + //TODO: Should mask the connection password as well + if (options.ContainsKey("passphrase") && !string.IsNullOrEmpty(options["passphrase"])) + options["passphrase"] = "**********"; + + foreach (KeyValuePair i in options) + { + sb.Append(" --" + i.Key); + if (!string.IsNullOrEmpty(i.Value)) + sb.Append("=" + QuoteIfRequired(i.Value)); + } + + // Filters + foreach (Datamodel.TaskFilter filter in schedule.Task.SortedFilters) + { + sb.Append(" --"); + sb.Append(filter.Include ? "include" : "exclude"); + sb.Append(filter.GlobbingFilter.Length == 0 ? "-regexp" : ""); + sb.Append("="); + sb.Append(QuoteIfRequired(filter.GlobbingFilter.Length > 0 ? filter.GlobbingFilter : filter.Filter)); + } + + // Source and target + sb.Append(" BACKUP"); + sb.Append(" " + QuoteIfRequired(source)); + sb.Append(" " + QuoteIfRequired(target)); + + + options.Remove("passphrase"); + + if (!string.IsNullOrEmpty(m_wrapper.BackupExpireInterval)) + { + sb.AppendLine(); + sb.AppendLine(); + sb.Append(QuoteIfRequired(Application.ExecutablePath.Substring(0, Application.ExecutablePath.Length - 4) + ".CommandLine.exe")); + sb.Append(" delete-older-than "); + sb.Append(QuoteIfRequired(m_wrapper.BackupExpireInterval)); + + foreach (KeyValuePair i in options) + { + sb.Append(" --" + i.Key); + if (!string.IsNullOrEmpty(i.Value)) + sb.Append("=" + QuoteIfRequired(i.Value)); + } + + sb.Append(" " + QuoteIfRequired(target)); + } + + if (m_wrapper.MaxFullBackups > 0) + { + sb.AppendLine(); + sb.Append(QuoteIfRequired(Application.ExecutablePath.Substring(0, Application.ExecutablePath.Length - 4) + ".CommandLine.exe")); + sb.Append(" delete-all-but-n"); + sb.Append(" " + QuoteIfRequired(m_wrapper.MaxFullBackups.ToString())); + + foreach (KeyValuePair i in options) + { + sb.Append(" --" + i.Key); + if (!string.IsNullOrEmpty(i.Value)) + sb.Append("=" + QuoteIfRequired(i.Value)); + } + + sb.Append(" " + QuoteIfRequired(target)); + } + + CommandLine.Text = sb.ToString(); + } + } + } } diff --git a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.resx b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.resx index 9792d2bb1..7c2540b0d 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.resx +++ b/Duplicati/GUI/Wizard pages/Add backup/FinishedAdd.resx @@ -112,55 +112,31 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - True - - - - 24, 16 - - - 50, 13 - - - 0 - - - Summary - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 + + + Fill + Courier New, 8.25pt - 24, 40 + 3, 3 + True - Both - 456, 152 + 450, 146 1 @@ -169,13 +145,13 @@ Summary - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + TabSummary - 1 + 0 True @@ -196,15 +172,123 @@ RunNow - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 $this + 1 + + + 4, 22 + + + 3, 3, 3, 3 + + + 456, 152 + + 0 - + + Summary + + + TabSummary + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Tabs + + + 0 + + + Fill + + + Courier New, 8.25pt + + + 3, 3 + + + True + + + Both + + + 450, 146 + + + 2 + + + CommandLine + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + TabCommandLine + + + 0 + + + 4, 22 + + + 3, 3, 3, 3 + + + 456, 152 + + + 1 + + + Command Line + + + TabCommandLine + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Tabs + + + 1 + + + 21, 16 + + + 464, 178 + + + 3 + + + Tabs + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + True diff --git a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs index ae6ddef5e..352ce41b2 100644 --- a/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs +++ b/Duplicati/GUI/Wizard pages/Add backup/SettingOverrides.cs @@ -64,6 +64,55 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup } } + public static List GetModuleOptions(WizardSettingsWrapper wrapper, Control parent) + { + List res = new List(); + try + { + res.AddRange(Library.DynamicLoader.BackendLoader.GetSupportedCommands(wrapper.Backend)); + } + catch (Exception ex) + { + if (parent != null) + MessageBox.Show(parent, string.Format(Strings.SettingOverrides.BackendLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + + try + { + res.AddRange(Library.DynamicLoader.EncryptionLoader.GetSupportedCommands(wrapper.EncryptionModule)); + } + catch (Exception ex) + { + if (parent != null) + MessageBox.Show(parent, string.Format(Strings.SettingOverrides.EncryptionLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + try + { + res.AddRange(Library.DynamicLoader.CompressionLoader.GetSupportedCommands(wrapper.CompressionModule)); + } + catch (Exception ex) + { + if (parent != null) + MessageBox.Show(parent, string.Format(Strings.SettingOverrides.CompressionLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + try + { + foreach (Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules) + if (m.SupportedCommands != null) + res.AddRange(m.SupportedCommands); + } + catch (Exception ex) + { + if (parent != null) + MessageBox.Show(parent, string.Format(Strings.SettingOverrides.GenericModuleLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + return res; + } + void SettingOverrides_PageEnter(object sender, System.Windows.Forms.Wizard.PageChangedArgs args) { if (!OptionGrid.Unsupported) @@ -73,46 +122,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup if (!m_settings.ContainsKey("Overrides:Table")) { IList primary = new Library.Main.Options(new Dictionary()).SupportedCommands; - List secondary = new List(); - - try - { - secondary.AddRange(Library.DynamicLoader.BackendLoader.GetSupportedCommands(m_wrapper.Backend)); - } - catch (Exception ex) - { - MessageBox.Show(this, string.Format(Strings.SettingOverrides.BackendLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - - try - { - secondary.AddRange(Library.DynamicLoader.EncryptionLoader.GetSupportedCommands(m_wrapper.EncryptionModule)); - } - catch (Exception ex) - { - MessageBox.Show(this, string.Format(Strings.SettingOverrides.EncryptionLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - try - { - secondary.AddRange(Library.DynamicLoader.CompressionLoader.GetSupportedCommands(m_wrapper.CompressionModule)); - } - catch (Exception ex) - { - MessageBox.Show(this, string.Format(Strings.SettingOverrides.CompressionLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - try - { - foreach(Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules) - if (m.SupportedCommands != null) - secondary.AddRange(m.SupportedCommands); - } - catch (Exception ex) - { - MessageBox.Show(this, string.Format(Strings.SettingOverrides.GenericModuleLoadError, ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } + IList secondary = GetModuleOptions(m_wrapper, this); OptionGrid.Setup(primary, secondary, m_wrapper.Overrides);