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
This commit is contained in:
kenneth.skovhede@gmail.com
2010-09-25 12:02:14 +00:00
parent 31eadfddd2
commit b81d63ea73
74 changed files with 735 additions and 998 deletions
-12
View File
@@ -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")
-9
View File
@@ -201,15 +201,6 @@ namespace Duplicati.CommandLine.Strings {
}
}
/// <summary>
/// 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 &apos;. Use the commandline option --time-separator=&quot;:&quot; to prevent this from happening..
/// </summary>
internal static string SettingDefaultTimeSeperatorWarning {
get {
return ResourceManager.GetString("SettingDefaultTimeSeperatorWarning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Supported backends:.
/// </summary>
@@ -163,9 +163,6 @@
<data name="NewOrModifiedFilesHeader" xml:space="preserve">
<value>New/Modified files</value>
</data>
<data name="SettingDefaultTimeSeperatorWarning" xml:space="preserve">
<value>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.</value>
</data>
<data name="SupportedBackendsHeader" xml:space="preserve">
<value>Supported backends:</value>
</data>
+9 -7
View File
@@ -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<Duplicati.Library.Main.ManifestEntry> 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<Duplicati.Library.Main.ManifestEntry> t = new List<Duplicati.Library.Main.ManifestEntry>();
t.Add(entries[0]);
@@ -235,8 +237,8 @@ namespace Duplicati.CommandLine
/// <param name="f2">Another folder</param>
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<string> folders1 = Utility.EnumerateFolders(f1);
List<string> folders2 = Utility.EnumerateFolders(f2);
+1 -1
View File
@@ -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);
}
}
}
-1
View File
@@ -8,5 +8,4 @@
<BackupTimeOffset>13h</BackupTimeOffset>
<EncodedFilters>e:.*\\Thumbs.db</EncodedFilters>
<IncludeSetup>true</IncludeSetup>
<FileTimeSeperator>'</FileTimeSeperator>
</settings>
@@ -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';
@@ -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';
+1 -1
View File
@@ -106,4 +106,4 @@ CREATE TABLE "EncryptionSetting" (
"Value" TEXT NULL
);
INSERT INTO "Version" ("Version") VALUES (5);
INSERT INTO "Version" ("Version") VALUES (6);
-21
View File
@@ -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]); }
+11 -21
View File
@@ -307,7 +307,6 @@
<Compile Include="ThrottleControl.Designer.cs">
<DependentUpon>ThrottleControl.cs</DependentUpon>
</Compile>
<Compile Include="UrlUtillity.cs" />
<Compile Include="Wizard pages\Add backup\AdvancedOptions.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -332,12 +331,6 @@
<Compile Include="Wizard pages\Add backup\FinishedAdd.Designer.cs">
<DependentUpon>FinishedAdd.cs</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Add backup\GeneratedFilenameOptions.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Wizard pages\Add backup\GeneratedFilenameOptions.Designer.cs">
<DependentUpon>GeneratedFilenameOptions.cs</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Add backup\SettingOverrides.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -499,21 +492,21 @@
<Compile Include="Wizard pages\Restore\FinishedRestore.Designer.cs">
<DependentUpon>FinishedRestore.cs</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Restore\SelectBackup.cs">
<Compile Include="Wizard pages\Restore\SelectBackupVersion.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Wizard pages\Restore\SelectBackup.Designer.cs">
<DependentUpon>SelectBackup.cs</DependentUpon>
<Compile Include="Wizard pages\Restore\SelectBackupVersion.Designer.cs">
<DependentUpon>SelectBackupVersion.cs</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Restore\Strings\FinishedRestore.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>FinishedRestore.resx</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Restore\Strings\SelectBackup.Designer.cs">
<Compile Include="Wizard pages\Restore\Strings\SelectBackupVersion.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>SelectBackup.resx</DependentUpon>
<DependentUpon>SelectBackupVersion.resx</DependentUpon>
</Compile>
<Compile Include="Wizard pages\Restore\Strings\TargetFolder.Designer.cs">
<AutoGen>True</AutoGen>
@@ -775,9 +768,9 @@
<SubType>Designer</SubType>
<DependentUpon>FinishedRestore.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Restore\SelectBackup.resx">
<EmbeddedResource Include="Wizard pages\Restore\SelectBackupVersion.resx">
<SubType>Designer</SubType>
<DependentUpon>SelectBackup.cs</DependentUpon>
<DependentUpon>SelectBackupVersion.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Restore\TargetFolder.resx">
<SubType>Designer</SubType>
@@ -928,10 +921,6 @@
<EmbeddedResource Include="ThrottleControl.resx">
<DependentUpon>ThrottleControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Add backup\GeneratedFilenameOptions.resx">
<SubType>Designer</SubType>
<DependentUpon>GeneratedFilenameOptions.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Add backup\SettingOverrides.resx">
<SubType>Designer</SubType>
<DependentUpon>SettingOverrides.cs</DependentUpon>
@@ -1015,10 +1004,10 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>FinishedRestore.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Restore\Strings\SelectBackup.resx">
<EmbeddedResource Include="Wizard pages\Restore\Strings\SelectBackupVersion.resx">
<SubType>Designer</SubType>
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SelectBackup.Designer.cs</LastGenOutput>
<LastGenOutput>SelectBackupVersion.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Wizard pages\Restore\Strings\TargetFolder.resx">
<SubType>Designer</SubType>
@@ -1132,7 +1121,8 @@
<EmbeddedResource Include="Wizard pages\Backends\RawContainer.resx">
<DependentUpon>RawContainer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Database schema\5.Remove signaturekey.sql" />
<EmbeddedResource Include="Database schema\5. Remove signaturekey.sql" />
<EmbeddedResource Include="Database schema\6. Remove TimeSeparator and UseShortFilenames.sql" />
<None Include="Resources\Play.png" />
<None Include="Resources\Delay.png" />
<None Include="Resources\Pause.png" />
+108 -125
View File
@@ -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<KeyValuePair<bool, string>> filters = new List<KeyValuePair<bool, string>>();
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<KeyValuePair<bool, string>> filters = new List<KeyValuePair<bool, string>>();
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<string> res = new List<string>();
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<string>(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<string> res = new List<string>();
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<string>(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
{
+7 -7
View File
@@ -88,8 +88,8 @@ namespace Duplicati.GUI
private static string[] PrependFilterList(string[] sourceFolders, ApplicationSettings settings, List<KeyValuePair<bool, string>> 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
/// <returns>The source folder string</returns>
private static string[] GetSourceFolders(bool includeDocuments, bool includeMusic, bool includeImages, bool includeDesktop, bool includeSettings, ApplicationSettings settings, List<KeyValuePair<bool, string>> 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<string> folders = new List<string>();
List<string> exfolders = new List<string>();
@@ -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]);
}
+1
View File
@@ -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);
//
+26 -2
View File
@@ -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)
@@ -121,6 +121,12 @@
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="viewFilesToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>160, 22</value>
</data>
<data name="viewFilesToolStripMenuItem.Text" xml:space="preserve">
<value>View contents ...</value>
</data>
<data name="contextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
<value>161, 26</value>
</data>
@@ -130,12 +136,6 @@
<data name="&gt;&gt;contextMenuStrip.Type" xml:space="preserve">
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="viewFilesToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>160, 22</value>
</data>
<data name="viewFilesToolStripMenuItem.Text" xml:space="preserve">
<value>View contents ...</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="statusLabel.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
+3 -3
View File
@@ -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)
+5 -5
View File
@@ -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
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
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);
}
}
@@ -63,7 +63,7 @@ namespace Duplicati.GUI.HelperControls.Strings {
/// <summary>
/// Looks up a localized string similar to Value type: {0}.
///{1}.
///{2}..
///{2}.
/// </summary>
internal static string InfoLabelFormat {
get {
@@ -120,7 +120,7 @@
<data name="InfoLabelFormat" xml:space="preserve">
<value>Value type: {0}.
{1}.
{2}.</value>
{2}</value>
</data>
<data name="PageNotSupportedWarning" xml:space="preserve">
<value>This page is not supported on the current platform, this is a known issue.
+11 -5
View File
@@ -41,7 +41,7 @@ namespace Duplicati.GUI
/// <summary>
/// Gets the folder where Duplicati data is stored
/// </summary>
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('"')); } }
/// <summary>
/// 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);
}
}
}
-6
View File
@@ -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;
}
@@ -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;
}
}
@@ -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());
@@ -144,7 +144,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;SelectWhen.ZOrder" xml:space="preserve">
<value>6</value>
<value>5</value>
</data>
<data name="SelectCleanup.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -171,7 +171,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;SelectCleanup.ZOrder" xml:space="preserve">
<value>5</value>
<value>4</value>
</data>
<data name="ThrottleOptions.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -198,7 +198,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;ThrottleOptions.ZOrder" xml:space="preserve">
<value>4</value>
<value>3</value>
</data>
<data name="EditFilters.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -225,7 +225,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;EditFilters.ZOrder" xml:space="preserve">
<value>3</value>
<value>2</value>
</data>
<data name="IncludeDuplicatiSetup.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -252,49 +252,22 @@
<value>$this</value>
</data>
<data name="&gt;&gt;IncludeDuplicatiSetup.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="EditVolumeFilenames.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="EditVolumeFilenames.Location" type="System.Drawing.Point, System.Drawing">
<value>32, 136</value>
</data>
<data name="EditVolumeFilenames.Size" type="System.Drawing.Size, System.Drawing">
<value>369, 17</value>
</data>
<data name="EditVolumeFilenames.TabIndex" type="System.Int32, mscorlib">
<value>6</value>
</data>
<data name="EditVolumeFilenames.Text" xml:space="preserve">
<value>Change the generated names for files stored on the backend (advanced)</value>
</data>
<data name="&gt;&gt;EditVolumeFilenames.Name" xml:space="preserve">
<value>EditVolumeFilenames</value>
</data>
<data name="&gt;&gt;EditVolumeFilenames.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;EditVolumeFilenames.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;EditVolumeFilenames.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="EditOverrides.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="EditOverrides.Location" type="System.Drawing.Point, System.Drawing">
<value>32, 168</value>
<value>32, 152</value>
</data>
<data name="EditOverrides.Size" type="System.Drawing.Size, System.Drawing">
<value>228, 17</value>
<value>205, 17</value>
</data>
<data name="EditOverrides.TabIndex" type="System.Int32, mscorlib">
<value>7</value>
</data>
<data name="EditOverrides.Text" xml:space="preserve">
<value>Manually override settings (very advanced)</value>
<value>Manually override settings (advanced)</value>
</data>
<data name="&gt;&gt;EditOverrides.Name" xml:space="preserve">
<value>EditOverrides</value>
@@ -1,94 +0,0 @@
namespace Duplicati.GUI.Wizard_pages.Add_backup
{
partial class GeneratedFilenameOptions
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}
@@ -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<Datamodel.Schedule>(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;
}
}
}
@@ -1,272 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>40, 24</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>92, 13</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>File time seperator</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
</data>
<data name="&gt;&gt;label1.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>4</value>
</data>
<data name="FilePrefixEnabled.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="FilePrefixEnabled.Location" type="System.Drawing.Point, System.Drawing">
<value>24, 56</value>
</data>
<data name="FilePrefixEnabled.Size" type="System.Drawing.Size, System.Drawing">
<value>133, 17</value>
</data>
<data name="FilePrefixEnabled.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="FilePrefixEnabled.Text" xml:space="preserve">
<value>Change filename prefix</value>
</data>
<data name="&gt;&gt;FilePrefixEnabled.Name" xml:space="preserve">
<value>FilePrefixEnabled</value>
</data>
<data name="&gt;&gt;FilePrefixEnabled.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;FilePrefixEnabled.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;FilePrefixEnabled.ZOrder" xml:space="preserve">
<value>3</value>
</data>
<data name="UseShortFilenames.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="UseShortFilenames.Location" type="System.Drawing.Point, System.Drawing">
<value>24, 88</value>
</data>
<data name="UseShortFilenames.Size" type="System.Drawing.Size, System.Drawing">
<value>118, 17</value>
</data>
<data name="UseShortFilenames.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="UseShortFilenames.Text" xml:space="preserve">
<value>Use short filenames</value>
</data>
<data name="&gt;&gt;UseShortFilenames.Name" xml:space="preserve">
<value>UseShortFilenames</value>
</data>
<data name="&gt;&gt;UseShortFilenames.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;UseShortFilenames.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;UseShortFilenames.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="FilePrefix.Enabled" type="System.Boolean, mscorlib">
<value>False</value>
</data>
<data name="FilePrefix.Location" type="System.Drawing.Point, System.Drawing">
<value>168, 56</value>
</data>
<data name="FilePrefix.Size" type="System.Drawing.Size, System.Drawing">
<value>128, 20</value>
</data>
<data name="FilePrefix.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="&gt;&gt;FilePrefix.Name" xml:space="preserve">
<value>FilePrefix</value>
</data>
<data name="&gt;&gt;FilePrefix.Type" xml:space="preserve">
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;FilePrefix.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;FilePrefix.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="FileTimeSeperator.Font" type="System.Drawing.Font, System.Drawing">
<value>Courier New, 8.25pt</value>
</data>
<data name="FileTimeSeperator.Items" xml:space="preserve">
<value>'</value>
</data>
<data name="FileTimeSeperator.Items1" xml:space="preserve">
<value>:</value>
</data>
<data name="FileTimeSeperator.Items2" xml:space="preserve">
<value>_</value>
</data>
<data name="FileTimeSeperator.Location" type="System.Drawing.Point, System.Drawing">
<value>168, 24</value>
</data>
<data name="FileTimeSeperator.Size" type="System.Drawing.Size, System.Drawing">
<value>56, 22</value>
</data>
<data name="FileTimeSeperator.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="&gt;&gt;FileTimeSeperator.Name" xml:space="preserve">
<value>FileTimeSeperator</value>
</data>
<data name="&gt;&gt;FileTimeSeperator.Type" xml:space="preserve">
<value>System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;FileTimeSeperator.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;FileTimeSeperator.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
<value>506, 242</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>GeneratedFilenameOptions</value>
</data>
<data name="&gt;&gt;$this.Type" xml:space="preserve">
<value>System.Windows.Forms.Wizard.WizardControl, System.Windows.Forms.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ae51c3db610c5381</value>
</data>
</root>
@@ -55,11 +55,11 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup
InitializeComponent();
m_sizes = new Dictionary<string, long>(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<KeyValuePair<bool, string>> filters = Library.Core.FilenameFilter.DecodeFilter(m_wrapper.EncodedFilters);
//See what folders are included with the current setup
@@ -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<Datamodel.Schedule>(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)
@@ -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;
+1 -1
View File
@@ -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&currency_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&currency_code=EUR&lc=DK&bn=PP%2dDonationsBF&charset=UTF%2d8");
}
private void donate_link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
@@ -1,6 +1,6 @@
namespace Duplicati.GUI.Wizard_pages.Restore
{
partial class SelectBackup
partial class SelectBackupVersion
{
/// <summary>
/// Required designer variable.
@@ -28,7 +28,7 @@ namespace Duplicati.GUI.Wizard_pages.Restore
/// </summary>
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();
@@ -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<Schedule>(m_wrapper.ScheduleID));
BackupList.Setup(m_wrapper.DataConnection.GetObjectById<Schedule>(m_wrapper.ScheduleID));
}
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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() {
}
/// <summary>
@@ -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;
@@ -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
+14 -3
View File
@@ -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();
+36 -16
View File
@@ -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;
}
}
+21 -10
View File
@@ -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<Schedule>(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)
+58 -4
View File
@@ -163,7 +163,7 @@
<value>0, 17</value>
</data>
<data name="BackupList.Size" type="System.Drawing.Size, System.Drawing">
<value>432, 127</value>
<value>432, 111</value>
</data>
<data name="BackupList.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
@@ -187,7 +187,7 @@
<value>0, 56</value>
</data>
<data name="panel1.Size" type="System.Drawing.Size, System.Drawing">
<value>432, 144</value>
<value>432, 128</value>
</data>
<data name="panel1.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
@@ -204,6 +204,60 @@
<data name="&gt;&gt;panel1.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="ShowAdvanced.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="ShowAdvanced.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="ShowAdvanced.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 4</value>
</data>
<data name="ShowAdvanced.Size" type="System.Drawing.Size, System.Drawing">
<value>141, 17</value>
</data>
<data name="ShowAdvanced.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="ShowAdvanced.Text" xml:space="preserve">
<value>Show advanced options</value>
</data>
<data name="&gt;&gt;ShowAdvanced.Name" xml:space="preserve">
<value>ShowAdvanced</value>
</data>
<data name="&gt;&gt;ShowAdvanced.Type" xml:space="preserve">
<value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ShowAdvanced.Parent" xml:space="preserve">
<value>ShowAdvancedPanel</value>
</data>
<data name="&gt;&gt;ShowAdvanced.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="ShowAdvancedPanel.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Bottom</value>
</data>
<data name="ShowAdvancedPanel.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 184</value>
</data>
<data name="ShowAdvancedPanel.Size" type="System.Drawing.Size, System.Drawing">
<value>432, 24</value>
</data>
<data name="ShowAdvancedPanel.TabIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="&gt;&gt;ShowAdvancedPanel.Name" xml:space="preserve">
<value>ShowAdvancedPanel</value>
</data>
<data name="&gt;&gt;ShowAdvancedPanel.Type" xml:space="preserve">
<value>System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;ShowAdvancedPanel.Parent" xml:space="preserve">
<value>ExpanderPanel</value>
</data>
<data name="&gt;&gt;ShowAdvancedPanel.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="DirectRestore.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
@@ -286,13 +340,13 @@
<value>ExpanderPanel</value>
</data>
<data name="&gt;&gt;RestoreOptions.ZOrder" xml:space="preserve">
<value>1</value>
<value>2</value>
</data>
<data name="ExpanderPanel.Location" type="System.Drawing.Point, System.Drawing">
<value>32, 8</value>
</data>
<data name="ExpanderPanel.Size" type="System.Drawing.Size, System.Drawing">
<value>432, 200</value>
<value>432, 208</value>
</data>
<data name="ExpanderPanel.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
+11 -1
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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);
}
}
/// <summary>
/// Looks up a localized string similar to Do you need to modify advanced settings?
///(Most users do not need this).
/// </summary>
internal static string ShowAdvancedQuestion {
get {
return ResourceManager.GetString("ShowAdvancedQuestion", resourceCulture);
}
}
}
}
@@ -126,4 +126,8 @@
<data name="PageTitle" xml:space="preserve">
<value>Welcome to Duplicati</value>
</data>
<data name="ShowAdvancedQuestion" xml:space="preserve">
<value>Do you need to modify advanced settings?
(Most users do not need this)</value>
</data>
</root>
+1 -1
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
@@ -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
}
/// <summary>
/// A prefix to the volume filename
/// True if advanced restore options should be displayed
/// </summary>
public string FilePrefix
public bool ShowAdvancedRestoreOptions
{
get { return GetItem<string>("FilePrefix", ""); }
set { SetItem("FilePrefix", value); }
}
/// <summary>
/// The character used to seperate time digits in the filename
/// </summary>
public string FileTimeSeperator
{
get { return GetItem<string>("FileTimeSeperator", ":"); }
set { SetItem("FileTimeSeperator", value); }
}
/// <summary>
/// True if the filenames generated should be short
/// </summary>
public bool ShortFilenames
{
get { return GetItem<bool>("ShortFilenames", false); }
set { SetItem("ShortFilenames", value); }
get { return GetItem<bool>("ShowAdvancedRestoreOptions", false); }
set { SetItem("ShowAdvancedRestoreOptions", value); }
}
/// <summary>
@@ -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)
@@ -60,9 +60,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\GUI\UrlUtillity.cs">
<Link>UrlUtillity.cs</Link>
</Compile>
<Compile Include="CloudFiles.cs" />
<Compile Include="CloudFilesUI.cs">
<SubType>UserControl</SubType>
@@ -66,9 +66,6 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\GUI\UrlUtillity.cs">
<Link>UrlUtillity.cs</Link>
</Compile>
<Compile Include="S3Backend.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="S3CommonOptions.cs">
+1 -1
View File
@@ -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)
@@ -38,7 +38,7 @@ namespace Duplicati.Library.Compression
/// <param name="basefolder">The folder to base the archive on</param>
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
}
/// <summary>
/// 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
/// </summary>
/// <param name="prefix">An optional prefix that is used to filter the list</param>
/// <returns>A filtered list of entries</returns>
@@ -83,7 +83,7 @@ namespace Duplicati.Library.Compression
/// <summary>
/// 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.
/// </summary>
/// <param name="path">The path to convert in internal format</param>
/// <returns>The path in filesystem format</returns>
@@ -97,7 +97,7 @@ namespace Duplicati.Library.Compression
/// <summary>
/// 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.
/// </summary>
/// <param name="path">The path to convert in filesystem format</param>
/// <returns>The path in the internal format</returns>
@@ -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;
@@ -105,6 +105,7 @@
<Compile Include="TempFolder.cs" />
<Compile Include="ThrottledStream.cs" />
<Compile Include="Timeparser.cs" />
<Compile Include="UrlUtillity.cs" />
<Compile Include="Utility.cs" />
</ItemGroup>
<ItemGroup>
+6 -6
View File
@@ -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<bool, string>(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<string> FilterList(string basepath, IEnumerable<string> filenames)
{
basepath = Core.Utility.AppendDirSeperator(basepath);
basepath = Core.Utility.AppendDirSeparator(basepath);
List<string> included = new List<string>();
foreach (string s in filenames)
+3 -3
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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 {
/// <summary>
/// Looks up a localized string similar to Filter contains: {0}.
/// </summary>
internal static string FilterContainsPathSeperator {
internal static string FilterContainsPathSeparator {
get {
return ResourceManager.GetString("FilterContainsPathSeperator", resourceCulture);
return ResourceManager.GetString("FilterContainsPathSeparator", resourceCulture);
}
}
}
@@ -117,7 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="FilterContainsPathSeperator" xml:space="preserve">
<data name="FilterContainsPathSeparator" xml:space="preserve">
<value>Filter contains: {0}</value>
</data>
</root>
+1 -1
View File
@@ -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);
}
+2 -2
View File
@@ -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;
@@ -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
{
/// <summary>
/// The file path to the system browser selected
/// </summary>
public static string SystemBrowser = null;
/// <summary>
/// A delegate for handing error messages
/// </summary>
/// <param name="errormessage">The message to display the error for</param>
public delegate void ErrorHandlerDelegate(string errormessage);
/// <summary>
/// The errorhandler callback method
/// </summary>
public static ErrorHandlerDelegate ErrorHandler;
/// <summary>
/// Opens the given URL in a browser
/// </summary>
/// <param name="url">The url to open, must start with http:// or https://</param>
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));
}
}
+15 -10
View File
@@ -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.
/// </summary>
/// <param name="basepath">The folder to look in.</param>
/// <returns>A list of the full filenames and foldernames. Foldernames ends with the directoryseperator char</returns>
/// <returns>A list of the full filenames and foldernames. Foldernames ends with the directoryseparator char</returns>
public static List<string> EnumerateFileSystemEntries(string basepath)
{
return EnumerateFileSystemEntries(basepath, null);
@@ -249,7 +249,7 @@ namespace Duplicati.Library.Core
/// </summary>
/// <param name="basepath">The folder to look in.</param>
/// <param name="filter">An optional filter to apply to the filenames</param>
/// <returns>A list of the full filenames and foldernames. Foldernames ends with the directoryseperator char</returns>
/// <returns>A list of the full filenames and foldernames. Foldernames ends with the directoryseparator char</returns>
public static List<string> EnumerateFileSystemEntries(string basepath, FilenameFilter filter)
{
PathCollector c = new PathCollector(true, true);
@@ -272,15 +272,20 @@ namespace Duplicati.Library.Core
}
/// <summary>
/// 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
/// </summary>
public static readonly string DirectorySeparatorString = System.IO.Path.DirectorySeparatorChar.ToString();
/// <summary>
/// Appends the appropriate directory separator to paths, depending on OS.
/// Does not append the separator if the path already ends with it.
/// </summary>
/// <param name="path">The path to append to</param>
/// <returns>The path with the directory seperator appended</returns>
public static string AppendDirSeperator(string path)
/// <returns>The path with the directory separator appended</returns>
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;
}
@@ -155,7 +155,7 @@ namespace SharpAESCrypt
/// <summary>
/// An exception message that indicates that an extension had an invalid format
/// </summary>
public static string InvalidExtensionData = "Invalid extension data, seperator (0x00) not found";
public static string InvalidExtensionData = "Invalid extension data, separator (0x00) not found";
/// <summary>
/// An exception message that indicates that the format was accepted, but the password was not verified
/// </summary>
@@ -356,13 +356,13 @@ namespace SharpAESCrypt
if (extensionLength != 0)
{
byte[] data = RepeatRead(m_stream, extensionLength);
int seperatorIndex = Array.IndexOf<byte>(data, 0);
if (seperatorIndex < 0)
int separatorIndex = Array.IndexOf<byte>(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<string, byte[]>(key, value));
}
+21 -11
View File
@@ -95,7 +95,7 @@ namespace Duplicati.Library.Main
/// The cache filename strategy used
/// </summary>
/// <returns>A cache filename strategy object</returns>
public static FilenameStrategy CreateCacheFilenameStrategy() { return new FilenameStrategy("dpl", "_", true); }
public static FilenameStrategy CreateCacheFilenameStrategy() { return new FilenameStrategy("dpl"); }
/// <summary>
/// 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 ? "<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<KeyValuePair<BackupEntryBase, string>>();
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;
}
@@ -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;
}
}
}
}
}
+72 -19
View File
@@ -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
/// </summary>
private Dictionary<DateTime, string> 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(@"(?<prefix>{0})\-(?<type>({1}|{2}|{3}|{4}|{5}))(?<inc>({6}|{7}))(?<time>([A-F]|[a-f]|[0-9])+)\.(?<volumegroup>{8}(?<volumenumber>\d+)\.)?(?<extension>.+)",
@@ -92,8 +103,17 @@ namespace Duplicati.Library.Main
VOLUME
)
);
m_filenameRegExp = new Regex(
string.Format(@"(?<prefix>{0})\-(?<inc>({1}|{2}))\-(?<type>({3}|{4}|{5}|{6}|{7}))\.(?<time>\d{10}\-\d{11}\-\d{11}.\d{11}{9}\d{11}{9}\d{11}(?<timezone>([\+\-]\d{11}{9}\d{11})|Z)?)\.(?<volumegroup>{8}(?<volumenumber>\d+)\.)?(?<extension>.+)",
//As we the --time-separator is now deprecated, we must guess what was used
string timeSepRegEx;
if (m_timeSeparator == null)
timeSepRegEx = "."; //We accept any character
else
timeSepRegEx = Regex.Escape(m_timeSeparator);
m_oldFilenameRegExp = new Regex(
string.Format(@"(?<prefix>{0})\-(?<inc>({1}|{2}))\-(?<type>({3}|{4}|{5}|{6}|{7}))\.(?<time>\d{10}\-\d{11}\-\d{11}.\d{11}(?<timeseparator>{9})\d{11}{9}\d{11}(?<timezone>([\+\-]\d{11}{9}\d{11})|Z)?)\.(?<volumegroup>{8}(?<volumenumber>\d+)\.)?(?<extension>.+)",
Regex.Escape(m_prefix),
FULL,
INCREMENTAL,
@@ -103,19 +123,33 @@ namespace Duplicati.Library.Main
MANIFEST_A,
MANIFEST_B,
VOLUME,
Regex.Escape(timeSeperator),
timeSepRegEx,
"{4}", //We need to insert it because it gets replaced by string.Format
"{2}" //Same as above
)
);
//The short filenames are UTC so there is no timezone attached
if (!m_useShortFilenames)
m_filenameRegExp = new Regex(
string.Format(@"(?<prefix>{0})\-(?<inc>({1}|{2}))\-(?<type>({3}|{4}|{5}|{6}|{7}))\.(?<time>{9})\.(?<volumegroup>{8}(?<volumenumber>\d+)\.)?(?<extension>.+)",
Regex.Escape(m_prefix),
FULL,
INCREMENTAL,
CONTENT,
SIGNATURE,
MANIFEST_OLD,
MANIFEST_A,
MANIFEST_B,
VOLUME,
@"\d{8}T\d{6}Z" //Timestamp format is YYYYMMDDTHHMMSSZ
)
);
//The short filenames and new filenames are UTC so there is no timezone attached
if (!m_useShortFilenames && m_useOldFilenames)
m_timeStringCache = new Dictionary<DateTime, string>();
}
public FilenameStrategy(Options options)
: this(options.BackupPrefix, options.TimeSeperatorChar, options.UseShortFilenames)
: this(options.BackupPrefix, options.TimeSeparatorChar, options.UseShortFilenames, options.UseOldFilenames)
{
}
@@ -134,18 +168,26 @@ namespace Duplicati.Library.Main
throw new Exception(string.Format(Strings.FilenameStrategy.InvalidEntryTypeError, type));
string filename;
if (!m_useShortFilenames)
if (m_useShortFilenames)
{
//Make sure the same DateTime is always the same string
if (!m_timeStringCache.ContainsKey(type.Time))
m_timeStringCache[type.Time] = type.Time.ToString("yyyy-MM-ddTHH:mm:ssK");
string datetime = m_timeStringCache[type.Time].Replace(":", m_timeSeperator);
filename = m_prefix + "-" + (type.IsFull ? FULL : INCREMENTAL) + "-" + t + "." + datetime;
filename = m_prefix + "-" + t + (type.IsFull ? FULL_SHORT : INCREMENTAL_SHORT) + (type.Time.ToUniversalTime().Ticks / TimeSpan.TicksPerSecond).ToString("X");
}
else
{
filename = m_prefix + "-" + t + (type.IsFull ? FULL_SHORT : INCREMENTAL_SHORT) + (type.Time.ToUniversalTime().Ticks / TimeSpan.TicksPerSecond).ToString("X");
string datetime;
if (m_useOldFilenames)
{
//Make sure the same DateTime is always the same string
if (!m_timeStringCache.ContainsKey(type.Time))
m_timeStringCache[type.Time] = type.Time.ToString("yyyy-MM-ddTHH:mm:ssK");
datetime = m_timeStringCache[type.Time].Replace(":", m_timeSeparator ?? (Core.Utility.IsClientLinux ? ":" : "'"));
}
else
{
datetime = type.Time.ToUniversalTime().ToString(TIMESTAMP_FORMAT);
}
filename = m_prefix + "-" + (type.IsFull ? FULL : INCREMENTAL) + "-" + t + "." + datetime;
}
if (type is ManifestEntry)
@@ -156,9 +198,15 @@ namespace Duplicati.Library.Main
public BackupEntryBase ParseFilename(Duplicati.Library.Interface.IFileEntry fe)
{
bool oldFilename = false;
Match m = m_filenameRegExp.Match(fe.Name);
if (!m.Success)
m = m_shortRegExp.Match(fe.Name);
if (!m.Success)
{
m = m_oldFilenameRegExp.Match(fe.Name);
oldFilename = true;
}
if (!m.Success)
return null;
if (m.Value != fe.Name)
@@ -171,7 +219,12 @@ namespace Duplicati.Library.Main
if (isShortName)
time = new DateTime(long.Parse(timeString, System.Globalization.NumberStyles.HexNumber) * TimeSpan.TicksPerSecond, DateTimeKind.Utc).ToLocalTime();
else
time = DateTime.Parse(timeString.Replace(m_timeSeperator, ":"));
{
if (oldFilename)
time = DateTime.Parse(timeString.Replace(m.Groups["timeseparator"].Value, ":"));
else
time = DateTime.ParseExact(timeString, TIMESTAMP_FORMAT, System.Globalization.CultureInfo.InvariantCulture).ToLocalTime();
}
string extension = m.Groups["extension"].Value;
+3 -5
View File
@@ -128,7 +128,7 @@ namespace Duplicati.Library.Main
//Make sure they all have the same format
for (int i = 0; i < sources.Length; i++)
sources[i] = Core.Utility.AppendDirSeperator(sources[i]);
sources[i] = Core.Utility.AppendDirSeparator(sources[i]);
//Sanity check for duplicate folders and multiple inclusions of the same folder
for (int i = 0; i < sources.Length - 1; i++)
@@ -352,7 +352,7 @@ namespace Duplicati.Library.Main
Core.TempFile mf = new Duplicati.Library.Core.TempFile();
mf.Protected = true;
using (new Logging.Timer("Writing manifest"))
using (new Logging.Timer("Writing manifest " + backuptime.ToUniversalTime().ToString("yyyyMMddTHHmmssK")))
{
manifest.Save(mf);
@@ -415,8 +415,6 @@ namespace Duplicati.Library.Main
backend.Put(p.Key, p.Value);
m_asyncReserved -= unitcost;
m_progress += unitcost;
}
}
}
@@ -758,7 +756,7 @@ namespace Duplicati.Library.Main
flatlist.Reverse();
string prefix = Core.Utility.AppendDirSeperator(RSync.RSyncDir.CONTROL_ROOT);
string prefix = Core.Utility.AppendDirSeparator(RSync.RSyncDir.CONTROL_ROOT);
foreach (ManifestEntry be in flatlist)
{
+32 -16
View File
@@ -111,8 +111,10 @@ namespace Duplicati.Library.Main
new CommandLineArgument("thread-priority", CommandLineArgument.ArgumentType.Enumeration, Strings.Options.ThreadpriorityShort, Strings.Options.ThreadpriorityLong, "normal", null, new string[] {"high", "abovenormal", "normal", "belownormal", "low", "idle" }),
new CommandLineArgument("backup-prefix", CommandLineArgument.ArgumentType.String, Strings.Options.BackupprefixShort, Strings.Options.BackupprefixLong, "duplicati"),
new CommandLineArgument("time-separator", CommandLineArgument.ArgumentType.String, Strings.Options.TimeseparatorShort, Strings.Options.TimeseparatorLong, ":", new string[] {"time-seperator"}),
new CommandLineArgument("short-filenames", CommandLineArgument.ArgumentType.Boolean, Strings.Options.ShortfilenamesShort, Strings.Options.ShortfilenamesLong),
new CommandLineArgument("time-separator", CommandLineArgument.ArgumentType.String, Strings.Options.TimeseparatorShort, Strings.Options.TimeseparatorLong, ":", new string[] {"time-seperator"}, null, Strings.Options.TimeseparatorDeprecated),
new CommandLineArgument("short-filenames", CommandLineArgument.ArgumentType.Boolean, Strings.Options.ShortfilenamesShort, Strings.Options.ShortfilenamesLong, "false", null, null, Strings.Options.ShortfilenamesDeprecated),
new CommandLineArgument("old-filenames", CommandLineArgument.ArgumentType.Boolean, Strings.Options.OldfilenamesShort, Strings.Options.OldfilenamesLong, "false", null, null, Strings.Options.OldfilenamesDeprecated),
new CommandLineArgument("include", CommandLineArgument.ArgumentType.String, Strings.Options.IncludeShort, Strings.Options.IncludeLong),
new CommandLineArgument("exclude", CommandLineArgument.ArgumentType.String, Strings.Options.ExcludeShort, Strings.Options.ExcludeLong),
@@ -353,10 +355,15 @@ namespace Duplicati.Library.Main
}
/// <summary>
/// A value indicating if file deletes are forced
/// A value indicating if short filenames are used
/// </summary>
public bool UseShortFilenames { get { return GetBool("short-filenames"); } }
/// <summary>
/// A value indicating if old filenames are used
/// </summary>
public bool UseOldFilenames { get { return GetBool("old-filenames"); } }
/// <summary>
/// Gets the backup prefix
/// </summary>
@@ -372,19 +379,19 @@ namespace Duplicati.Library.Main
}
/// <summary>
/// Gets the process priority
/// Gets the character used to separate the time components of a file timestamp
/// </summary>
public string TimeSeperatorChar
public string TimeSeparatorChar
{
get
{
if (!m_options.ContainsKey("time-separator") || string.IsNullOrEmpty(m_options["time-separator"]))
if (!m_options.ContainsKey("time-seperator") || string.IsNullOrEmpty(m_options["time-seperator"]))
return ":";
else
return m_options["time-seperator"];
else
return m_options["time-separator"];
string key;
if (m_options.TryGetValue("time-separator", out key) && !string.IsNullOrEmpty(key))
return key;
if (m_options.TryGetValue("time-seperator", out key) && !string.IsNullOrEmpty(key))
return key;
return null;
}
}
@@ -527,7 +534,7 @@ namespace Duplicati.Library.Main
}
/// <summary>
/// A value indicating if backups are transmitted on a seperate thread
/// A value indicating if backups are transmitted on a separate thread
/// </summary>
public bool AsynchronousUpload { get { return GetBool("asynchronous-upload"); } }
@@ -705,12 +712,21 @@ namespace Duplicati.Library.Main
/// </summary>
public List<KeyValuePair<bool, Library.Interface.IGenericModule>> LoadedModules { get { return m_loadedModules; } }
/// <summary>
/// Helper method to extract boolean values.
/// If the option is not present, it it's value is false.
/// If the option is present it's value is true, unless the option's value is false, off or 0
/// </summary>
/// <param name="name">The name of the option to read</param>
/// <returns>The interpreted value of the option</returns>
private bool GetBool(string name)
{
if (!m_options.ContainsKey(name))
return false;
string value;
if (m_options.TryGetValue(name, out value))
return Core.Utility.ParseBool(value, true);
else
return Core.Utility.ParseBool(m_options[name], true);
return false;
}
}
+18 -18
View File
@@ -425,9 +425,9 @@ namespace Duplicati.Library.Main.RSync
: this(sourcefolder, stat, filter)
{
string[] prefixes = new string[] {
Core.Utility.AppendDirSeperator(COMBINED_SIGNATURE_ROOT),
Core.Utility.AppendDirSeperator(CONTENT_SIGNATURE_ROOT),
Core.Utility.AppendDirSeperator(DELTA_SIGNATURE_ROOT)
Core.Utility.AppendDirSeparator(COMBINED_SIGNATURE_ROOT),
Core.Utility.AppendDirSeparator(CONTENT_SIGNATURE_ROOT),
Core.Utility.AppendDirSeparator(DELTA_SIGNATURE_ROOT)
};
m_patches = patches;
@@ -498,7 +498,7 @@ namespace Duplicati.Library.Main.RSync
{
if (!System.IO.Path.IsPathRooted(sourcefolder[i]))
sourcefolder[i] = System.IO.Path.GetFullPath(sourcefolder[i]);
sourcefolder[i] = Core.Utility.AppendDirSeperator(sourcefolder[i]);
sourcefolder[i] = Core.Utility.AppendDirSeparator(sourcefolder[i]);
}
m_stat = stat;
m_sourcefolder = sourcefolder;
@@ -1284,7 +1284,7 @@ namespace Duplicati.Library.Main.RSync
/// <returns>True if the element is accepted, false if it is filtered</returns>
private bool FilterPredicate(string element)
{
return m_filter.ShouldInclude(System.IO.Path.DirectorySeparatorChar.ToString(), System.IO.Path.DirectorySeparatorChar.ToString() + Core.Utility.AppendDirSeperator(element));
return m_filter.ShouldInclude(Core.Utility.DirectorySeparatorString, Core.Utility.DirectorySeparatorString + Core.Utility.AppendDirSeparator(element));
}
/// <summary>
@@ -1322,7 +1322,7 @@ namespace Duplicati.Library.Main.RSync
m_folderTimestamps = new Dictionary<string, DateTime>();
for (int i = 0; i < destination.Length; i++)
destination[i] = Core.Utility.AppendDirSeperator(destination[i]);
destination[i] = Core.Utility.AppendDirSeparator(destination[i]);
bool isUtc = patch.FileExists(UTC_TIME_MARKER);
@@ -1436,7 +1436,7 @@ namespace Duplicati.Library.Main.RSync
fe = new PartialEntryRecord(patch.ReadAllLines(COMPLETED_FILE));
//Restore new files
string prefix = Core.Utility.AppendDirSeperator(CONTENT_ROOT);
string prefix = Core.Utility.AppendDirSeparator(CONTENT_ROOT);
foreach (string s in m_filter.FilterList(prefix, patch.ListFiles(prefix)))
{
@@ -1517,7 +1517,7 @@ namespace Duplicati.Library.Main.RSync
}
//Patch modfied files
prefix = Core.Utility.AppendDirSeperator(DELTA_ROOT);
prefix = Core.Utility.AppendDirSeparator(DELTA_ROOT);
foreach (string s in m_filter.FilterList(prefix, patch.ListFiles(prefix)))
{
string target = GetFullPathFromRelname(destination, s.Substring(prefix.Length));
@@ -1686,11 +1686,11 @@ namespace Duplicati.Library.Main.RSync
}
/// <summary>
/// Converts a list of filenames with / as the dir seperator to use the OS seperator.
/// Converts a list of filenames with / as the dir separator to use the OS separator.
/// </summary>
/// <param name="filenames">The list of filenames to convert</param>
/// <param name="prefix">An optional prefix that is appended to the filenames</param>
/// <returns>A list of filenames that use the prefix and the OS direseperator</returns>
/// <returns>A list of filenames that use the prefix and the OS dirseparator</returns>
public static string[] FilenamesFromPlatformIndependant(string[] filenames, string[] prefixes)
{
if (prefixes == null)
@@ -1707,10 +1707,10 @@ namespace Duplicati.Library.Main.RSync
/// <summary>
/// Converts a list of filenames with / as the dir seperator to use the OS seperator.
/// Converts a list of filenames with / as the dir separator to use the OS separator.
/// </summary>
/// <param name="filenames">The list of filenames to convert</param>
/// <returns>A list of filenames that use the prefix and the OS direseperator</returns>
/// <returns>A list of filenames that use the prefix and the OS dirseparator</returns>
public static string[] FilenamesFromPlatformIndependant(string[] filenames)
{
return FilenamesFromPlatformIndependant(filenames, null);
@@ -1768,14 +1768,14 @@ namespace Duplicati.Library.Main.RSync
List<KeyValuePair<PatchFileType, string>> files = new List<KeyValuePair<PatchFileType, string>>();
KeyValuePair<PatchFileType, string>[] signatures = new KeyValuePair<PatchFileType, string>[] {
new KeyValuePair<PatchFileType, string>(PatchFileType.AddedOrUpdatedFile, Core.Utility.AppendDirSeperator(COMBINED_SIGNATURE_ROOT)),
new KeyValuePair<PatchFileType, string>(PatchFileType.AddedFile, Core.Utility.AppendDirSeperator(CONTENT_SIGNATURE_ROOT)),
new KeyValuePair<PatchFileType, string>(PatchFileType.UpdatedFile, Core.Utility.AppendDirSeperator(DELTA_SIGNATURE_ROOT)),
new KeyValuePair<PatchFileType, string>(PatchFileType.AddedOrUpdatedFile, Core.Utility.AppendDirSeparator(COMBINED_SIGNATURE_ROOT)),
new KeyValuePair<PatchFileType, string>(PatchFileType.AddedFile, Core.Utility.AppendDirSeparator(CONTENT_SIGNATURE_ROOT)),
new KeyValuePair<PatchFileType, string>(PatchFileType.UpdatedFile, Core.Utility.AppendDirSeparator(DELTA_SIGNATURE_ROOT)),
};
string content_prefix = Core.Utility.AppendDirSeperator(CONTENT_ROOT);
string delta_prefix = Core.Utility.AppendDirSeperator(DELTA_ROOT);
string control_prefix = Core.Utility.AppendDirSeperator(CONTROL_ROOT);
string content_prefix = Core.Utility.AppendDirSeparator(CONTENT_ROOT);
string delta_prefix = Core.Utility.AppendDirSeparator(DELTA_ROOT);
string control_prefix = Core.Utility.AppendDirSeparator(CONTROL_ROOT);
Dictionary<string, bool> partials = new Dictionary<string, bool>();
foreach (Library.Interface.ICompression arch in patches)
+49 -4
View File
@@ -142,7 +142,7 @@ namespace Duplicati.Library.Main.Strings {
}
/// <summary>
/// Looks up a localized string similar to Transmit files on a seperate thread.
/// Looks up a localized string similar to Transmit files on a separate thread.
/// </summary>
internal static string AsynchronousuploadShort {
get {
@@ -609,6 +609,33 @@ namespace Duplicati.Library.Main.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to This option will be removed in the future but is included for the odd case where the new format breaks something.
/// </summary>
internal static string OldfilenamesDeprecated {
get {
return ResourceManager.GetString("OldfilenamesDeprecated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to By setting this option the filenames generated by Duplicati will contain a time separator as well as a timezone component, which is not cross platform compatible.
/// </summary>
internal static string OldfilenamesLong {
get {
return ResourceManager.GetString("OldfilenamesLong", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uses the old filename format.
/// </summary>
internal static string OldfilenamesShort {
get {
return ResourceManager.GetString("OldfilenamesShort", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Supply a passphrase that Duplicati will use to encrypt the backup volumes, making them unreadable without the passphrase. This variable can also be supplied through the environment variable PASSPHRASE..
/// </summary>
@@ -663,6 +690,15 @@ namespace Duplicati.Library.Main.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Duplicati now uses a filename format that is portable across all operating systems, so this option should not be used and will be removed in the future.
/// </summary>
internal static string ShortfilenamesDeprecated {
get {
return ResourceManager.GetString("ShortfilenamesDeprecated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to If the filesystem does not support the long filenames that Duplicati uses, this switch will change the time to be a much more compact, but hard to read format. It will also make the default prefix &quot;dpl&quot;..
/// </summary>
@@ -700,7 +736,7 @@ namespace Duplicati.Library.Main.Strings {
}
/// <summary>
/// Looks up a localized string similar to Supply a list of files seperated with semicolons, that will be added to each backup. The Duplicati GUI program uses this to store the setup database with each backup..
/// Looks up a localized string similar to Supply a list of files separated with semicolons, that will be added to each backup. The Duplicati GUI program uses this to store the setup database with each backup..
/// </summary>
internal static string SignaturecontrolfilesLong {
get {
@@ -808,7 +844,16 @@ namespace Duplicati.Library.Main.Strings {
}
/// <summary>
/// Looks up a localized string similar to Per default, Duplicati will use the colon &quot;:&quot; character to seperate the time fields in the filename. However, on some filesystem, notably windows, this character is not allowed. Use this option to use another character..
/// Looks up a localized string similar to Duplicati no longer uses a time separator for the filenames so this option is useless.
/// </summary>
internal static string TimeseparatorDeprecated {
get {
return ResourceManager.GetString("TimeseparatorDeprecated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Per default, Duplicati will use the colon &quot;:&quot; character to separate the time fields in the filename. However, on some filesystem, notably windows, this character is not allowed. Use this option to use another character..
/// </summary>
internal static string TimeseparatorLong {
get {
@@ -817,7 +862,7 @@ namespace Duplicati.Library.Main.Strings {
}
/// <summary>
/// Looks up a localized string similar to Backup volume filename timeseperator.
/// Looks up a localized string similar to Backup volume filename timeseparator.
/// </summary>
internal static string TimeseparatorShort {
get {
+19 -4
View File
@@ -121,7 +121,7 @@
<value>By supplying this option, Duplicati will transmit files, while building volumes. This can shorten the time it takes to perform a backup, but requires more diskspace.</value>
</data>
<data name="AsynchronousuploadShort" xml:space="preserve">
<value>Transmit files on a seperate thread</value>
<value>Transmit files on a separate thread</value>
</data>
<data name="AutocleanupLong" xml:space="preserve">
<value>If a backup is interrupted there will likely be partial files present on the backend. Using this flag, Duplicati will automatically remove such files when encountered.</value>
@@ -250,7 +250,7 @@
<value>A path to temporary storage</value>
</data>
<data name="SignaturecontrolfilesLong" xml:space="preserve">
<value>Supply a list of files seperated with semicolons, that will be added to each backup. The Duplicati GUI program uses this to store the setup database with each backup.</value>
<value>Supply a list of files separated with semicolons, that will be added to each backup. The Duplicati GUI program uses this to store the setup database with each backup.</value>
</data>
<data name="SignaturecontrolfilesShort" xml:space="preserve">
<value>A list of control files to embed in the backups</value>
@@ -280,10 +280,10 @@
<value>Thread priority</value>
</data>
<data name="TimeseparatorLong" xml:space="preserve">
<value>Per default, Duplicati will use the colon ":" character to seperate the time fields in the filename. However, on some filesystem, notably windows, this character is not allowed. Use this option to use another character.</value>
<value>Per default, Duplicati will use the colon ":" character to separate the time fields in the filename. However, on some filesystem, notably windows, this character is not allowed. Use this option to use another character.</value>
</data>
<data name="TimeseparatorShort" xml:space="preserve">
<value>Backup volume filename timeseperator</value>
<value>Backup volume filename timeseparator</value>
</data>
<data name="TotalsizeLong" xml:space="preserve">
<value>This option can place an upper limit on the total size of each backup. Note that if this flag is specified the backup may not contain all files, even for a full backup.</value>
@@ -384,4 +384,19 @@
<data name="ExcludeemptyfoldersShort" xml:space="preserve">
<value>Controls empty folder actions</value>
</data>
<data name="OldfilenamesDeprecated" xml:space="preserve">
<value>This option will be removed in the future but is included for the odd case where the new format breaks something</value>
</data>
<data name="OldfilenamesLong" xml:space="preserve">
<value>By setting this option the filenames generated by Duplicati will contain a time separator as well as a timezone component, which is not cross platform compatible</value>
</data>
<data name="OldfilenamesShort" xml:space="preserve">
<value>Uses the old filename format</value>
</data>
<data name="ShortfilenamesDeprecated" xml:space="preserve">
<value>Duplicati now uses a filename format that is portable across all operating systems, so this option should not be used and will be removed in the future</value>
</data>
<data name="TimeseparatorDeprecated" xml:space="preserve">
<value>Duplicati no longer uses a time separator for the filenames so this option is useless</value>
</data>
</root>
+4 -4
View File
@@ -46,7 +46,7 @@ namespace Duplicati.Library.Snapshots
public SnapShot(string path)
{
m_name = string.Format("duplicati-{0}", Guid.NewGuid().ToString());
m_realDir = Core.Utility.AppendDirSeperator(path);
m_realDir = Core.Utility.AppendDirSeparator(path);
GetVolumeName(m_realDir);
}
@@ -172,7 +172,7 @@ namespace Duplicati.Library.Snapshots
if (string.IsNullOrEmpty(m_mountPoint) || m_mountPoint.Trim().Length == 0)
throw new Exception(string.Format(Strings.LinuxSnapshot.ScriptOutputError, "mountpoint", output));
m_mountPoint = Core.Utility.AppendDirSeperator(m_mountPoint);
m_mountPoint = Core.Utility.AppendDirSeparator(m_mountPoint);
}
/// <summary>
@@ -187,7 +187,7 @@ namespace Duplicati.Library.Snapshots
throw new InvalidOperationException();
//Create the snapshot volume
string output = ExecuteCommand("create-lvm-snapshot.sh", string.Format("\"{0}\" \"{1}\" \"{2}\"", m_name, m_device, Core.Utility.AppendDirSeperator(Core.TempFolder.SystemTempPath)), 0);
string output = ExecuteCommand("create-lvm-snapshot.sh", string.Format("\"{0}\" \"{1}\" \"{2}\"", m_name, m_device, Core.Utility.AppendDirSeparator(Core.TempFolder.SystemTempPath)), 0);
System.Text.RegularExpressions.Regex rex = new System.Text.RegularExpressions.Regex("tmpdir=\"(?<tmpdir>[^\"]+)\"");
System.Text.RegularExpressions.Match m = rex.Match(output);
@@ -200,7 +200,7 @@ namespace Duplicati.Library.Snapshots
if (!System.IO.Directory.Exists(m_tmpDir))
throw new Exception(string.Format(Strings.LinuxSnapshot.MountFolderMissingError, m_tmpDir, output));
m_tmpDir = Core.Utility.AppendDirSeperator(m_tmpDir);
m_tmpDir = Core.Utility.AppendDirSeparator(m_tmpDir);
}
#region IDisposable Members
+1 -1
View File
@@ -48,7 +48,7 @@ namespace Duplicati.Library.Snapshots
{
m_sourcefolders = new string[folders.Length];
for (int i = 0; i < m_sourcefolders.Length; i++)
m_sourcefolders[i] = Core.Utility.AppendDirSeperator(folders[i]);
m_sourcefolders[i] = Core.Utility.AppendDirSeparator(folders[i]);
m_attemptDirtyAccess = attemptDirtyAccess;
m_attemptBackupRead = false;
@@ -58,7 +58,7 @@ namespace Duplicati.Library.Snapshots
m_sourcepaths = new string[sourcepaths.Length];
for(int i = 0; i < m_sourcepaths.Length; i++)
m_sourcepaths[i] = Core.Utility.AppendDirSeperator(sourcepaths[i]);
m_sourcepaths[i] = Core.Utility.AppendDirSeparator(sourcepaths[i]);
try
{
@@ -170,8 +170,8 @@ namespace Duplicati.Library.Snapshots
/// <returns>A list of non-shadow paths</returns>
private string[] ListFolders(string folder)
{
string root = Core.Utility.AppendDirSeperator(Path.GetPathRoot(folder));
string volumePath = Core.Utility.AppendDirSeperator(GetSnapshotPath(root));
string root = Core.Utility.AppendDirSeparator(Path.GetPathRoot(folder));
string volumePath = Core.Utility.AppendDirSeparator(GetSnapshotPath(root));
string[] tmp = Alphaleonis.Win32.Filesystem.Directory.GetDirectories(GetSnapshotPath(folder));
for (int i = 0; i < tmp.Length; i++)
@@ -188,8 +188,8 @@ namespace Duplicati.Library.Snapshots
/// <returns>A list of non-shadow paths</returns>
private string[] ListFiles(string folder)
{
string root = Core.Utility.AppendDirSeperator(Path.GetPathRoot(folder));
string volumePath = Core.Utility.AppendDirSeperator(GetSnapshotPath(root));
string root = Core.Utility.AppendDirSeparator(Path.GetPathRoot(folder));
string volumePath = Core.Utility.AppendDirSeparator(GetSnapshotPath(root));
string[] tmp = Alphaleonis.Win32.Filesystem.Directory.GetFiles(GetSnapshotPath(folder));
for (int i = 0; i < tmp.Length; i++)