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
344 lines
15 KiB
C#
344 lines
15 KiB
C#
#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.Collections.Specialized;
|
|
using System.Text;
|
|
|
|
|
|
namespace Duplicati.Datamodel
|
|
{
|
|
public partial class Task
|
|
{
|
|
public Task()
|
|
{
|
|
this.AfterDataCommit += new System.Data.LightDatamodel.DataConnectionEventHandler(Task_AfterDataCommit);
|
|
}
|
|
|
|
void Task_AfterDataCommit(object sender, System.Data.LightDatamodel.DataActions action)
|
|
{
|
|
if (action != System.Data.LightDatamodel.DataActions.Fetch)
|
|
{
|
|
m_backendSettings = null;
|
|
m_extensionSettings = null;
|
|
}
|
|
}
|
|
|
|
private SettingsHelper<BackendSetting, string, string> m_backendSettings;
|
|
private SettingsHelper<TaskExtension, string, string> m_extensionSettings;
|
|
|
|
private SettingsHelper<TaskOverride, string, string> m_taskOverrides;
|
|
|
|
private SettingsHelper<EncryptionSetting, string, string> m_encryptionSettings;
|
|
private SettingsHelper<CompressionSetting, string, string> m_compressionSettings;
|
|
|
|
public IDictionary<string, string> BackendSettingsLookup
|
|
{
|
|
get
|
|
{
|
|
//Extra check because the datamodel copies the collection between contexts... not nice
|
|
if (m_backendSettings == null || m_backendSettings.DataParent != this.DataParent || m_backendSettings.Collection != this.BackendSettings)
|
|
m_backendSettings = new SettingsHelper<BackendSetting, string, string>(this.DataParent, this.BackendSettings, "Name", "Value");
|
|
|
|
return m_backendSettings;
|
|
}
|
|
}
|
|
|
|
public IDictionary<string, string> TaskExtensionsLookup
|
|
{
|
|
get
|
|
{
|
|
//Extra check because the datamodel copies the collection between contexts... not nice
|
|
if (m_extensionSettings == null || m_extensionSettings.DataParent != this.DataParent || m_extensionSettings.Collection != this.TaskExtensions)
|
|
m_extensionSettings = new SettingsHelper<TaskExtension, string, string>(this.DataParent, this.TaskExtensions, "Name", "Value");
|
|
|
|
return m_extensionSettings;
|
|
}
|
|
}
|
|
|
|
public IDictionary<string, string> TaskOverridesLookup
|
|
{
|
|
get
|
|
{
|
|
//Extra check because the datamodel copies the collection between contexts... not nice
|
|
if (m_taskOverrides == null || m_taskOverrides.DataParent != this.DataParent || m_taskOverrides.Collection != this.TaskOverrides)
|
|
m_taskOverrides = new SettingsHelper<TaskOverride, string, string>(this.DataParent, this.TaskOverrides, "Name", "Value");
|
|
|
|
return m_taskOverrides;
|
|
}
|
|
}
|
|
|
|
public IDictionary<string, string> EncryptionSettingsLookup
|
|
{
|
|
get
|
|
{
|
|
//Extra check because the datamodel copies the collection between contexts... not nice
|
|
if (m_encryptionSettings == null || m_encryptionSettings.DataParent != this.DataParent || m_encryptionSettings.Collection != this.EncryptionSettings)
|
|
m_encryptionSettings = new SettingsHelper<EncryptionSetting, string, string>(this.DataParent, this.EncryptionSettings, "Name", "Value");
|
|
|
|
return m_encryptionSettings;
|
|
}
|
|
}
|
|
|
|
public IDictionary<string, string> CompressionSettingsLookup
|
|
{
|
|
get
|
|
{
|
|
//Extra check because the datamodel copies the collection between contexts... not nice
|
|
if (m_compressionSettings == null || m_compressionSettings.DataParent != this.DataParent || m_compressionSettings.Collection != this.CompressionSettings)
|
|
m_compressionSettings = new SettingsHelper<CompressionSetting, string, string>(this.DataParent, this.CompressionSettings, "Name", "Value");
|
|
|
|
return m_compressionSettings;
|
|
}
|
|
}
|
|
|
|
public TaskExtensionWrapper Extensions
|
|
{
|
|
get { return new TaskExtensionWrapper(this); }
|
|
}
|
|
|
|
public string EncodedFilter
|
|
{
|
|
get
|
|
{
|
|
if (this.Filters.Count <= 0)
|
|
return "";
|
|
|
|
List<KeyValuePair<bool, string>> filters = new List<KeyValuePair<bool, string>>();
|
|
foreach (TaskFilter f in this.SortedFilters)
|
|
filters.Add(new KeyValuePair<bool, string>(f.Include, f.Filter));
|
|
|
|
return Library.Core.FilenameFilter.EncodeAsFilter(filters);
|
|
}
|
|
set
|
|
{
|
|
if (value == this.EncodedFilter)
|
|
return;
|
|
|
|
//Delete previous ones
|
|
this.SortedFilters = new TaskFilter[0];
|
|
|
|
List<TaskFilter> filters = new List<TaskFilter>();
|
|
foreach (KeyValuePair<bool, string> f in Library.Core.FilenameFilter.DecodeFilter(value))
|
|
{
|
|
TaskFilter tf = this.DataParent.Add<TaskFilter>();
|
|
tf.Filter = f.Value;
|
|
tf.Include = f.Key;
|
|
filters.Add(tf);
|
|
}
|
|
|
|
this.SortedFilters = filters.ToArray();
|
|
}
|
|
}
|
|
|
|
public bool ExistsInDb
|
|
{
|
|
get { return this.ID > 0; }
|
|
}
|
|
|
|
|
|
public TaskFilter[] SortedFilters
|
|
{
|
|
get
|
|
{
|
|
return System.Data.LightDatamodel.Query.Parse("ORDER BY SortOrder").EvaluateList<TaskFilter>(this.Filters).ToArray();
|
|
}
|
|
set
|
|
{
|
|
foreach (TaskFilter t in this.SortedFilters)
|
|
if (Array.IndexOf<TaskFilter>(value, t) >= 0)
|
|
this.Filters.Remove(t);
|
|
else
|
|
t.DataParent.DeleteObject(t);
|
|
|
|
int index = 0;
|
|
foreach (TaskFilter t in value)
|
|
{
|
|
t.SortOrder = index++;
|
|
this.Filters.Add(t);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public class TaskExtensionWrapper
|
|
{
|
|
private const string MAX_UPLOAD_SIZE = "Max Upload Size";
|
|
private const string UPLOAD_BANDWIDTH = "Upload Bandwidth";
|
|
private const string DOWNLOAD_BANDWIDTH = "Download Bandwidth";
|
|
private const string VOLUME_SIZE = "Volume Size";
|
|
private const string THREAD_PRIORITY = "Thread Priority";
|
|
private const string ASYNC_TRANSFER = "Async Transfer";
|
|
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 SELECTFILES_VERSION = "Select Files - Version";
|
|
private const string SELECTFILES_USESIMPLEMODE = "Select Files - Use Simple Mode";
|
|
private const string SELECTFILES_INCLUDEDOCUMENTS = "Select Files - Include Documents";
|
|
private const string SELECTFILES_INCLUDEDESKTOP = "Select Files - Include Desktop";
|
|
private const string SELECTFILES_INCLUDEMUSIC = "Select Files - Include Music";
|
|
private const string SELECTFILES_INCLUDEIMAGES = "Select Files - Include Images";
|
|
private const string SELECTFILES_INCLUDEAPPDATA = "Select Files - Include AppData";
|
|
|
|
private const string SELECTWHEN_WARNEDNOSCHEDULE = "Select When - Warned No Schedule";
|
|
private const string SELECTWHEN_WARNEDTOOMANYINCREMENTALS = "Select When - Warned Too Many Incrementals";
|
|
private const string SELECTWHEN_WARNEDNOINCREMENTALS = "Select When - Warned No Incrementals";
|
|
|
|
private const string PASSWORDSETTINGS_WARNEDNOPASSWORD = "Password Settings - Warned No Password";
|
|
|
|
private const string CLEANUPSETTINGS_WARNEDNOCLEANUP = "Cleanup Settings - Warned No Cleanup";
|
|
|
|
private Task m_owner;
|
|
|
|
public TaskExtensionWrapper(Task owner)
|
|
{
|
|
m_owner = owner;
|
|
}
|
|
|
|
public string MaxUploadSize
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[MAX_UPLOAD_SIZE]; }
|
|
set { m_owner.TaskExtensionsLookup[MAX_UPLOAD_SIZE] = value; }
|
|
}
|
|
|
|
public string UploadBandwidth
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[UPLOAD_BANDWIDTH]; }
|
|
set { m_owner.TaskExtensionsLookup[UPLOAD_BANDWIDTH] = value; }
|
|
}
|
|
|
|
public string DownloadBandwidth
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[DOWNLOAD_BANDWIDTH]; }
|
|
set { m_owner.TaskExtensionsLookup[DOWNLOAD_BANDWIDTH] = value; }
|
|
}
|
|
|
|
public string VolumeSize
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[VOLUME_SIZE]; }
|
|
set { m_owner.TaskExtensionsLookup[VOLUME_SIZE] = value; }
|
|
}
|
|
|
|
public string ThreadPriority
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[THREAD_PRIORITY]; }
|
|
set { m_owner.TaskExtensionsLookup[THREAD_PRIORITY] = value; }
|
|
}
|
|
|
|
public bool AsyncTransfer
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[ASYNC_TRANSFER], false); }
|
|
set { m_owner.TaskExtensionsLookup[ASYNC_TRANSFER] = value.ToString(); }
|
|
}
|
|
|
|
public bool IncludeSetup
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[INCLUDE_SETUP], true); }
|
|
set { m_owner.TaskExtensionsLookup[INCLUDE_SETUP] = value.ToString(); }
|
|
}
|
|
|
|
public bool IgnoreTimestamps
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[IGNORE_TIMESTAMPS], false); }
|
|
set { m_owner.TaskExtensionsLookup[IGNORE_TIMESTAMPS] = value.ToString(); }
|
|
}
|
|
|
|
public string FileSizeLimit
|
|
{
|
|
get { return m_owner.TaskExtensionsLookup[FILE_SIZE_LIMIT]; }
|
|
set { m_owner.TaskExtensionsLookup[FILE_SIZE_LIMIT] = value; }
|
|
}
|
|
|
|
public int SelectFiles_Version
|
|
{
|
|
get { return string.IsNullOrEmpty(m_owner.TaskExtensionsLookup[SELECTFILES_VERSION]) ? 1 : int.Parse(m_owner.TaskExtensionsLookup[SELECTFILES_VERSION]); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_VERSION] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_UseSimpleMode
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_USESIMPLEMODE], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_USESIMPLEMODE] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_IncludeDocuments
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEDOCUMENTS], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEDOCUMENTS] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_IncludeDesktop
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEDESKTOP], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEDESKTOP] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_IncludeMusic
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEMUSIC], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEMUSIC] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_IncludeImages
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEIMAGES], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEIMAGES] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectFiles_IncludeAppData
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEAPPDATA], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTFILES_INCLUDEAPPDATA] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectWhen_WarnedNoSchedule
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDNOSCHEDULE], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDNOSCHEDULE] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectWhen_WarnedNoIncrementals
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDNOINCREMENTALS], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDNOINCREMENTALS] = value.ToString(); }
|
|
}
|
|
|
|
public bool SelectWhen_WarnedTooManyIncrementals
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDTOOMANYINCREMENTALS], false); }
|
|
set { m_owner.TaskExtensionsLookup[SELECTWHEN_WARNEDTOOMANYINCREMENTALS] = value.ToString(); }
|
|
}
|
|
|
|
public bool PasswordSettings_WarnedNoPassword
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[PASSWORDSETTINGS_WARNEDNOPASSWORD], false); }
|
|
set { m_owner.TaskExtensionsLookup[PASSWORDSETTINGS_WARNEDNOPASSWORD] = value.ToString(); }
|
|
}
|
|
|
|
public bool CleanupSettings_WarnedNoCleanup
|
|
{
|
|
get { return Duplicati.Library.Core.Utility.ParseBool(m_owner.TaskExtensionsLookup[CLEANUPSETTINGS_WARNEDNOCLEANUP], false); }
|
|
set { m_owner.TaskExtensionsLookup[CLEANUPSETTINGS_WARNEDNOCLEANUP] = value.ToString(); }
|
|
}
|
|
}
|
|
}
|
|
}
|